From 39eb19ed3572749add957f8f980f4b50549192a2 Mon Sep 17 00:00:00 2001 From: Gleb Popov <6yearold@gmail.com> Date: Sat, 22 Sep 2018 22:36:40 +0300 Subject: [PATCH 001/242] Fix various tests on FreeBSD. --- test/core/iomgr/socket_utils_test.cc | 1 + test/cpp/interop/interop_test.cc | 4 ---- test/cpp/naming/address_sorting_test.cc | 1 + test/cpp/naming/resolver_component_tests_runner_invoker.cc | 4 ++++ test/cpp/qps/json_run_localhost.cc | 4 ++++ 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/test/core/iomgr/socket_utils_test.cc b/test/core/iomgr/socket_utils_test.cc index a21f3fac62e..8c5b6f3db9f 100644 --- a/test/core/iomgr/socket_utils_test.cc +++ b/test/core/iomgr/socket_utils_test.cc @@ -24,6 +24,7 @@ #include "src/core/lib/iomgr/socket_utils_posix.h" #include +#include #include #include diff --git a/test/cpp/interop/interop_test.cc b/test/cpp/interop/interop_test.cc index ae155b65f95..8e45b877212 100644 --- a/test/cpp/interop/interop_test.cc +++ b/test/cpp/interop/interop_test.cc @@ -16,10 +16,6 @@ * */ -#ifndef _POSIX_SOURCE -#define _POSIX_SOURCE -#endif - #include #include #include diff --git a/test/cpp/naming/address_sorting_test.cc b/test/cpp/naming/address_sorting_test.cc index fc6721d0ba8..37fd408cc7a 100644 --- a/test/cpp/naming/address_sorting_test.cc +++ b/test/cpp/naming/address_sorting_test.cc @@ -51,6 +51,7 @@ #ifndef GPR_WINDOWS #include +#include #include #endif diff --git a/test/cpp/naming/resolver_component_tests_runner_invoker.cc b/test/cpp/naming/resolver_component_tests_runner_invoker.cc index 68be00a67d6..d8f7100a284 100644 --- a/test/cpp/naming/resolver_component_tests_runner_invoker.cc +++ b/test/cpp/naming/resolver_component_tests_runner_invoker.cc @@ -29,6 +29,10 @@ #include #include +#ifdef __FreeBSD__ +#include +#endif + #include "test/cpp/util/subprocess.h" #include "test/cpp/util/test_config.h" diff --git a/test/cpp/qps/json_run_localhost.cc b/test/cpp/qps/json_run_localhost.cc index 948c3088e67..42cc9e0ed76 100644 --- a/test/cpp/qps/json_run_localhost.cc +++ b/test/cpp/qps/json_run_localhost.cc @@ -24,6 +24,10 @@ #include #include +#ifdef __FreeBSD__ +#include +#endif + #include #include "src/core/lib/gpr/env.h" From e2f3741c7434facf2438197d9865af5679f667bc Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 19 Sep 2018 11:53:55 -0700 Subject: [PATCH 002/242] Changed podspec templates and Podfile for test --- include/grpc/impl/codegen/port_platform.h | 64 +++++++++++------------ src/objective-c/GRPCClient/GRPCCall.m | 1 + src/objective-c/tests/Podfile | 30 ++--------- templates/gRPC-Core.podspec.template | 11 ++-- templates/gRPC-ProtoRPC.podspec.template | 6 +-- templates/gRPC.podspec.template | 7 +-- 6 files changed, 43 insertions(+), 76 deletions(-) diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index 031c0c36aef..46d831395da 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -185,38 +185,39 @@ #define _BSD_SOURCE #endif #if TARGET_OS_IPHONE -#define GPR_PLATFORM_STRING "ios" -#define GPR_CPU_IPHONE 1 -#define GPR_PTHREAD_TLS 1 + #define GPR_PLATFORM_STRING "ios" + #define GPR_CPU_IPHONE 1 + #define GPR_PTHREAD_TLS 1 + #define GRPC_CFSTREAM 1 #else /* TARGET_OS_IPHONE */ -#define GPR_PLATFORM_STRING "osx" -#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED -#if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_7 -#define GPR_CPU_IPHONE 1 -#define GPR_PTHREAD_TLS 1 -#else /* __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_7 */ -#define GPR_CPU_POSIX 1 -/* TODO(vjpai): there is a reported issue in bazel build for Mac where __thread - in a header is currently not working (bazelbuild/bazel#4341). Remove - the following conditional and use GPR_GCC_TLS when that is fixed */ -#ifndef GRPC_BAZEL_BUILD -#define GPR_GCC_TLS 1 -#else /* GRPC_BAZEL_BUILD */ -#define GPR_PTHREAD_TLS 1 -#endif /* GRPC_BAZEL_BUILD */ -#define GPR_APPLE_PTHREAD_NAME 1 -#endif -#else /* __MAC_OS_X_VERSION_MIN_REQUIRED */ -#define GPR_CPU_POSIX 1 -/* TODO(vjpai): Remove the following conditional and use only GPR_GCC_TLS - when bazelbuild/bazel#4341 is fixed */ -#ifndef GRPC_BAZEL_BUILD -#define GPR_GCC_TLS 1 -#else /* GRPC_BAZEL_BUILD */ -#define GPR_PTHREAD_TLS 1 -#endif /* GRPC_BAZEL_BUILD */ -#endif -#define GPR_POSIX_CRASH_HANDLER 1 + #define GPR_PLATFORM_STRING "osx" + #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED + #if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_7 + #define GPR_CPU_IPHONE 1 + #define GPR_PTHREAD_TLS 1 + #else /* __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_7 */ + #define GPR_CPU_POSIX 1 + /* TODO(vjpai): there is a reported issue in bazel build for Mac where __thread + in a header is currently not working (bazelbuild/bazel#4341). Remove + the following conditional and use GPR_GCC_TLS when that is fixed */ + #ifndef GRPC_BAZEL_BUILD + #define GPR_GCC_TLS 1 + #else /* GRPC_BAZEL_BUILD */ + #define GPR_PTHREAD_TLS 1 + #endif /* GRPC_BAZEL_BUILD */ + #define GPR_APPLE_PTHREAD_NAME 1 + #endif + #else /* __MAC_OS_X_VERSION_MIN_REQUIRED */ + #define GPR_CPU_POSIX 1 + /* TODO(vjpai): Remove the following conditional and use only GPR_GCC_TLS + when bazelbuild/bazel#4341 is fixed */ + #ifndef GRPC_BAZEL_BUILD + #define GPR_GCC_TLS 1 + #else /* GRPC_BAZEL_BUILD */ + #define GPR_PTHREAD_TLS 1 + #endif /* GRPC_BAZEL_BUILD */ + #endif + #define GPR_POSIX_CRASH_HANDLER 1 #endif #define GPR_APPLE 1 #define GPR_GCC_ATOMIC 1 @@ -228,7 +229,6 @@ #define GPR_POSIX_SYNC 1 #define GPR_POSIX_TIME 1 #define GPR_GETPID_IN_UNISTD_H 1 -/* TODO(mxyan): Remove when CFStream becomes default */ #ifndef GRPC_CFSTREAM #define GPR_SUPPORT_CHANNELS_FROM_FD 1 #endif diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 084fbdeb491..5a6b13d75b0 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -121,6 +121,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; // Guarantees the code in {} block is invoked only once. See ref at: // https://developer.apple.com/documentation/objectivec/nsobject/1418639-initialize?language=objc if (self == [GRPCCall self]) { + setenv(kCFStreamVarName, "1", 1); grpc_init(); callFlags = [NSMutableDictionary dictionary]; } diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile index 5d2f1340daa..bc0ba2f2b75 100644 --- a/src/objective-c/tests/Podfile +++ b/src/objective-c/tests/Podfile @@ -15,6 +15,9 @@ GRPC_LOCAL_SRC = '../../..' InteropTestsLocalCleartext InteropTestsRemoteWithCronet UnitTests + InteropTestsRemoteCFStream + InteropTestsLocalSSLCFStream + InteropTestsLocalCleartextCFStream ).each do |target_name| target target_name do pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf", :inhibit_warnings => true @@ -37,27 +40,6 @@ GRPC_LOCAL_SRC = '../../..' end end -%w( - InteropTestsRemoteCFStream - InteropTestsLocalSSLCFStream - InteropTestsLocalCleartextCFStream -).each do |target_name| - target target_name do - pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf", :inhibit_warnings => true - - pod '!ProtoCompiler', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" - pod '!ProtoCompiler-gRPCPlugin', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" - - pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true - - pod 'gRPC/CFStream', :path => GRPC_LOCAL_SRC - pod 'gRPC-Core/CFStream-Implementation', :path => GRPC_LOCAL_SRC - pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC - pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC, :inhibit_warnings => true - pod 'RemoteTest', :path => "RemoteTestClient", :inhibit_warnings => true - end -end - %w( CoreCronetEnd2EndTests CronetUnitTests @@ -118,11 +100,7 @@ post_install do |installer| # GPR_UNREACHABLE_CODE causes "Control may reach end of non-void # function" warning config.build_settings['GCC_WARN_ABOUT_RETURN_TYPE'] = 'NO' - if target.name.include?('CFStream') - config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_CFSTREAM=1' - else - config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_CRONET_WITH_PACKET_COALESCING=1' - end + config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_CRONET_WITH_PACKET_COALESCING=1' end end diff --git a/templates/gRPC-Core.podspec.template b/templates/gRPC-Core.podspec.template index 461e8b767ff..91726ab03da 100644 --- a/templates/gRPC-Core.podspec.template +++ b/templates/gRPC-Core.podspec.template @@ -179,19 +179,14 @@ ss.compiler_flags = '-DGRPC_SHADOW_BORINGSSL_SYMBOLS' # To save you from scrolling, this is the last part of the podspec. - ss.source_files = ${ruby_multiline_list(grpc_private_files(libs), 22)} + ss.source_files = ${ruby_multiline_list(grpc_private_files(libs) + cfstream_private_files(filegroups), 22)} - ss.private_header_files = ${ruby_multiline_list(grpc_private_headers(libs), 30)} + ss.private_header_files = ${ruby_multiline_list(grpc_private_headers(libs) + cfstream_private_headers(filegroups), 30)} end + # CFStream is now default. Leaving this subspec only for compatibility purpose. s.subspec 'CFStream-Implementation' do |ss| - ss.header_mappings_dir = '.' ss.dependency "#{s.name}/Implementation", version - ss.pod_target_xcconfig = { - 'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1' - } - ss.source_files = ${ruby_multiline_list(cfstream_private_files(filegroups), 22)} - ss.private_header_files = ${ruby_multiline_list(cfstream_private_headers(filegroups), 30)} end s.subspec 'Cronet-Interface' do |ss| diff --git a/templates/gRPC-ProtoRPC.podspec.template b/templates/gRPC-ProtoRPC.podspec.template index 96966784f18..cfc4b60b2eb 100644 --- a/templates/gRPC-ProtoRPC.podspec.template +++ b/templates/gRPC-ProtoRPC.podspec.template @@ -54,12 +54,10 @@ ss.source_files = "#{src_dir}/*.{h,m}" end + + # CFStream is now default. Leaving this subspec only for compatibility purpose. s.subspec 'CFStream' do |ss| - ss.dependency 'gRPC/CFStream', version ss.dependency "#{s.name}/Main", version - ss.pod_target_xcconfig = { - 'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1' - } end s.pod_target_xcconfig = { diff --git a/templates/gRPC.podspec.template b/templates/gRPC.podspec.template index a3190c2d8e6..c8054e1d1d0 100644 --- a/templates/gRPC.podspec.template +++ b/templates/gRPC.podspec.template @@ -65,14 +65,9 @@ ss.dependency 'gRPC-Core', version end - # This subspec is mutually exclusive with the `Main` subspec + # CFStream is now default. Leaving this subspec only for compatibility purpose. s.subspec 'CFStream' do |ss| - ss.dependency 'gRPC-Core/CFStream-Implementation', version ss.dependency "#{s.name}/Main", version - - ss.pod_target_xcconfig = { - 'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1' - } end s.subspec 'GID' do |ss| From acf3a72e243a37b68f4c0da7e72d61a62127ba75 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 14 Dec 2018 13:46:53 -0800 Subject: [PATCH 003/242] CFStream use serial dispatch queue --- src/core/lib/iomgr/cfstream_handle.cc | 98 ++++++++++++--------------- src/core/lib/iomgr/cfstream_handle.h | 2 + 2 files changed, 46 insertions(+), 54 deletions(-) diff --git a/src/core/lib/iomgr/cfstream_handle.cc b/src/core/lib/iomgr/cfstream_handle.cc index 827fd24831e..bb402f96cf5 100644 --- a/src/core/lib/iomgr/cfstream_handle.cc +++ b/src/core/lib/iomgr/cfstream_handle.cc @@ -52,62 +52,53 @@ CFStreamHandle* CFStreamHandle::CreateStreamHandle( void CFStreamHandle::ReadCallback(CFReadStreamRef stream, CFStreamEventType type, void* client_callback_info) { + grpc_core::ExecCtx exec_ctx; CFStreamHandle* handle = static_cast(client_callback_info); - CFSTREAM_HANDLE_REF(handle, "read callback"); - dispatch_async( - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - grpc_core::ExecCtx exec_ctx; - if (grpc_tcp_trace.enabled()) { - gpr_log(GPR_DEBUG, "CFStream ReadCallback (%p, %p, %lu, %p)", handle, - stream, type, client_callback_info); - } - switch (type) { - case kCFStreamEventOpenCompleted: - handle->open_event_.SetReady(); - break; - case kCFStreamEventHasBytesAvailable: - case kCFStreamEventEndEncountered: - handle->read_event_.SetReady(); - break; - case kCFStreamEventErrorOccurred: - handle->open_event_.SetReady(); - handle->read_event_.SetReady(); - break; - default: - GPR_UNREACHABLE_CODE(return ); - } - CFSTREAM_HANDLE_UNREF(handle, "read callback"); - }); + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_DEBUG, "CFStream ReadCallback (%p, %p, %lu, %p)", handle, + stream, type, client_callback_info); + } + switch (type) { + case kCFStreamEventOpenCompleted: + handle->open_event_.SetReady(); + break; + case kCFStreamEventHasBytesAvailable: + case kCFStreamEventEndEncountered: + handle->read_event_.SetReady(); + break; + case kCFStreamEventErrorOccurred: + handle->open_event_.SetReady(); + handle->read_event_.SetReady(); + break; + default: + GPR_UNREACHABLE_CODE(return ); + } } void CFStreamHandle::WriteCallback(CFWriteStreamRef stream, CFStreamEventType type, void* clientCallBackInfo) { + grpc_core::ExecCtx exec_ctx; CFStreamHandle* handle = static_cast(clientCallBackInfo); - CFSTREAM_HANDLE_REF(handle, "write callback"); - dispatch_async( - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - grpc_core::ExecCtx exec_ctx; - if (grpc_tcp_trace.enabled()) { - gpr_log(GPR_DEBUG, "CFStream WriteCallback (%p, %p, %lu, %p)", handle, - stream, type, clientCallBackInfo); - } - switch (type) { - case kCFStreamEventOpenCompleted: - handle->open_event_.SetReady(); - break; - case kCFStreamEventCanAcceptBytes: - case kCFStreamEventEndEncountered: - handle->write_event_.SetReady(); - break; - case kCFStreamEventErrorOccurred: - handle->open_event_.SetReady(); - handle->write_event_.SetReady(); - break; - default: - GPR_UNREACHABLE_CODE(return ); - } - CFSTREAM_HANDLE_UNREF(handle, "write callback"); - }); + printf("** CFStreamHandle::WriteCallback\n"); + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_DEBUG, "CFStream WriteCallback (%p, %p, %lu, %p)", handle, + stream, type, clientCallBackInfo); + } + switch (type) { + case kCFStreamEventOpenCompleted: + handle->open_event_.SetReady(); + break; + case kCFStreamEventCanAcceptBytes: + case kCFStreamEventEndEncountered: + handle->write_event_.SetReady(); + break; + case kCFStreamEventErrorOccurred: + handle->open_event_.SetReady(); + handle->write_event_.SetReady(); + break; + default: + GPR_UNREACHABLE_CODE(return ); + } } CFStreamHandle::CFStreamHandle(CFReadStreamRef read_stream, @@ -116,6 +107,7 @@ CFStreamHandle::CFStreamHandle(CFReadStreamRef read_stream, open_event_.InitEvent(); read_event_.InitEvent(); write_event_.InitEvent(); + dispatch_queue_ = dispatch_queue_create(nullptr, DISPATCH_QUEUE_SERIAL); CFStreamClientContext ctx = {0, static_cast(this), CFStreamHandle::Retain, CFStreamHandle::Release, nil}; @@ -129,10 +121,8 @@ CFStreamHandle::CFStreamHandle(CFReadStreamRef read_stream, kCFStreamEventOpenCompleted | kCFStreamEventCanAcceptBytes | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, CFStreamHandle::WriteCallback, &ctx); - CFReadStreamScheduleWithRunLoop(read_stream, CFRunLoopGetMain(), - kCFRunLoopCommonModes); - CFWriteStreamScheduleWithRunLoop(write_stream, CFRunLoopGetMain(), - kCFRunLoopCommonModes); + CFReadStreamSetDispatchQueue(read_stream, dispatch_queue_); + CFWriteStreamSetDispatchQueue(write_stream, dispatch_queue_); } CFStreamHandle::~CFStreamHandle() { diff --git a/src/core/lib/iomgr/cfstream_handle.h b/src/core/lib/iomgr/cfstream_handle.h index 4258e72431c..93ec5f044bb 100644 --- a/src/core/lib/iomgr/cfstream_handle.h +++ b/src/core/lib/iomgr/cfstream_handle.h @@ -62,6 +62,8 @@ class CFStreamHandle final { grpc_core::LockfreeEvent read_event_; grpc_core::LockfreeEvent write_event_; + dispatch_queue_t dispatch_queue_; + gpr_refcount refcount_; }; From a7643b1f424aac7481a0f7db615cc24d36724736 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 27 Dec 2018 11:40:17 -0800 Subject: [PATCH 004/242] build projects --- gRPC-Core.podspec | 35 ++++++++++++++++------------------- gRPC-ProtoRPC.podspec | 6 ++---- gRPC.podspec | 7 +------ 3 files changed, 19 insertions(+), 29 deletions(-) diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index f873bc693bc..b5b8aef2225 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -846,7 +846,15 @@ Pod::Spec.new do |s| 'src/core/ext/filters/http/client_authority_filter.cc', 'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc', 'src/core/ext/filters/workarounds/workaround_utils.cc', - 'src/core/plugin_registry/grpc_plugin_registry.cc' + 'src/core/plugin_registry/grpc_plugin_registry.cc', + 'src/core/lib/iomgr/cfstream_handle.cc', + 'src/core/lib/iomgr/endpoint_cfstream.cc', + 'src/core/lib/iomgr/error_cfstream.cc', + 'src/core/lib/iomgr/iomgr_posix_cfstream.cc', + 'src/core/lib/iomgr/tcp_client_cfstream.cc', + 'src/core/lib/iomgr/cfstream_handle.h', + 'src/core/lib/iomgr/endpoint_cfstream.h', + 'src/core/lib/iomgr/error_cfstream.h' ss.private_header_files = 'src/core/lib/gpr/alloc.h', 'src/core/lib/gpr/arena.h', @@ -1148,28 +1156,17 @@ Pod::Spec.new do |s| 'src/core/ext/filters/message_size/message_size_filter.h', 'src/core/ext/filters/http/client_authority_filter.h', 'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h', - 'src/core/ext/filters/workarounds/workaround_utils.h' - end - - s.subspec 'CFStream-Implementation' do |ss| - ss.header_mappings_dir = '.' - ss.dependency "#{s.name}/Implementation", version - ss.pod_target_xcconfig = { - 'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1' - } - ss.source_files = 'src/core/lib/iomgr/cfstream_handle.cc', - 'src/core/lib/iomgr/endpoint_cfstream.cc', - 'src/core/lib/iomgr/error_cfstream.cc', - 'src/core/lib/iomgr/iomgr_posix_cfstream.cc', - 'src/core/lib/iomgr/tcp_client_cfstream.cc', - 'src/core/lib/iomgr/cfstream_handle.h', - 'src/core/lib/iomgr/endpoint_cfstream.h', - 'src/core/lib/iomgr/error_cfstream.h' - ss.private_header_files = 'src/core/lib/iomgr/cfstream_handle.h', + 'src/core/ext/filters/workarounds/workaround_utils.h', + 'src/core/lib/iomgr/cfstream_handle.h', 'src/core/lib/iomgr/endpoint_cfstream.h', 'src/core/lib/iomgr/error_cfstream.h' end + # CFStream is now default. Leaving this subspec only for compatibility purpose. + s.subspec 'CFStream-Implementation' do |ss| + ss.dependency "#{s.name}/Implementation", version + end + s.subspec 'Cronet-Interface' do |ss| ss.header_mappings_dir = 'include/grpc' ss.source_files = 'include/grpc/grpc_cronet.h' diff --git a/gRPC-ProtoRPC.podspec b/gRPC-ProtoRPC.podspec index 13fe3e0b9c0..d27df2d30b7 100644 --- a/gRPC-ProtoRPC.podspec +++ b/gRPC-ProtoRPC.podspec @@ -52,12 +52,10 @@ Pod::Spec.new do |s| ss.source_files = "#{src_dir}/*.{h,m}" end + + # CFStream is now default. Leaving this subspec only for compatibility purpose. s.subspec 'CFStream' do |ss| - ss.dependency 'gRPC/CFStream', version ss.dependency "#{s.name}/Main", version - ss.pod_target_xcconfig = { - 'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1' - } end s.pod_target_xcconfig = { diff --git a/gRPC.podspec b/gRPC.podspec index 940a1ac6217..ddc32da6261 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -63,14 +63,9 @@ Pod::Spec.new do |s| ss.dependency 'gRPC-Core', version end - # This subspec is mutually exclusive with the `Main` subspec + # CFStream is now default. Leaving this subspec only for compatibility purpose. s.subspec 'CFStream' do |ss| - ss.dependency 'gRPC-Core/CFStream-Implementation', version ss.dependency "#{s.name}/Main", version - - ss.pod_target_xcconfig = { - 'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1' - } end s.subspec 'GID' do |ss| From 80f005ee8fe33c21debbe0af1e976ff96d8bf0cf Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 27 Dec 2018 13:46:52 -0800 Subject: [PATCH 005/242] Remove debug info; clang-format --- BUILD | 28 +++------- include/grpc/impl/codegen/port_platform.h | 64 +++++++++++------------ src/core/lib/iomgr/cfstream_handle.cc | 1 - 3 files changed, 40 insertions(+), 53 deletions(-) diff --git a/BUILD b/BUILD index e3c765198b2..b8abce38072 100644 --- a/BUILD +++ b/BUILD @@ -706,12 +706,15 @@ grpc_cc_library( "src/core/lib/http/parser.cc", "src/core/lib/iomgr/buffer_list.cc", "src/core/lib/iomgr/call_combiner.cc", + "src/core/lib/iomgr/cfstream_handle.cc", "src/core/lib/iomgr/combiner.cc", "src/core/lib/iomgr/endpoint.cc", + "src/core/lib/iomgr/endpoint_cfstream.cc", "src/core/lib/iomgr/endpoint_pair_posix.cc", "src/core/lib/iomgr/endpoint_pair_uv.cc", "src/core/lib/iomgr/endpoint_pair_windows.cc", "src/core/lib/iomgr/error.cc", + "src/core/lib/iomgr/error_cfstream.cc", "src/core/lib/iomgr/ev_epoll1_linux.cc", "src/core/lib/iomgr/ev_epollex_linux.cc", "src/core/lib/iomgr/ev_poll_posix.cc", @@ -730,6 +733,7 @@ grpc_cc_library( "src/core/lib/iomgr/iomgr_custom.cc", "src/core/lib/iomgr/iomgr_internal.cc", "src/core/lib/iomgr/iomgr_posix.cc", + "src/core/lib/iomgr/iomgr_posix_cfstream.cc", "src/core/lib/iomgr/iomgr_windows.cc", "src/core/lib/iomgr/is_epollexclusive_available.cc", "src/core/lib/iomgr/load_file.cc", @@ -757,6 +761,7 @@ grpc_cc_library( "src/core/lib/iomgr/socket_utils_windows.cc", "src/core/lib/iomgr/socket_windows.cc", "src/core/lib/iomgr/tcp_client.cc", + "src/core/lib/iomgr/tcp_client_cfstream.cc", "src/core/lib/iomgr/tcp_client_custom.cc", "src/core/lib/iomgr/tcp_client_posix.cc", "src/core/lib/iomgr/tcp_client_windows.cc", @@ -858,12 +863,15 @@ grpc_cc_library( "src/core/lib/iomgr/block_annotate.h", "src/core/lib/iomgr/buffer_list.h", "src/core/lib/iomgr/call_combiner.h", + "src/core/lib/iomgr/cfstream_handle.h", "src/core/lib/iomgr/closure.h", "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/dynamic_annotations.h", "src/core/lib/iomgr/endpoint.h", + "src/core/lib/iomgr/endpoint_cfstream.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", + "src/core/lib/iomgr/error_cfstream.h", "src/core/lib/iomgr/error_internal.h", "src/core/lib/iomgr/ev_epoll1_linux.h", "src/core/lib/iomgr/ev_epollex_linux.h", @@ -1018,26 +1026,6 @@ grpc_cc_library( ], ) -grpc_cc_library( - name = "grpc_cfstream", - srcs = [ - "src/core/lib/iomgr/cfstream_handle.cc", - "src/core/lib/iomgr/endpoint_cfstream.cc", - "src/core/lib/iomgr/error_cfstream.cc", - "src/core/lib/iomgr/iomgr_posix_cfstream.cc", - "src/core/lib/iomgr/tcp_client_cfstream.cc", - ], - hdrs = [ - "src/core/lib/iomgr/cfstream_handle.h", - "src/core/lib/iomgr/endpoint_cfstream.h", - "src/core/lib/iomgr/error_cfstream.h", - ], - deps = [ - ":gpr_base", - ":grpc_base", - ], -) - grpc_cc_library( name = "grpc_client_channel", srcs = [ diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index 46d831395da..21253db01e4 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -185,39 +185,39 @@ #define _BSD_SOURCE #endif #if TARGET_OS_IPHONE - #define GPR_PLATFORM_STRING "ios" - #define GPR_CPU_IPHONE 1 - #define GPR_PTHREAD_TLS 1 - #define GRPC_CFSTREAM 1 +#define GPR_PLATFORM_STRING "ios" +#define GPR_CPU_IPHONE 1 +#define GPR_PTHREAD_TLS 1 +#define GRPC_CFSTREAM 1 #else /* TARGET_OS_IPHONE */ - #define GPR_PLATFORM_STRING "osx" - #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED - #if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_7 - #define GPR_CPU_IPHONE 1 - #define GPR_PTHREAD_TLS 1 - #else /* __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_7 */ - #define GPR_CPU_POSIX 1 - /* TODO(vjpai): there is a reported issue in bazel build for Mac where __thread - in a header is currently not working (bazelbuild/bazel#4341). Remove - the following conditional and use GPR_GCC_TLS when that is fixed */ - #ifndef GRPC_BAZEL_BUILD - #define GPR_GCC_TLS 1 - #else /* GRPC_BAZEL_BUILD */ - #define GPR_PTHREAD_TLS 1 - #endif /* GRPC_BAZEL_BUILD */ - #define GPR_APPLE_PTHREAD_NAME 1 - #endif - #else /* __MAC_OS_X_VERSION_MIN_REQUIRED */ - #define GPR_CPU_POSIX 1 - /* TODO(vjpai): Remove the following conditional and use only GPR_GCC_TLS - when bazelbuild/bazel#4341 is fixed */ - #ifndef GRPC_BAZEL_BUILD - #define GPR_GCC_TLS 1 - #else /* GRPC_BAZEL_BUILD */ - #define GPR_PTHREAD_TLS 1 - #endif /* GRPC_BAZEL_BUILD */ - #endif - #define GPR_POSIX_CRASH_HANDLER 1 +#define GPR_PLATFORM_STRING "osx" +#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED +#if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_7 +#define GPR_CPU_IPHONE 1 +#define GPR_PTHREAD_TLS 1 +#else /* __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_7 */ +#define GPR_CPU_POSIX 1 +/* TODO(vjpai): there is a reported issue in bazel build for Mac where __thread + in a header is currently not working (bazelbuild/bazel#4341). Remove + the following conditional and use GPR_GCC_TLS when that is fixed */ +#ifndef GRPC_BAZEL_BUILD +#define GPR_GCC_TLS 1 +#else /* GRPC_BAZEL_BUILD */ +#define GPR_PTHREAD_TLS 1 +#endif /* GRPC_BAZEL_BUILD */ +#define GPR_APPLE_PTHREAD_NAME 1 +#endif +#else /* __MAC_OS_X_VERSION_MIN_REQUIRED */ +#define GPR_CPU_POSIX 1 +/* TODO(vjpai): Remove the following conditional and use only GPR_GCC_TLS + when bazelbuild/bazel#4341 is fixed */ +#ifndef GRPC_BAZEL_BUILD +#define GPR_GCC_TLS 1 +#else /* GRPC_BAZEL_BUILD */ +#define GPR_PTHREAD_TLS 1 +#endif /* GRPC_BAZEL_BUILD */ +#endif +#define GPR_POSIX_CRASH_HANDLER 1 #endif #define GPR_APPLE 1 #define GPR_GCC_ATOMIC 1 diff --git a/src/core/lib/iomgr/cfstream_handle.cc b/src/core/lib/iomgr/cfstream_handle.cc index bb402f96cf5..6cb9ca1a0d4 100644 --- a/src/core/lib/iomgr/cfstream_handle.cc +++ b/src/core/lib/iomgr/cfstream_handle.cc @@ -79,7 +79,6 @@ void CFStreamHandle::WriteCallback(CFWriteStreamRef stream, void* clientCallBackInfo) { grpc_core::ExecCtx exec_ctx; CFStreamHandle* handle = static_cast(clientCallBackInfo); - printf("** CFStreamHandle::WriteCallback\n"); if (grpc_tcp_trace.enabled()) { gpr_log(GPR_DEBUG, "CFStream WriteCallback (%p, %p, %lu, %p)", handle, stream, type, clientCallBackInfo); From 12b0db3e57d52d6cc98b7518907a3f7fa582138b Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Thu, 14 Feb 2019 20:01:14 +0100 Subject: [PATCH 006/242] Folding CompletionQueue and ServerCompletionQueue. --- include/grpcpp/channel_impl.h | 12 +- include/grpcpp/generic/generic_stub.h | 1 - include/grpcpp/impl/codegen/async_stream.h | 2 - .../grpcpp/impl/codegen/async_unary_call.h | 1 - include/grpcpp/impl/codegen/call.h | 14 +- include/grpcpp/impl/codegen/call_op_set.h | 1 - .../grpcpp/impl/codegen/channel_interface.h | 15 +- include/grpcpp/impl/codegen/client_callback.h | 1 - include/grpcpp/impl/codegen/client_context.h | 2 +- .../grpcpp/impl/codegen/client_unary_call.h | 2 - .../grpcpp/impl/codegen/completion_queue.h | 382 +--------------- .../impl/codegen/completion_queue_impl.h | 417 ++++++++++++++++++ .../grpcpp/impl/codegen/intercepted_channel.h | 10 +- include/grpcpp/impl/codegen/server_context.h | 7 +- .../grpcpp/impl/codegen/server_interface.h | 51 +-- include/grpcpp/impl/codegen/service_type.h | 2 - include/grpcpp/server_builder.h | 12 +- src/compiler/cpp_generator.cc | 4 +- src/cpp/common/completion_queue_cc.cc | 8 +- 19 files changed, 498 insertions(+), 446 deletions(-) create mode 100644 include/grpcpp/impl/codegen/completion_queue_impl.h diff --git a/include/grpcpp/channel_impl.h b/include/grpcpp/channel_impl.h index ea90e5b8f7b..9ce41d92790 100644 --- a/include/grpcpp/channel_impl.h +++ b/include/grpcpp/channel_impl.h @@ -33,6 +33,8 @@ struct grpc_channel; namespace grpc_impl { +class CompletionQueue; + namespace experimental { /// Resets the channel's connection backoff. /// TODO(roth): Once we see whether this proves useful, either create a gRFC @@ -76,22 +78,22 @@ class Channel final : public ::grpc::ChannelInterface, ::grpc::internal::Call CreateCall(const ::grpc::internal::RpcMethod& method, ::grpc::ClientContext* context, - ::grpc::CompletionQueue* cq) override; + CompletionQueue* cq) override; void PerformOpsOnCall(::grpc::internal::CallOpSetInterface* ops, ::grpc::internal::Call* call) override; void* RegisterMethod(const char* method) override; void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline, - ::grpc::CompletionQueue* cq, void* tag) override; + CompletionQueue* cq, void* tag) override; bool WaitForStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline) override; - ::grpc::CompletionQueue* CallbackCQ() override; + CompletionQueue* CallbackCQ() override; ::grpc::internal::Call CreateCallInternal( const ::grpc::internal::RpcMethod& method, ::grpc::ClientContext* context, - ::grpc::CompletionQueue* cq, size_t interceptor_pos) override; + CompletionQueue* cq, size_t interceptor_pos) override; const grpc::string host_; grpc_channel* const c_channel_; // owned @@ -103,7 +105,7 @@ class Channel final : public ::grpc::ChannelInterface, // with this channel (if any). It is set on the first call to CallbackCQ(). // It is _not owned_ by the channel; ownership belongs with its internal // shutdown callback tag (invoked when the CQ is fully shutdown). - ::grpc::CompletionQueue* callback_cq_ = nullptr; + CompletionQueue* callback_cq_ = nullptr; std::vector< std::unique_ptr<::grpc::experimental::ClientInterceptorFactoryInterface>> diff --git a/include/grpcpp/generic/generic_stub.h b/include/grpcpp/generic/generic_stub.h index eb014184e4a..f449f1baab4 100644 --- a/include/grpcpp/generic/generic_stub.h +++ b/include/grpcpp/generic/generic_stub.h @@ -29,7 +29,6 @@ namespace grpc { -class CompletionQueue; typedef ClientAsyncReaderWriter GenericClientAsyncReaderWriter; typedef ClientAsyncResponseReader GenericClientAsyncResponseReader; diff --git a/include/grpcpp/impl/codegen/async_stream.h b/include/grpcpp/impl/codegen/async_stream.h index bfb2df4f232..721fc7e56d6 100644 --- a/include/grpcpp/impl/codegen/async_stream.h +++ b/include/grpcpp/impl/codegen/async_stream.h @@ -28,8 +28,6 @@ namespace grpc { -class CompletionQueue; - namespace internal { /// Common interface for all client side asynchronous streaming. class ClientAsyncStreamingInterface { diff --git a/include/grpcpp/impl/codegen/async_unary_call.h b/include/grpcpp/impl/codegen/async_unary_call.h index 89dcb124189..4b97cf29018 100644 --- a/include/grpcpp/impl/codegen/async_unary_call.h +++ b/include/grpcpp/impl/codegen/async_unary_call.h @@ -29,7 +29,6 @@ namespace grpc { -class CompletionQueue; extern CoreCodegenInterface* g_core_codegen_interface; /// An interface relevant for async client side unary RPCs (which send diff --git a/include/grpcpp/impl/codegen/call.h b/include/grpcpp/impl/codegen/call.h index c040c30dd9d..eefa4a7f9cd 100644 --- a/include/grpcpp/impl/codegen/call.h +++ b/include/grpcpp/impl/codegen/call.h @@ -21,9 +21,11 @@ #include #include -namespace grpc { +namespace grpc_impl { class CompletionQueue; +} +namespace grpc { namespace experimental { class ClientRpcInfo; class ServerRpcInfo; @@ -41,13 +43,13 @@ class Call final { call_(nullptr), max_receive_message_size_(-1) {} /** call is owned by the caller */ - Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq) + Call(grpc_call* call, CallHook* call_hook, ::grpc_impl::CompletionQueue* cq) : call_hook_(call_hook), cq_(cq), call_(call), max_receive_message_size_(-1) {} - Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq, + Call(grpc_call* call, CallHook* call_hook, ::grpc_impl::CompletionQueue* cq, experimental::ClientRpcInfo* rpc_info) : call_hook_(call_hook), cq_(cq), @@ -55,7 +57,7 @@ class Call final { max_receive_message_size_(-1), client_rpc_info_(rpc_info) {} - Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq, + Call(grpc_call* call, CallHook* call_hook, ::grpc_impl::CompletionQueue* cq, int max_receive_message_size, experimental::ServerRpcInfo* rpc_info) : call_hook_(call_hook), cq_(cq), @@ -68,7 +70,7 @@ class Call final { } grpc_call* call() const { return call_; } - CompletionQueue* cq() const { return cq_; } + ::grpc_impl::CompletionQueue* cq() const { return cq_; } int max_receive_message_size() const { return max_receive_message_size_; } @@ -82,7 +84,7 @@ class Call final { private: CallHook* call_hook_; - CompletionQueue* cq_; + ::grpc_impl::CompletionQueue* cq_; grpc_call* call_; int max_receive_message_size_; experimental::ClientRpcInfo* client_rpc_info_ = nullptr; diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index 4ca87a99fca..d810625b3e4 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -48,7 +48,6 @@ namespace grpc { -class CompletionQueue; extern CoreCodegenInterface* g_core_codegen_interface; namespace internal { diff --git a/include/grpcpp/impl/codegen/channel_interface.h b/include/grpcpp/impl/codegen/channel_interface.h index 5353f5feaa6..17a18efaf7b 100644 --- a/include/grpcpp/impl/codegen/channel_interface.h +++ b/include/grpcpp/impl/codegen/channel_interface.h @@ -24,10 +24,13 @@ #include #include +namespace grpc_impl { +class CompletionQueue; +} + namespace grpc { class ChannelInterface; class ClientContext; -class CompletionQueue; template class ClientReader; @@ -73,7 +76,7 @@ class ChannelInterface { /// deadline expires. \a GetState needs to called to get the current state. template void NotifyOnStateChange(grpc_connectivity_state last_observed, T deadline, - CompletionQueue* cq, void* tag) { + ::grpc_impl::CompletionQueue* cq, void* tag) { TimePoint deadline_tp(deadline); NotifyOnStateChangeImpl(last_observed, deadline_tp.raw_time(), cq, tag); } @@ -125,13 +128,13 @@ class ChannelInterface { friend class ::grpc::internal::InterceptedChannel; virtual internal::Call CreateCall(const internal::RpcMethod& method, ClientContext* context, - CompletionQueue* cq) = 0; + ::grpc_impl::CompletionQueue* cq) = 0; virtual void PerformOpsOnCall(internal::CallOpSetInterface* ops, internal::Call* call) = 0; virtual void* RegisterMethod(const char* method) = 0; virtual void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline, - CompletionQueue* cq, void* tag) = 0; + ::grpc_impl::CompletionQueue* cq, void* tag) = 0; virtual bool WaitForStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline) = 0; @@ -144,7 +147,7 @@ class ChannelInterface { // change (even though this is private and non-API) virtual internal::Call CreateCallInternal(const internal::RpcMethod& method, ClientContext* context, - CompletionQueue* cq, + ::grpc_impl::CompletionQueue* cq, size_t interceptor_pos) { return internal::Call(); } @@ -157,7 +160,7 @@ class ChannelInterface { // Returns nullptr (rather than being pure) since this is a post-1.0 method // and adding a new pure method to an interface would be a breaking change // (even though this is private and non-API) - virtual CompletionQueue* CallbackCQ() { return nullptr; } + virtual ::grpc_impl::CompletionQueue* CallbackCQ() { return nullptr; } }; } // namespace grpc diff --git a/include/grpcpp/impl/codegen/client_callback.h b/include/grpcpp/impl/codegen/client_callback.h index 6a0d0948cc6..f0ea62a7849 100644 --- a/include/grpcpp/impl/codegen/client_callback.h +++ b/include/grpcpp/impl/codegen/client_callback.h @@ -36,7 +36,6 @@ class Channel; namespace grpc { class ClientContext; -class CompletionQueue; namespace internal { class RpcMethod; diff --git a/include/grpcpp/impl/codegen/client_context.h b/include/grpcpp/impl/codegen/client_context.h index e6579b5b7a7..c291c7adfd3 100644 --- a/include/grpcpp/impl/codegen/client_context.h +++ b/include/grpcpp/impl/codegen/client_context.h @@ -59,12 +59,12 @@ struct grpc_call; namespace grpc_impl { class Channel; + } namespace grpc { class ChannelInterface; -class CompletionQueue; class CallCredentials; class ClientContext; diff --git a/include/grpcpp/impl/codegen/client_unary_call.h b/include/grpcpp/impl/codegen/client_unary_call.h index b9f8e1663f1..e0f692b1783 100644 --- a/include/grpcpp/impl/codegen/client_unary_call.h +++ b/include/grpcpp/impl/codegen/client_unary_call.h @@ -27,9 +27,7 @@ namespace grpc { -class Channel; class ClientContext; -class CompletionQueue; namespace internal { class RpcMethod; diff --git a/include/grpcpp/impl/codegen/completion_queue.h b/include/grpcpp/impl/codegen/completion_queue.h index 79a2805cb5f..00f773acf48 100644 --- a/include/grpcpp/impl/codegen/completion_queue.h +++ b/include/grpcpp/impl/codegen/completion_queue.h @@ -32,387 +32,13 @@ #ifndef GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H #define GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H -#include -#include -#include -#include -#include -#include - -struct grpc_completion_queue; - -namespace grpc_impl { - -class Channel; -} +#include namespace grpc { -template -class ClientReader; -template -class ClientWriter; -template -class ClientReaderWriter; -template -class ServerReader; -template -class ServerWriter; -namespace internal { -template -class ServerReaderWriterBody; -} // namespace internal +typedef ::grpc_impl::CompletionQueue CompletionQueue; +typedef ::grpc_impl::ServerCompletionQueue ServerCompletionQueue; -class ChannelInterface; -class ClientContext; -class CompletionQueue; -class Server; -class ServerBuilder; -class ServerContext; -class ServerInterface; - -namespace internal { -class CompletionQueueTag; -class RpcMethod; -template -class RpcMethodHandler; -template -class ClientStreamingHandler; -template -class ServerStreamingHandler; -template -class BidiStreamingHandler; -template -class TemplatedBidiStreamingHandler; -template -class ErrorMethodHandler; -template -class BlockingUnaryCallImpl; -template -class CallOpSet; -} // namespace internal - -extern CoreCodegenInterface* g_core_codegen_interface; - -/// A thin wrapper around \ref grpc_completion_queue (see \ref -/// src/core/lib/surface/completion_queue.h). -/// See \ref doc/cpp/perf_notes.md for notes on best practices for high -/// performance servers. -class CompletionQueue : private GrpcLibraryCodegen { - public: - /// Default constructor. Implicitly creates a \a grpc_completion_queue - /// instance. - CompletionQueue() - : CompletionQueue(grpc_completion_queue_attributes{ - GRPC_CQ_CURRENT_VERSION, GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, - nullptr}) {} - - /// Wrap \a take, taking ownership of the instance. - /// - /// \param take The completion queue instance to wrap. Ownership is taken. - explicit CompletionQueue(grpc_completion_queue* take); - - /// Destructor. Destroys the owned wrapped completion queue / instance. - ~CompletionQueue() { - g_core_codegen_interface->grpc_completion_queue_destroy(cq_); - } - - /// Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT. - enum NextStatus { - SHUTDOWN, ///< The completion queue has been shutdown and fully-drained - GOT_EVENT, ///< Got a new event; \a tag will be filled in with its - ///< associated value; \a ok indicating its success. - TIMEOUT ///< deadline was reached. - }; - - /// Read from the queue, blocking until an event is available or the queue is - /// shutting down. - /// - /// \param tag [out] Updated to point to the read event's tag. - /// \param ok [out] true if read a successful event, false otherwise. - /// - /// Note that each tag sent to the completion queue (through RPC operations - /// or alarms) will be delivered out of the completion queue by a call to - /// Next (or a related method), regardless of whether the operation succeeded - /// or not. Success here means that this operation completed in the normal - /// valid manner. - /// - /// Server-side RPC request: \a ok indicates that the RPC has indeed - /// been started. If it is false, the server has been Shutdown - /// before this particular call got matched to an incoming RPC. - /// - /// Client-side StartCall/RPC invocation: \a ok indicates that the RPC is - /// going to go to the wire. If it is false, it not going to the wire. This - /// would happen if the channel is either permanently broken or - /// transiently broken but with the fail-fast option. (Note that async unary - /// RPCs don't post a CQ tag at this point, nor do client-streaming - /// or bidi-streaming RPCs that have the initial metadata corked option set.) - /// - /// Client-side Write, Client-side WritesDone, Server-side Write, - /// Server-side Finish, Server-side SendInitialMetadata (which is - /// typically included in Write or Finish when not done explicitly): - /// \a ok means that the data/metadata/status/etc is going to go to the - /// wire. If it is false, it not going to the wire because the call - /// is already dead (i.e., canceled, deadline expired, other side - /// dropped the channel, etc). - /// - /// Client-side Read, Server-side Read, Client-side - /// RecvInitialMetadata (which is typically included in Read if not - /// done explicitly): \a ok indicates whether there is a valid message - /// that got read. If not, you know that there are certainly no more - /// messages that can ever be read from this stream. For the client-side - /// operations, this only happens because the call is dead. For the - /// server-sider operation, though, this could happen because the client - /// has done a WritesDone already. - /// - /// Client-side Finish: \a ok should always be true - /// - /// Server-side AsyncNotifyWhenDone: \a ok should always be true - /// - /// Alarm: \a ok is true if it expired, false if it was canceled - /// - /// \return true if got an event, false if the queue is fully drained and - /// shut down. - bool Next(void** tag, bool* ok) { - return (AsyncNextInternal(tag, ok, - g_core_codegen_interface->gpr_inf_future( - GPR_CLOCK_REALTIME)) != SHUTDOWN); - } - - /// Read from the queue, blocking up to \a deadline (or the queue's shutdown). - /// Both \a tag and \a ok are updated upon success (if an event is available - /// within the \a deadline). A \a tag points to an arbitrary location usually - /// employed to uniquely identify an event. - /// - /// \param tag [out] Upon sucess, updated to point to the event's tag. - /// \param ok [out] Upon sucess, true if a successful event, false otherwise - /// See documentation for CompletionQueue::Next for explanation of ok - /// \param deadline [in] How long to block in wait for an event. - /// - /// \return The type of event read. - template - NextStatus AsyncNext(void** tag, bool* ok, const T& deadline) { - TimePoint deadline_tp(deadline); - return AsyncNextInternal(tag, ok, deadline_tp.raw_time()); - } - - /// EXPERIMENTAL - /// First executes \a F, then reads from the queue, blocking up to - /// \a deadline (or the queue's shutdown). - /// Both \a tag and \a ok are updated upon success (if an event is available - /// within the \a deadline). A \a tag points to an arbitrary location usually - /// employed to uniquely identify an event. - /// - /// \param f [in] Function to execute before calling AsyncNext on this queue. - /// \param tag [out] Upon sucess, updated to point to the event's tag. - /// \param ok [out] Upon sucess, true if read a regular event, false - /// otherwise. - /// \param deadline [in] How long to block in wait for an event. - /// - /// \return The type of event read. - template - NextStatus DoThenAsyncNext(F&& f, void** tag, bool* ok, const T& deadline) { - CompletionQueueTLSCache cache = CompletionQueueTLSCache(this); - f(); - if (cache.Flush(tag, ok)) { - return GOT_EVENT; - } else { - return AsyncNext(tag, ok, deadline); - } - } - - /// Request the shutdown of the queue. - /// - /// \warning This method must be called at some point if this completion queue - /// is accessed with Next or AsyncNext. \a Next will not return false - /// until this method has been called and all pending tags have been drained. - /// (Likewise for \a AsyncNext returning \a NextStatus::SHUTDOWN .) - /// Only once either one of these methods does that (that is, once the queue - /// has been \em drained) can an instance of this class be destroyed. - /// Also note that applications must ensure that no work is enqueued on this - /// completion queue after this method is called. - void Shutdown(); - - /// Returns a \em raw pointer to the underlying \a grpc_completion_queue - /// instance. - /// - /// \warning Remember that the returned instance is owned. No transfer of - /// owership is performed. - grpc_completion_queue* cq() { return cq_; } - - protected: - /// Private constructor of CompletionQueue only visible to friend classes - CompletionQueue(const grpc_completion_queue_attributes& attributes) { - cq_ = g_core_codegen_interface->grpc_completion_queue_create( - g_core_codegen_interface->grpc_completion_queue_factory_lookup( - &attributes), - &attributes, NULL); - InitialAvalanching(); // reserve this for the future shutdown - } - - private: - // Friend synchronous wrappers so that they can access Pluck(), which is - // a semi-private API geared towards the synchronous implementation. - template - friend class ::grpc::ClientReader; - template - friend class ::grpc::ClientWriter; - template - friend class ::grpc::ClientReaderWriter; - template - friend class ::grpc::ServerReader; - template - friend class ::grpc::ServerWriter; - template - friend class ::grpc::internal::ServerReaderWriterBody; - template - friend class ::grpc::internal::RpcMethodHandler; - template - friend class ::grpc::internal::ClientStreamingHandler; - template - friend class ::grpc::internal::ServerStreamingHandler; - template - friend class ::grpc::internal::TemplatedBidiStreamingHandler; - template - friend class ::grpc::internal::ErrorMethodHandler; - friend class ::grpc::Server; - friend class ::grpc::ServerContext; - friend class ::grpc::ServerInterface; - template - friend class ::grpc::internal::BlockingUnaryCallImpl; - - // Friends that need access to constructor for callback CQ - friend class ::grpc_impl::Channel; - - // For access to Register/CompleteAvalanching - template - friend class ::grpc::internal::CallOpSet; - - /// EXPERIMENTAL - /// Creates a Thread Local cache to store the first event - /// On this completion queue queued from this thread. Once - /// initialized, it must be flushed on the same thread. - class CompletionQueueTLSCache { - public: - CompletionQueueTLSCache(CompletionQueue* cq); - ~CompletionQueueTLSCache(); - bool Flush(void** tag, bool* ok); - - private: - CompletionQueue* cq_; - bool flushed_; - }; - - NextStatus AsyncNextInternal(void** tag, bool* ok, gpr_timespec deadline); - - /// Wraps \a grpc_completion_queue_pluck. - /// \warning Must not be mixed with calls to \a Next. - bool Pluck(internal::CompletionQueueTag* tag) { - auto deadline = - g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME); - while (true) { - auto ev = g_core_codegen_interface->grpc_completion_queue_pluck( - cq_, tag, deadline, nullptr); - bool ok = ev.success != 0; - void* ignored = tag; - if (tag->FinalizeResult(&ignored, &ok)) { - GPR_CODEGEN_ASSERT(ignored == tag); - return ok; - } - } - } - - /// Performs a single polling pluck on \a tag. - /// \warning Must not be mixed with calls to \a Next. - /// - /// TODO: sreek - This calls tag->FinalizeResult() even if the cq_ is already - /// shutdown. This is most likely a bug and if it is a bug, then change this - /// implementation to simple call the other TryPluck function with a zero - /// timeout. i.e: - /// TryPluck(tag, gpr_time_0(GPR_CLOCK_REALTIME)) - void TryPluck(internal::CompletionQueueTag* tag) { - auto deadline = g_core_codegen_interface->gpr_time_0(GPR_CLOCK_REALTIME); - auto ev = g_core_codegen_interface->grpc_completion_queue_pluck( - cq_, tag, deadline, nullptr); - if (ev.type == GRPC_QUEUE_TIMEOUT) return; - bool ok = ev.success != 0; - void* ignored = tag; - // the tag must be swallowed if using TryPluck - GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok)); - } - - /// Performs a single polling pluck on \a tag. Calls tag->FinalizeResult if - /// the pluck() was successful and returned the tag. - /// - /// This exects tag->FinalizeResult (if called) to return 'false' i.e expects - /// that the tag is internal not something that is returned to the user. - void TryPluck(internal::CompletionQueueTag* tag, gpr_timespec deadline) { - auto ev = g_core_codegen_interface->grpc_completion_queue_pluck( - cq_, tag, deadline, nullptr); - if (ev.type == GRPC_QUEUE_TIMEOUT || ev.type == GRPC_QUEUE_SHUTDOWN) { - return; - } - - bool ok = ev.success != 0; - void* ignored = tag; - GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok)); - } - - /// Manage state of avalanching operations : completion queue tags that - /// trigger other completion queue operations. The underlying core completion - /// queue should not really shutdown until all avalanching operations have - /// been finalized. Note that we maintain the requirement that an avalanche - /// registration must take place before CQ shutdown (which must be maintained - /// elsehwere) - void InitialAvalanching() { - gpr_atm_rel_store(&avalanches_in_flight_, static_cast(1)); - } - void RegisterAvalanching() { - gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_, - static_cast(1)); - } - void CompleteAvalanching() { - if (gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_, - static_cast(-1)) == 1) { - g_core_codegen_interface->grpc_completion_queue_shutdown(cq_); - } - } - - grpc_completion_queue* cq_; // owned - - gpr_atm avalanches_in_flight_; -}; - -/// A specific type of completion queue used by the processing of notifications -/// by servers. Instantiated by \a ServerBuilder. -class ServerCompletionQueue : public CompletionQueue { - public: - bool IsFrequentlyPolled() { return polling_type_ != GRPC_CQ_NON_LISTENING; } - - protected: - /// Default constructor - ServerCompletionQueue() : polling_type_(GRPC_CQ_DEFAULT_POLLING) {} - - private: - /// \param completion_type indicates whether this is a NEXT or CALLBACK - /// completion queue. - /// \param polling_type Informs the GRPC library about the type of polling - /// allowed on this completion queue. See grpc_cq_polling_type's description - /// in grpc_types.h for more details. - /// \param shutdown_cb is the shutdown callback used for CALLBACK api queues - ServerCompletionQueue(grpc_cq_completion_type completion_type, - grpc_cq_polling_type polling_type, - grpc_experimental_completion_queue_functor* shutdown_cb) - : CompletionQueue(grpc_completion_queue_attributes{ - GRPC_CQ_CURRENT_VERSION, completion_type, polling_type, - shutdown_cb}), - polling_type_(polling_type) {} - - grpc_cq_polling_type polling_type_; - friend class ServerBuilder; - friend class Server; -}; - -} // namespace grpc +} #endif // GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H diff --git a/include/grpcpp/impl/codegen/completion_queue_impl.h b/include/grpcpp/impl/codegen/completion_queue_impl.h new file mode 100644 index 00000000000..b87a1e62158 --- /dev/null +++ b/include/grpcpp/impl/codegen/completion_queue_impl.h @@ -0,0 +1,417 @@ +/* + * + * Copyright 2015-2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/// A completion queue implements a concurrent producer-consumer queue, with +/// two main API-exposed methods: \a Next and \a AsyncNext. These +/// methods are the essential component of the gRPC C++ asynchronous API. +/// There is also a \a Shutdown method to indicate that a given completion queue +/// will no longer have regular events. This must be called before the +/// completion queue is destroyed. +/// All completion queue APIs are thread-safe and may be used concurrently with +/// any other completion queue API invocation; it is acceptable to have +/// multiple threads calling \a Next or \a AsyncNext on the same or different +/// completion queues, or to call these methods concurrently with a \a Shutdown +/// elsewhere. +/// \remark{All other API calls on completion queue should be completed before +/// a completion queue destructor is called.} +#ifndef GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_IMPL_H +#define GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_IMPL_H + +#include +#include +#include +#include +#include +#include + +struct grpc_completion_queue; + +namespace grpc { + +template +class ClientReader; +template +class ClientWriter; +template +class ClientReaderWriter; +template +class ServerReader; +template +class ServerWriter; +namespace internal { +template +class ServerReaderWriterBody; +} // namespace internal + +class ChannelInterface; +class ClientContext; +class Server; +class ServerBuilder; +class ServerContext; +class ServerInterface; + +namespace internal { +class CompletionQueueTag; +class RpcMethod; +template +class RpcMethodHandler; +template +class ClientStreamingHandler; +template +class ServerStreamingHandler; +template +class BidiStreamingHandler; +template +class TemplatedBidiStreamingHandler; +template +class ErrorMethodHandler; +template +class BlockingUnaryCallImpl; +template +class CallOpSet; +} // namespace internal + +extern CoreCodegenInterface* g_core_codegen_interface; + +} // namespace grpc + +namespace grpc_impl { +class Channel; + +/// A thin wrapper around \ref grpc_completion_queue (see \ref +/// src/core/lib/surface/completion_queue.h). +/// See \ref doc/cpp/perf_notes.md for notes on best practices for high +/// performance servers. +class CompletionQueue : private ::grpc::GrpcLibraryCodegen { + public: + /// Default constructor. Implicitly creates a \a grpc_completion_queue + /// instance. + CompletionQueue() + : CompletionQueue(grpc_completion_queue_attributes{ + GRPC_CQ_CURRENT_VERSION, GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, + nullptr}) {} + + /// Wrap \a take, taking ownership of the instance. + /// + /// \param take The completion queue instance to wrap. Ownership is taken. + explicit CompletionQueue(grpc_completion_queue* take); + + /// Destructor. Destroys the owned wrapped completion queue / instance. + ~CompletionQueue() { + ::grpc::g_core_codegen_interface->grpc_completion_queue_destroy(cq_); + } + + /// Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT. + enum NextStatus { + SHUTDOWN, ///< The completion queue has been shutdown and fully-drained + GOT_EVENT, ///< Got a new event; \a tag will be filled in with its + ///< associated value; \a ok indicating its success. + TIMEOUT ///< deadline was reached. + }; + + /// Read from the queue, blocking until an event is available or the queue is + /// shutting down. + /// + /// \param tag [out] Updated to point to the read event's tag. + /// \param ok [out] true if read a successful event, false otherwise. + /// + /// Note that each tag sent to the completion queue (through RPC operations + /// or alarms) will be delivered out of the completion queue by a call to + /// Next (or a related method), regardless of whether the operation succeeded + /// or not. Success here means that this operation completed in the normal + /// valid manner. + /// + /// Server-side RPC request: \a ok indicates that the RPC has indeed + /// been started. If it is false, the server has been Shutdown + /// before this particular call got matched to an incoming RPC. + /// + /// Client-side StartCall/RPC invocation: \a ok indicates that the RPC is + /// going to go to the wire. If it is false, it not going to the wire. This + /// would happen if the channel is either permanently broken or + /// transiently broken but with the fail-fast option. (Note that async unary + /// RPCs don't post a CQ tag at this point, nor do client-streaming + /// or bidi-streaming RPCs that have the initial metadata corked option set.) + /// + /// Client-side Write, Client-side WritesDone, Server-side Write, + /// Server-side Finish, Server-side SendInitialMetadata (which is + /// typically included in Write or Finish when not done explicitly): + /// \a ok means that the data/metadata/status/etc is going to go to the + /// wire. If it is false, it not going to the wire because the call + /// is already dead (i.e., canceled, deadline expired, other side + /// dropped the channel, etc). + /// + /// Client-side Read, Server-side Read, Client-side + /// RecvInitialMetadata (which is typically included in Read if not + /// done explicitly): \a ok indicates whether there is a valid message + /// that got read. If not, you know that there are certainly no more + /// messages that can ever be read from this stream. For the client-side + /// operations, this only happens because the call is dead. For the + /// server-sider operation, though, this could happen because the client + /// has done a WritesDone already. + /// + /// Client-side Finish: \a ok should always be true + /// + /// Server-side AsyncNotifyWhenDone: \a ok should always be true + /// + /// Alarm: \a ok is true if it expired, false if it was canceled + /// + /// \return true if got an event, false if the queue is fully drained and + /// shut down. + bool Next(void** tag, bool* ok) { + return (AsyncNextInternal(tag, ok, + ::grpc::g_core_codegen_interface->gpr_inf_future( + GPR_CLOCK_REALTIME)) != SHUTDOWN); + } + + /// Read from the queue, blocking up to \a deadline (or the queue's shutdown). + /// Both \a tag and \a ok are updated upon success (if an event is available + /// within the \a deadline). A \a tag points to an arbitrary location usually + /// employed to uniquely identify an event. + /// + /// \param tag [out] Upon sucess, updated to point to the event's tag. + /// \param ok [out] Upon sucess, true if a successful event, false otherwise + /// See documentation for CompletionQueue::Next for explanation of ok + /// \param deadline [in] How long to block in wait for an event. + /// + /// \return The type of event read. + template + NextStatus AsyncNext(void** tag, bool* ok, const T& deadline) { + ::grpc::TimePoint deadline_tp(deadline); + return AsyncNextInternal(tag, ok, deadline_tp.raw_time()); + } + + /// EXPERIMENTAL + /// First executes \a F, then reads from the queue, blocking up to + /// \a deadline (or the queue's shutdown). + /// Both \a tag and \a ok are updated upon success (if an event is available + /// within the \a deadline). A \a tag points to an arbitrary location usually + /// employed to uniquely identify an event. + /// + /// \param f [in] Function to execute before calling AsyncNext on this queue. + /// \param tag [out] Upon sucess, updated to point to the event's tag. + /// \param ok [out] Upon sucess, true if read a regular event, false + /// otherwise. + /// \param deadline [in] How long to block in wait for an event. + /// + /// \return The type of event read. + template + NextStatus DoThenAsyncNext(F&& f, void** tag, bool* ok, const T& deadline) { + CompletionQueueTLSCache cache = CompletionQueueTLSCache(this); + f(); + if (cache.Flush(tag, ok)) { + return GOT_EVENT; + } else { + return AsyncNext(tag, ok, deadline); + } + } + + /// Request the shutdown of the queue. + /// + /// \warning This method must be called at some point if this completion queue + /// is accessed with Next or AsyncNext. \a Next will not return false + /// until this method has been called and all pending tags have been drained. + /// (Likewise for \a AsyncNext returning \a NextStatus::SHUTDOWN .) + /// Only once either one of these methods does that (that is, once the queue + /// has been \em drained) can an instance of this class be destroyed. + /// Also note that applications must ensure that no work is enqueued on this + /// completion queue after this method is called. + void Shutdown(); + + /// Returns a \em raw pointer to the underlying \a grpc_completion_queue + /// instance. + /// + /// \warning Remember that the returned instance is owned. No transfer of + /// owership is performed. + grpc_completion_queue* cq() { return cq_; } + + protected: + /// Private constructor of CompletionQueue only visible to friend classes + CompletionQueue(const grpc_completion_queue_attributes& attributes) { + cq_ = ::grpc::g_core_codegen_interface->grpc_completion_queue_create( + ::grpc::g_core_codegen_interface->grpc_completion_queue_factory_lookup( + &attributes), + &attributes, NULL); + InitialAvalanching(); // reserve this for the future shutdown + } + + private: + // Friend synchronous wrappers so that they can access Pluck(), which is + // a semi-private API geared towards the synchronous implementation. + template + friend class ::grpc::ClientReader; + template + friend class ::grpc::ClientWriter; + template + friend class ::grpc::ClientReaderWriter; + template + friend class ::grpc::ServerReader; + template + friend class ::grpc::ServerWriter; + template + friend class ::grpc::internal::ServerReaderWriterBody; + template + friend class ::grpc::internal::RpcMethodHandler; + template + friend class ::grpc::internal::ClientStreamingHandler; + template + friend class ::grpc::internal::ServerStreamingHandler; + template + friend class ::grpc::internal::TemplatedBidiStreamingHandler; + template <::grpc::StatusCode code> + friend class ::grpc::internal::ErrorMethodHandler; + friend class ::grpc::Server; + friend class ::grpc::ServerContext; + friend class ::grpc::ServerInterface; + template + friend class ::grpc::internal::BlockingUnaryCallImpl; + + // Friends that need access to constructor for callback CQ + friend class ::grpc_impl::Channel; + + // For access to Register/CompleteAvalanching + template + friend class ::grpc::internal::CallOpSet; + + /// EXPERIMENTAL + /// Creates a Thread Local cache to store the first event + /// On this completion queue queued from this thread. Once + /// initialized, it must be flushed on the same thread. + class CompletionQueueTLSCache { + public: + CompletionQueueTLSCache(CompletionQueue* cq); + ~CompletionQueueTLSCache(); + bool Flush(void** tag, bool* ok); + + private: + CompletionQueue* cq_; + bool flushed_; + }; + + NextStatus AsyncNextInternal(void** tag, bool* ok, gpr_timespec deadline); + + /// Wraps \a grpc_completion_queue_pluck. + /// \warning Must not be mixed with calls to \a Next. + bool Pluck(::grpc::internal::CompletionQueueTag* tag) { + auto deadline = + ::grpc::g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME); + while (true) { + auto ev = ::grpc::g_core_codegen_interface->grpc_completion_queue_pluck( + cq_, tag, deadline, nullptr); + bool ok = ev.success != 0; + void* ignored = tag; + if (tag->FinalizeResult(&ignored, &ok)) { + GPR_CODEGEN_ASSERT(ignored == tag); + return ok; + } + } + } + + /// Performs a single polling pluck on \a tag. + /// \warning Must not be mixed with calls to \a Next. + /// + /// TODO: sreek - This calls tag->FinalizeResult() even if the cq_ is already + /// shutdown. This is most likely a bug and if it is a bug, then change this + /// implementation to simple call the other TryPluck function with a zero + /// timeout. i.e: + /// TryPluck(tag, gpr_time_0(GPR_CLOCK_REALTIME)) + void TryPluck(::grpc::internal::CompletionQueueTag* tag) { + auto deadline = ::grpc::g_core_codegen_interface->gpr_time_0(GPR_CLOCK_REALTIME); + auto ev = ::grpc::g_core_codegen_interface->grpc_completion_queue_pluck( + cq_, tag, deadline, nullptr); + if (ev.type == GRPC_QUEUE_TIMEOUT) return; + bool ok = ev.success != 0; + void* ignored = tag; + // the tag must be swallowed if using TryPluck + GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok)); + } + + /// Performs a single polling pluck on \a tag. Calls tag->FinalizeResult if + /// the pluck() was successful and returned the tag. + /// + /// This exects tag->FinalizeResult (if called) to return 'false' i.e expects + /// that the tag is internal not something that is returned to the user. + void TryPluck(::grpc::internal::CompletionQueueTag* tag, gpr_timespec deadline) { + auto ev = ::grpc::g_core_codegen_interface->grpc_completion_queue_pluck( + cq_, tag, deadline, nullptr); + if (ev.type == GRPC_QUEUE_TIMEOUT || ev.type == GRPC_QUEUE_SHUTDOWN) { + return; + } + + bool ok = ev.success != 0; + void* ignored = tag; + GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok)); + } + + /// Manage state of avalanching operations : completion queue tags that + /// trigger other completion queue operations. The underlying core completion + /// queue should not really shutdown until all avalanching operations have + /// been finalized. Note that we maintain the requirement that an avalanche + /// registration must take place before CQ shutdown (which must be maintained + /// elsehwere) + void InitialAvalanching() { + gpr_atm_rel_store(&avalanches_in_flight_, static_cast(1)); + } + void RegisterAvalanching() { + gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_, + static_cast(1)); + } + void CompleteAvalanching() { + if (gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_, + static_cast(-1)) == 1) { + ::grpc::g_core_codegen_interface->grpc_completion_queue_shutdown(cq_); + } + } + + grpc_completion_queue* cq_; // owned + + gpr_atm avalanches_in_flight_; +}; + +/// A specific type of completion queue used by the processing of notifications +/// by servers. Instantiated by \a ServerBuilder. +class ServerCompletionQueue : public CompletionQueue { + public: + bool IsFrequentlyPolled() { return polling_type_ != GRPC_CQ_NON_LISTENING; } + + protected: + /// Default constructor + ServerCompletionQueue() : polling_type_(GRPC_CQ_DEFAULT_POLLING) {} + + private: + /// \param completion_type indicates whether this is a NEXT or CALLBACK + /// completion queue. + /// \param polling_type Informs the GRPC library about the type of polling + /// allowed on this completion queue. See grpc_cq_polling_type's description + /// in grpc_types.h for more details. + /// \param shutdown_cb is the shutdown callback used for CALLBACK api queues + ServerCompletionQueue(grpc_cq_completion_type completion_type, + grpc_cq_polling_type polling_type, + grpc_experimental_completion_queue_functor* shutdown_cb) + : CompletionQueue(grpc_completion_queue_attributes{ + GRPC_CQ_CURRENT_VERSION, completion_type, polling_type, + shutdown_cb}), + polling_type_(polling_type) {} + + grpc_cq_polling_type polling_type_; + friend class ::grpc::ServerBuilder; + friend class ::grpc::Server; +}; + +} // namespace grpc + +#endif // GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H diff --git a/include/grpcpp/impl/codegen/intercepted_channel.h b/include/grpcpp/impl/codegen/intercepted_channel.h index 5255a6d1472..62cdc518410 100644 --- a/include/grpcpp/impl/codegen/intercepted_channel.h +++ b/include/grpcpp/impl/codegen/intercepted_channel.h @@ -21,6 +21,10 @@ #include +namespace grpc_impl { +class CompletionQueue; +} + namespace grpc { namespace internal { @@ -46,7 +50,7 @@ class InterceptedChannel : public ChannelInterface { : channel_(channel), interceptor_pos_(pos) {} Call CreateCall(const RpcMethod& method, ClientContext* context, - CompletionQueue* cq) override { + ::grpc_impl::CompletionQueue* cq) override { return channel_->CreateCallInternal(method, context, cq, interceptor_pos_); } @@ -58,7 +62,7 @@ class InterceptedChannel : public ChannelInterface { } void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, - gpr_timespec deadline, CompletionQueue* cq, + gpr_timespec deadline, ::grpc_impl::CompletionQueue* cq, void* tag) override { return channel_->NotifyOnStateChangeImpl(last_observed, deadline, cq, tag); } @@ -67,7 +71,7 @@ class InterceptedChannel : public ChannelInterface { return channel_->WaitForStateChangeImpl(last_observed, deadline); } - CompletionQueue* CallbackCQ() override { return channel_->CallbackCQ(); } + ::grpc_impl::CompletionQueue* CallbackCQ() override { return channel_->CallbackCQ(); } ChannelInterface* channel_; size_t interceptor_pos_; diff --git a/include/grpcpp/impl/codegen/server_context.h b/include/grpcpp/impl/codegen/server_context.h index affe61b547b..4c8ab688e33 100644 --- a/include/grpcpp/impl/codegen/server_context.h +++ b/include/grpcpp/impl/codegen/server_context.h @@ -41,6 +41,10 @@ struct grpc_metadata; struct grpc_call; struct census_context; +namespace grpc_impl { +class CompletionQueue; +} + namespace grpc { class ClientContext; template @@ -82,7 +86,6 @@ class Call; class ServerReactor; } // namespace internal -class CompletionQueue; class Server; class ServerInterface; @@ -346,7 +349,7 @@ class ServerContext { gpr_timespec deadline_; grpc_call* call_; - CompletionQueue* cq_; + ::grpc_impl::CompletionQueue* cq_; bool sent_initial_metadata_; mutable std::shared_ptr auth_context_; mutable internal::MetadataMap client_metadata_; diff --git a/include/grpcpp/impl/codegen/server_interface.h b/include/grpcpp/impl/codegen/server_interface.h index b056643269a..18e40ad6d9f 100644 --- a/include/grpcpp/impl/codegen/server_interface.h +++ b/include/grpcpp/impl/codegen/server_interface.h @@ -30,13 +30,14 @@ namespace grpc_impl { class Channel; +class CompletionQueue; +class ServerCompletionQueue; } namespace grpc { class AsyncGenericService; class GenericServerContext; -class ServerCompletionQueue; class ServerContext; class ServerCredentials; class Service; @@ -138,7 +139,7 @@ class ServerInterface : public internal::CallHook { /// caller is required to keep all completion queues live until the server is /// destroyed. /// \param num_cqs How many completion queues does \a cqs hold. - virtual void Start(ServerCompletionQueue** cqs, size_t num_cqs) = 0; + virtual void Start(::grpc_impl::ServerCompletionQueue** cqs, size_t num_cqs) = 0; virtual void ShutdownInternal(gpr_timespec deadline) = 0; @@ -153,8 +154,8 @@ class ServerInterface : public internal::CallHook { public: BaseAsyncRequest(ServerInterface* server, ServerContext* context, internal::ServerAsyncStreamingInterface* stream, - CompletionQueue* call_cq, - ServerCompletionQueue* notification_cq, void* tag, + ::grpc_impl::CompletionQueue* call_cq, + ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag, bool delete_on_finalize); virtual ~BaseAsyncRequest(); @@ -167,8 +168,8 @@ class ServerInterface : public internal::CallHook { ServerInterface* const server_; ServerContext* const context_; internal::ServerAsyncStreamingInterface* const stream_; - CompletionQueue* const call_cq_; - ServerCompletionQueue* const notification_cq_; + ::grpc_impl::CompletionQueue* const call_cq_; + ::grpc_impl::ServerCompletionQueue* const notification_cq_; void* const tag_; const bool delete_on_finalize_; grpc_call* call_; @@ -182,8 +183,8 @@ class ServerInterface : public internal::CallHook { public: RegisteredAsyncRequest(ServerInterface* server, ServerContext* context, internal::ServerAsyncStreamingInterface* stream, - CompletionQueue* call_cq, - ServerCompletionQueue* notification_cq, void* tag, + ::grpc_impl::CompletionQueue* call_cq, + ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag, const char* name, internal::RpcMethod::RpcType type); virtual bool FinalizeResult(void** tag, bool* status) override { @@ -191,7 +192,7 @@ class ServerInterface : public internal::CallHook { if (done_intercepting_) { return BaseAsyncRequest::FinalizeResult(tag, status); } - call_wrapper_ = internal::Call( + call_wrapper_ = ::grpc::internal::Call( call_, server_, call_cq_, server_->max_receive_message_size(), context_->set_server_rpc_info(name_, type_, *server_->interceptor_creators())); @@ -200,7 +201,7 @@ class ServerInterface : public internal::CallHook { protected: void IssueRequest(void* registered_method, grpc_byte_buffer** payload, - ServerCompletionQueue* notification_cq); + ::grpc_impl::ServerCompletionQueue* notification_cq); const char* name_; const internal::RpcMethod::RpcType type_; }; @@ -210,8 +211,8 @@ class ServerInterface : public internal::CallHook { NoPayloadAsyncRequest(internal::RpcServiceMethod* registered_method, ServerInterface* server, ServerContext* context, internal::ServerAsyncStreamingInterface* stream, - CompletionQueue* call_cq, - ServerCompletionQueue* notification_cq, void* tag) + ::grpc_impl::CompletionQueue* call_cq, + ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag) : RegisteredAsyncRequest( server, context, stream, call_cq, notification_cq, tag, registered_method->name(), registered_method->method_type()) { @@ -227,8 +228,8 @@ class ServerInterface : public internal::CallHook { PayloadAsyncRequest(internal::RpcServiceMethod* registered_method, ServerInterface* server, ServerContext* context, internal::ServerAsyncStreamingInterface* stream, - CompletionQueue* call_cq, - ServerCompletionQueue* notification_cq, void* tag, + ::grpc_impl::CompletionQueue* call_cq, + ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag, Message* request) : RegisteredAsyncRequest( server, context, stream, call_cq, notification_cq, tag, @@ -284,9 +285,9 @@ class ServerInterface : public internal::CallHook { ServerInterface* const server_; ServerContext* const context_; internal::ServerAsyncStreamingInterface* const stream_; - CompletionQueue* const call_cq_; + ::grpc_impl::CompletionQueue* const call_cq_; - ServerCompletionQueue* const notification_cq_; + ::grpc_impl::ServerCompletionQueue* const notification_cq_; void* const tag_; Message* const request_; ByteBuffer payload_; @@ -296,8 +297,8 @@ class ServerInterface : public internal::CallHook { public: GenericAsyncRequest(ServerInterface* server, GenericServerContext* context, internal::ServerAsyncStreamingInterface* stream, - CompletionQueue* call_cq, - ServerCompletionQueue* notification_cq, void* tag, + ::grpc_impl::CompletionQueue* call_cq, + ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag, bool delete_on_finalize); bool FinalizeResult(void** tag, bool* status) override; @@ -310,8 +311,8 @@ class ServerInterface : public internal::CallHook { void RequestAsyncCall(internal::RpcServiceMethod* method, ServerContext* context, internal::ServerAsyncStreamingInterface* stream, - CompletionQueue* call_cq, - ServerCompletionQueue* notification_cq, void* tag, + ::grpc_impl::CompletionQueue* call_cq, + ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag, Message* message) { GPR_CODEGEN_ASSERT(method); new PayloadAsyncRequest(method, this, context, stream, call_cq, @@ -321,8 +322,8 @@ class ServerInterface : public internal::CallHook { void RequestAsyncCall(internal::RpcServiceMethod* method, ServerContext* context, internal::ServerAsyncStreamingInterface* stream, - CompletionQueue* call_cq, - ServerCompletionQueue* notification_cq, void* tag) { + ::grpc_impl::CompletionQueue* call_cq, + ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag) { GPR_CODEGEN_ASSERT(method); new NoPayloadAsyncRequest(method, this, context, stream, call_cq, notification_cq, tag); @@ -330,8 +331,8 @@ class ServerInterface : public internal::CallHook { void RequestAsyncGenericCall(GenericServerContext* context, internal::ServerAsyncStreamingInterface* stream, - CompletionQueue* call_cq, - ServerCompletionQueue* notification_cq, + ::grpc_impl::CompletionQueue* call_cq, + ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag) { new GenericAsyncRequest(this, context, stream, call_cq, notification_cq, tag, true); @@ -357,7 +358,7 @@ class ServerInterface : public internal::CallHook { // Returns nullptr (rather than being pure) since this is a post-1.0 method // and adding a new pure method to an interface would be a breaking change // (even though this is private and non-API) - virtual CompletionQueue* CallbackCQ() { return nullptr; } + virtual ::grpc_impl::CompletionQueue* CallbackCQ() { return nullptr; } }; } // namespace grpc diff --git a/include/grpcpp/impl/codegen/service_type.h b/include/grpcpp/impl/codegen/service_type.h index 332a04c294f..5325b80b0fd 100644 --- a/include/grpcpp/impl/codegen/service_type.h +++ b/include/grpcpp/impl/codegen/service_type.h @@ -28,10 +28,8 @@ namespace grpc { -class CompletionQueue; class Server; class ServerInterface; -class ServerCompletionQueue; class ServerContext; namespace internal { diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h index 028b8cffaa7..73524c3a7e6 100644 --- a/include/grpcpp/server_builder.h +++ b/include/grpcpp/server_builder.h @@ -35,13 +35,17 @@ struct grpc_resource_quota; +namespace grpc_impl { + +class ServerCompletionQueue; + +} + namespace grpc { class AsyncGenericService; class ResourceQuota; -class CompletionQueue; class Server; -class ServerCompletionQueue; class ServerCredentials; class Service; @@ -123,7 +127,7 @@ class ServerBuilder { /// not polling the completion queue frequently) will have a significantly /// negative performance impact and hence should not be used in production /// use cases. - std::unique_ptr AddCompletionQueue( + std::unique_ptr<::grpc_impl::ServerCompletionQueue> AddCompletionQueue( bool is_frequently_polled = true); ////////////////////////////////////////////////////////////////////////////// @@ -306,7 +310,7 @@ class ServerBuilder { SyncServerSettings sync_server_settings_; /// List of completion queues added via \a AddCompletionQueue method. - std::vector cqs_; + std::vector<::grpc_impl::ServerCompletionQueue*> cqs_; std::shared_ptr creds_; std::vector> plugins_; diff --git a/src/compiler/cpp_generator.cc b/src/compiler/cpp_generator.cc index e98abdd082a..72cd5a2dcbe 100644 --- a/src/compiler/cpp_generator.cc +++ b/src/compiler/cpp_generator.cc @@ -147,10 +147,10 @@ grpc::string GetHeaderIncludes(grpc_generator::File* file, printer->Print(vars, "\n"); printer->Print(vars, "namespace grpc_impl {\n"); printer->Print(vars, "class Channel;\n"); - printer->Print(vars, "} // namespace grpc_impl\n\n"); - printer->Print(vars, "namespace grpc {\n"); printer->Print(vars, "class CompletionQueue;\n"); printer->Print(vars, "class ServerCompletionQueue;\n"); + printer->Print(vars, "} // namespace grpc_impl\n\n"); + printer->Print(vars, "namespace grpc {\n"); printer->Print(vars, "class ServerContext;\n"); printer->Print(vars, "} // namespace grpc\n\n"); diff --git a/src/cpp/common/completion_queue_cc.cc b/src/cpp/common/completion_queue_cc.cc index 4bb3bcbd8b6..d1d0f8ab23c 100644 --- a/src/cpp/common/completion_queue_cc.cc +++ b/src/cpp/common/completion_queue_cc.cc @@ -24,9 +24,9 @@ #include #include -namespace grpc { +namespace grpc_impl { -static internal::GrpcLibraryInitializer g_gli_initializer; +static ::grpc::internal::GrpcLibraryInitializer g_gli_initializer; // 'CompletionQueue' constructor can safely call GrpcLibraryCodegen(false) here // i.e not have GrpcLibraryCodegen call grpc_init(). This is because, to create @@ -52,7 +52,7 @@ CompletionQueue::NextStatus CompletionQueue::AsyncNextInternal( case GRPC_QUEUE_SHUTDOWN: return SHUTDOWN; case GRPC_OP_COMPLETE: - auto core_cq_tag = static_cast(ev.tag); + auto core_cq_tag = static_cast<::grpc::internal::CompletionQueueTag*>(ev.tag); *ok = ev.success != 0; *tag = core_cq_tag; if (core_cq_tag->FinalizeResult(tag, ok)) { @@ -79,7 +79,7 @@ bool CompletionQueue::CompletionQueueTLSCache::Flush(void** tag, bool* ok) { flushed_ = true; if (grpc_completion_queue_thread_local_cache_flush(cq_->cq_, &res_tag, &res)) { - auto core_cq_tag = static_cast(res_tag); + auto core_cq_tag = static_cast<::grpc::internal::CompletionQueueTag*>(res_tag); *ok = res == 1; if (core_cq_tag->FinalizeResult(tag, ok)) { return true; From 5847c3a87a7fd85da1ed9326c4fc5f4c56518ec7 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Thu, 14 Feb 2019 20:05:59 +0100 Subject: [PATCH 007/242] Reformat. --- include/grpcpp/channel_impl.h | 4 +- .../grpcpp/impl/codegen/channel_interface.h | 3 +- include/grpcpp/impl/codegen/client_context.h | 1 - .../grpcpp/impl/codegen/completion_queue.h | 2 +- .../impl/codegen/completion_queue_impl.h | 8 ++-- .../grpcpp/impl/codegen/intercepted_channel.h | 7 +++- .../grpcpp/impl/codegen/server_interface.h | 42 ++++++++++--------- include/grpcpp/server_builder.h | 1 - src/cpp/common/completion_queue_cc.cc | 8 ++-- 9 files changed, 43 insertions(+), 33 deletions(-) diff --git a/include/grpcpp/channel_impl.h b/include/grpcpp/channel_impl.h index 9ce41d92790..c6adf7a9605 100644 --- a/include/grpcpp/channel_impl.h +++ b/include/grpcpp/channel_impl.h @@ -84,8 +84,8 @@ class Channel final : public ::grpc::ChannelInterface, void* RegisterMethod(const char* method) override; void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, - gpr_timespec deadline, - CompletionQueue* cq, void* tag) override; + gpr_timespec deadline, CompletionQueue* cq, + void* tag) override; bool WaitForStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline) override; diff --git a/include/grpcpp/impl/codegen/channel_interface.h b/include/grpcpp/impl/codegen/channel_interface.h index 17a18efaf7b..faa5e41cef9 100644 --- a/include/grpcpp/impl/codegen/channel_interface.h +++ b/include/grpcpp/impl/codegen/channel_interface.h @@ -134,7 +134,8 @@ class ChannelInterface { virtual void* RegisterMethod(const char* method) = 0; virtual void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline, - ::grpc_impl::CompletionQueue* cq, void* tag) = 0; + ::grpc_impl::CompletionQueue* cq, + void* tag) = 0; virtual bool WaitForStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline) = 0; diff --git a/include/grpcpp/impl/codegen/client_context.h b/include/grpcpp/impl/codegen/client_context.h index c291c7adfd3..6d1d03ec1f8 100644 --- a/include/grpcpp/impl/codegen/client_context.h +++ b/include/grpcpp/impl/codegen/client_context.h @@ -59,7 +59,6 @@ struct grpc_call; namespace grpc_impl { class Channel; - } namespace grpc { diff --git a/include/grpcpp/impl/codegen/completion_queue.h b/include/grpcpp/impl/codegen/completion_queue.h index 00f773acf48..edd1c2e97c8 100644 --- a/include/grpcpp/impl/codegen/completion_queue.h +++ b/include/grpcpp/impl/codegen/completion_queue.h @@ -39,6 +39,6 @@ namespace grpc { typedef ::grpc_impl::CompletionQueue CompletionQueue; typedef ::grpc_impl::ServerCompletionQueue ServerCompletionQueue; -} +} // namespace grpc #endif // GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H diff --git a/include/grpcpp/impl/codegen/completion_queue_impl.h b/include/grpcpp/impl/codegen/completion_queue_impl.h index b87a1e62158..df2d01b3394 100644 --- a/include/grpcpp/impl/codegen/completion_queue_impl.h +++ b/include/grpcpp/impl/codegen/completion_queue_impl.h @@ -330,7 +330,8 @@ class CompletionQueue : private ::grpc::GrpcLibraryCodegen { /// timeout. i.e: /// TryPluck(tag, gpr_time_0(GPR_CLOCK_REALTIME)) void TryPluck(::grpc::internal::CompletionQueueTag* tag) { - auto deadline = ::grpc::g_core_codegen_interface->gpr_time_0(GPR_CLOCK_REALTIME); + auto deadline = + ::grpc::g_core_codegen_interface->gpr_time_0(GPR_CLOCK_REALTIME); auto ev = ::grpc::g_core_codegen_interface->grpc_completion_queue_pluck( cq_, tag, deadline, nullptr); if (ev.type == GRPC_QUEUE_TIMEOUT) return; @@ -345,7 +346,8 @@ class CompletionQueue : private ::grpc::GrpcLibraryCodegen { /// /// This exects tag->FinalizeResult (if called) to return 'false' i.e expects /// that the tag is internal not something that is returned to the user. - void TryPluck(::grpc::internal::CompletionQueueTag* tag, gpr_timespec deadline) { + void TryPluck(::grpc::internal::CompletionQueueTag* tag, + gpr_timespec deadline) { auto ev = ::grpc::g_core_codegen_interface->grpc_completion_queue_pluck( cq_, tag, deadline, nullptr); if (ev.type == GRPC_QUEUE_TIMEOUT || ev.type == GRPC_QUEUE_SHUTDOWN) { @@ -412,6 +414,6 @@ class ServerCompletionQueue : public CompletionQueue { friend class ::grpc::Server; }; -} // namespace grpc +} // namespace grpc_impl #endif // GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H diff --git a/include/grpcpp/impl/codegen/intercepted_channel.h b/include/grpcpp/impl/codegen/intercepted_channel.h index 62cdc518410..cd0fcc06753 100644 --- a/include/grpcpp/impl/codegen/intercepted_channel.h +++ b/include/grpcpp/impl/codegen/intercepted_channel.h @@ -62,7 +62,8 @@ class InterceptedChannel : public ChannelInterface { } void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, - gpr_timespec deadline, ::grpc_impl::CompletionQueue* cq, + gpr_timespec deadline, + ::grpc_impl::CompletionQueue* cq, void* tag) override { return channel_->NotifyOnStateChangeImpl(last_observed, deadline, cq, tag); } @@ -71,7 +72,9 @@ class InterceptedChannel : public ChannelInterface { return channel_->WaitForStateChangeImpl(last_observed, deadline); } - ::grpc_impl::CompletionQueue* CallbackCQ() override { return channel_->CallbackCQ(); } + ::grpc_impl::CompletionQueue* CallbackCQ() override { + return channel_->CallbackCQ(); + } ChannelInterface* channel_; size_t interceptor_pos_; diff --git a/include/grpcpp/impl/codegen/server_interface.h b/include/grpcpp/impl/codegen/server_interface.h index 18e40ad6d9f..c3b8f8b3f3d 100644 --- a/include/grpcpp/impl/codegen/server_interface.h +++ b/include/grpcpp/impl/codegen/server_interface.h @@ -32,7 +32,7 @@ namespace grpc_impl { class Channel; class CompletionQueue; class ServerCompletionQueue; -} +} // namespace grpc_impl namespace grpc { @@ -139,7 +139,8 @@ class ServerInterface : public internal::CallHook { /// caller is required to keep all completion queues live until the server is /// destroyed. /// \param num_cqs How many completion queues does \a cqs hold. - virtual void Start(::grpc_impl::ServerCompletionQueue** cqs, size_t num_cqs) = 0; + virtual void Start(::grpc_impl::ServerCompletionQueue** cqs, + size_t num_cqs) = 0; virtual void ShutdownInternal(gpr_timespec deadline) = 0; @@ -155,8 +156,8 @@ class ServerInterface : public internal::CallHook { BaseAsyncRequest(ServerInterface* server, ServerContext* context, internal::ServerAsyncStreamingInterface* stream, ::grpc_impl::CompletionQueue* call_cq, - ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag, - bool delete_on_finalize); + ::grpc_impl::ServerCompletionQueue* notification_cq, + void* tag, bool delete_on_finalize); virtual ~BaseAsyncRequest(); bool FinalizeResult(void** tag, bool* status) override; @@ -184,8 +185,9 @@ class ServerInterface : public internal::CallHook { RegisteredAsyncRequest(ServerInterface* server, ServerContext* context, internal::ServerAsyncStreamingInterface* stream, ::grpc_impl::CompletionQueue* call_cq, - ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag, - const char* name, internal::RpcMethod::RpcType type); + ::grpc_impl::ServerCompletionQueue* notification_cq, + void* tag, const char* name, + internal::RpcMethod::RpcType type); virtual bool FinalizeResult(void** tag, bool* status) override { /* If we are done intercepting, then there is nothing more for us to do */ @@ -212,7 +214,8 @@ class ServerInterface : public internal::CallHook { ServerInterface* server, ServerContext* context, internal::ServerAsyncStreamingInterface* stream, ::grpc_impl::CompletionQueue* call_cq, - ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag) + ::grpc_impl::ServerCompletionQueue* notification_cq, + void* tag) : RegisteredAsyncRequest( server, context, stream, call_cq, notification_cq, tag, registered_method->name(), registered_method->method_type()) { @@ -229,8 +232,8 @@ class ServerInterface : public internal::CallHook { ServerInterface* server, ServerContext* context, internal::ServerAsyncStreamingInterface* stream, ::grpc_impl::CompletionQueue* call_cq, - ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag, - Message* request) + ::grpc_impl::ServerCompletionQueue* notification_cq, + void* tag, Message* request) : RegisteredAsyncRequest( server, context, stream, call_cq, notification_cq, tag, registered_method->name(), registered_method->method_type()), @@ -298,8 +301,8 @@ class ServerInterface : public internal::CallHook { GenericAsyncRequest(ServerInterface* server, GenericServerContext* context, internal::ServerAsyncStreamingInterface* stream, ::grpc_impl::CompletionQueue* call_cq, - ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag, - bool delete_on_finalize); + ::grpc_impl::ServerCompletionQueue* notification_cq, + void* tag, bool delete_on_finalize); bool FinalizeResult(void** tag, bool* status) override; @@ -312,8 +315,8 @@ class ServerInterface : public internal::CallHook { ServerContext* context, internal::ServerAsyncStreamingInterface* stream, ::grpc_impl::CompletionQueue* call_cq, - ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag, - Message* message) { + ::grpc_impl::ServerCompletionQueue* notification_cq, + void* tag, Message* message) { GPR_CODEGEN_ASSERT(method); new PayloadAsyncRequest(method, this, context, stream, call_cq, notification_cq, tag, message); @@ -323,17 +326,18 @@ class ServerInterface : public internal::CallHook { ServerContext* context, internal::ServerAsyncStreamingInterface* stream, ::grpc_impl::CompletionQueue* call_cq, - ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag) { + ::grpc_impl::ServerCompletionQueue* notification_cq, + void* tag) { GPR_CODEGEN_ASSERT(method); new NoPayloadAsyncRequest(method, this, context, stream, call_cq, notification_cq, tag); } - void RequestAsyncGenericCall(GenericServerContext* context, - internal::ServerAsyncStreamingInterface* stream, - ::grpc_impl::CompletionQueue* call_cq, - ::grpc_impl::ServerCompletionQueue* notification_cq, - void* tag) { + void RequestAsyncGenericCall( + GenericServerContext* context, + internal::ServerAsyncStreamingInterface* stream, + ::grpc_impl::CompletionQueue* call_cq, + ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag) { new GenericAsyncRequest(this, context, stream, call_cq, notification_cq, tag, true); } diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h index 73524c3a7e6..ae37ce55fbd 100644 --- a/include/grpcpp/server_builder.h +++ b/include/grpcpp/server_builder.h @@ -38,7 +38,6 @@ struct grpc_resource_quota; namespace grpc_impl { class ServerCompletionQueue; - } namespace grpc { diff --git a/src/cpp/common/completion_queue_cc.cc b/src/cpp/common/completion_queue_cc.cc index d1d0f8ab23c..43c2eee96f8 100644 --- a/src/cpp/common/completion_queue_cc.cc +++ b/src/cpp/common/completion_queue_cc.cc @@ -52,7 +52,8 @@ CompletionQueue::NextStatus CompletionQueue::AsyncNextInternal( case GRPC_QUEUE_SHUTDOWN: return SHUTDOWN; case GRPC_OP_COMPLETE: - auto core_cq_tag = static_cast<::grpc::internal::CompletionQueueTag*>(ev.tag); + auto core_cq_tag = + static_cast<::grpc::internal::CompletionQueueTag*>(ev.tag); *ok = ev.success != 0; *tag = core_cq_tag; if (core_cq_tag->FinalizeResult(tag, ok)) { @@ -79,7 +80,8 @@ bool CompletionQueue::CompletionQueueTLSCache::Flush(void** tag, bool* ok) { flushed_ = true; if (grpc_completion_queue_thread_local_cache_flush(cq_->cq_, &res_tag, &res)) { - auto core_cq_tag = static_cast<::grpc::internal::CompletionQueueTag*>(res_tag); + auto core_cq_tag = + static_cast<::grpc::internal::CompletionQueueTag*>(res_tag); *ok = res == 1; if (core_cq_tag->FinalizeResult(tag, ok)) { return true; @@ -88,4 +90,4 @@ bool CompletionQueue::CompletionQueueTLSCache::Flush(void** tag, bool* ok) { return false; } -} // namespace grpc +} // namespace grpc_impl From 7eb4fee9125c65abe77e82f498925abd8706399d Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Thu, 14 Feb 2019 20:07:21 +0100 Subject: [PATCH 008/242] Regenerate golden file. --- test/cpp/codegen/compiler_test_golden | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/cpp/codegen/compiler_test_golden b/test/cpp/codegen/compiler_test_golden index de71dcd5cb1..881bae3d6dc 100644 --- a/test/cpp/codegen/compiler_test_golden +++ b/test/cpp/codegen/compiler_test_golden @@ -42,11 +42,11 @@ namespace grpc_impl { class Channel; +class CompletionQueue; +class ServerCompletionQueue; } // namespace grpc_impl namespace grpc { -class CompletionQueue; -class ServerCompletionQueue; class ServerContext; } // namespace grpc From 035442b0863984bc0a77599b326fea8a00975d5f Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Thu, 14 Feb 2019 21:40:31 +0100 Subject: [PATCH 009/242] Fixing header guard. --- include/grpcpp/impl/codegen/completion_queue_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/grpcpp/impl/codegen/completion_queue_impl.h b/include/grpcpp/impl/codegen/completion_queue_impl.h index df2d01b3394..0a4b2100454 100644 --- a/include/grpcpp/impl/codegen/completion_queue_impl.h +++ b/include/grpcpp/impl/codegen/completion_queue_impl.h @@ -416,4 +416,4 @@ class ServerCompletionQueue : public CompletionQueue { } // namespace grpc_impl -#endif // GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H +#endif // GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_IMPL_H From ad1a34f9046199018b8edf755cc71f7f6deb81fc Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Thu, 14 Feb 2019 21:55:20 +0100 Subject: [PATCH 010/242] Adding new header to build files. --- BUILD | 1 + CMakeLists.txt | 5 +++++ Makefile | 5 +++++ build.yaml | 1 + gRPC-C++.podspec | 1 + tools/doxygen/Doxyfile.c++ | 1 + tools/doxygen/Doxyfile.c++.internal | 1 + tools/run_tests/generated/sources_and_headers.json | 2 ++ 8 files changed, 17 insertions(+) diff --git a/BUILD b/BUILD index 7986c156ed2..a2e133f8d7d 100644 --- a/BUILD +++ b/BUILD @@ -2122,6 +2122,7 @@ grpc_cc_library( "include/grpcpp/impl/codegen/client_interceptor.h", "include/grpcpp/impl/codegen/client_unary_call.h", "include/grpcpp/impl/codegen/completion_queue.h", + "include/grpcpp/impl/codegen/completion_queue_impl.h", "include/grpcpp/impl/codegen/completion_queue_tag.h", "include/grpcpp/impl/codegen/config.h", "include/grpcpp/impl/codegen/core_codegen_interface.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 41f6ad0ee6d..92735b6c9a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3138,6 +3138,7 @@ foreach(_hdr include/grpcpp/impl/codegen/client_interceptor.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h + include/grpcpp/impl/codegen/completion_queue_impl.h include/grpcpp/impl/codegen/completion_queue_tag.h include/grpcpp/impl/codegen/config.h include/grpcpp/impl/codegen/core_codegen_interface.h @@ -3730,6 +3731,7 @@ foreach(_hdr include/grpcpp/impl/codegen/client_interceptor.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h + include/grpcpp/impl/codegen/completion_queue_impl.h include/grpcpp/impl/codegen/completion_queue_tag.h include/grpcpp/impl/codegen/config.h include/grpcpp/impl/codegen/core_codegen_interface.h @@ -4153,6 +4155,7 @@ foreach(_hdr include/grpcpp/impl/codegen/client_interceptor.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h + include/grpcpp/impl/codegen/completion_queue_impl.h include/grpcpp/impl/codegen/completion_queue_tag.h include/grpcpp/impl/codegen/config.h include/grpcpp/impl/codegen/core_codegen_interface.h @@ -4348,6 +4351,7 @@ foreach(_hdr include/grpcpp/impl/codegen/client_interceptor.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h + include/grpcpp/impl/codegen/completion_queue_impl.h include/grpcpp/impl/codegen/completion_queue_tag.h include/grpcpp/impl/codegen/config.h include/grpcpp/impl/codegen/core_codegen_interface.h @@ -4686,6 +4690,7 @@ foreach(_hdr include/grpcpp/impl/codegen/client_interceptor.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h + include/grpcpp/impl/codegen/completion_queue_impl.h include/grpcpp/impl/codegen/completion_queue_tag.h include/grpcpp/impl/codegen/config.h include/grpcpp/impl/codegen/core_codegen_interface.h diff --git a/Makefile b/Makefile index 721ef768003..ac04814fd74 100644 --- a/Makefile +++ b/Makefile @@ -5544,6 +5544,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/client_interceptor.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ + include/grpcpp/impl/codegen/completion_queue_impl.h \ include/grpcpp/impl/codegen/completion_queue_tag.h \ include/grpcpp/impl/codegen/config.h \ include/grpcpp/impl/codegen/core_codegen_interface.h \ @@ -6145,6 +6146,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/client_interceptor.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ + include/grpcpp/impl/codegen/completion_queue_impl.h \ include/grpcpp/impl/codegen/completion_queue_tag.h \ include/grpcpp/impl/codegen/config.h \ include/grpcpp/impl/codegen/core_codegen_interface.h \ @@ -6547,6 +6549,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/client_interceptor.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ + include/grpcpp/impl/codegen/completion_queue_impl.h \ include/grpcpp/impl/codegen/completion_queue_tag.h \ include/grpcpp/impl/codegen/config.h \ include/grpcpp/impl/codegen/core_codegen_interface.h \ @@ -6714,6 +6717,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/client_interceptor.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ + include/grpcpp/impl/codegen/completion_queue_impl.h \ include/grpcpp/impl/codegen/completion_queue_tag.h \ include/grpcpp/impl/codegen/config.h \ include/grpcpp/impl/codegen/core_codegen_interface.h \ @@ -7058,6 +7062,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/client_interceptor.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ + include/grpcpp/impl/codegen/completion_queue_impl.h \ include/grpcpp/impl/codegen/completion_queue_tag.h \ include/grpcpp/impl/codegen/config.h \ include/grpcpp/impl/codegen/core_codegen_interface.h \ diff --git a/build.yaml b/build.yaml index 3b0f3e11b2a..4c56cabf03e 100644 --- a/build.yaml +++ b/build.yaml @@ -1246,6 +1246,7 @@ filegroups: - include/grpcpp/impl/codegen/client_interceptor.h - include/grpcpp/impl/codegen/client_unary_call.h - include/grpcpp/impl/codegen/completion_queue.h + - include/grpcpp/impl/codegen/completion_queue_impl.h - include/grpcpp/impl/codegen/completion_queue_tag.h - include/grpcpp/impl/codegen/config.h - include/grpcpp/impl/codegen/core_codegen_interface.h diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index fd5edbe744e..d98b80556c5 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -148,6 +148,7 @@ Pod::Spec.new do |s| 'include/grpcpp/impl/codegen/client_interceptor.h', 'include/grpcpp/impl/codegen/client_unary_call.h', 'include/grpcpp/impl/codegen/completion_queue.h', + 'include/grpcpp/impl/codegen/completion_queue_impl.h', 'include/grpcpp/impl/codegen/completion_queue_tag.h', 'include/grpcpp/impl/codegen/config.h', 'include/grpcpp/impl/codegen/core_codegen_interface.h', diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index cbc601921e1..27a3b6e168a 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -955,6 +955,7 @@ include/grpcpp/impl/codegen/client_context.h \ include/grpcpp/impl/codegen/client_interceptor.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ +include/grpcpp/impl/codegen/completion_queue_impl.h \ include/grpcpp/impl/codegen/completion_queue_tag.h \ include/grpcpp/impl/codegen/config.h \ include/grpcpp/impl/codegen/config_protobuf.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index a20e2a8d9bf..33f9e4f42da 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -956,6 +956,7 @@ include/grpcpp/impl/codegen/client_context.h \ include/grpcpp/impl/codegen/client_interceptor.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ +include/grpcpp/impl/codegen/completion_queue_impl.h \ include/grpcpp/impl/codegen/completion_queue_tag.h \ include/grpcpp/impl/codegen/config.h \ include/grpcpp/impl/codegen/config_protobuf.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 8f87daad295..79645366729 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -11164,6 +11164,7 @@ "include/grpcpp/impl/codegen/client_interceptor.h", "include/grpcpp/impl/codegen/client_unary_call.h", "include/grpcpp/impl/codegen/completion_queue.h", + "include/grpcpp/impl/codegen/completion_queue_impl.h", "include/grpcpp/impl/codegen/completion_queue_tag.h", "include/grpcpp/impl/codegen/config.h", "include/grpcpp/impl/codegen/core_codegen_interface.h", @@ -11240,6 +11241,7 @@ "include/grpcpp/impl/codegen/client_interceptor.h", "include/grpcpp/impl/codegen/client_unary_call.h", "include/grpcpp/impl/codegen/completion_queue.h", + "include/grpcpp/impl/codegen/completion_queue_impl.h", "include/grpcpp/impl/codegen/completion_queue_tag.h", "include/grpcpp/impl/codegen/config.h", "include/grpcpp/impl/codegen/core_codegen_interface.h", From 2fd2ee2289f2c0b1bdc66687d7d98124c405b8b9 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 18 Feb 2019 14:09:27 +0100 Subject: [PATCH 011/242] test C# on .NET core by default too --- tools/run_tests/run_tests_matrix.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/tools/run_tests/run_tests_matrix.py b/tools/run_tests/run_tests_matrix.py index d93add00cd2..785dff36eab 100755 --- a/tools/run_tests/run_tests_matrix.py +++ b/tools/run_tests/run_tests_matrix.py @@ -197,6 +197,7 @@ def _create_test_jobs(extra_args=[], inner_jobs=_DEFAULT_INNER_JOBS): inner_jobs=inner_jobs, timeout_seconds=_CPP_RUNTESTS_TIMEOUT) + # C# tests on .NET desktop/mono test_jobs += _generate_jobs( languages=['csharp'], configs=['dbg', 'opt'], @@ -204,6 +205,16 @@ def _create_test_jobs(extra_args=[], inner_jobs=_DEFAULT_INNER_JOBS): labels=['basictests', 'multilang'], extra_args=extra_args, inner_jobs=inner_jobs) + # C# tests on .NET core + test_jobs += _generate_jobs( + languages=['csharp'], + configs=['dbg', 'opt'], + platforms=['linux', 'macos', 'windows'], + arch='default', + compiler='coreclr', + labels=['basictests', 'multilang'], + extra_args=extra_args, + inner_jobs=inner_jobs) test_jobs += _generate_jobs( languages=['python'], @@ -392,16 +403,6 @@ def _create_portability_test_jobs(extra_args=[], extra_args=extra_args, inner_jobs=inner_jobs) - test_jobs += _generate_jobs( - languages=['csharp'], - configs=['dbg'], - platforms=['linux'], - arch='default', - compiler='coreclr', - labels=['portability', 'multilang'], - extra_args=extra_args, - inner_jobs=inner_jobs) - test_jobs += _generate_jobs( languages=['c'], configs=['dbg'], From 91ad8884975b334fab848b626fb28de6355fc608 Mon Sep 17 00:00:00 2001 From: Nicolas Noble Date: Wed, 27 Feb 2019 16:53:23 -0800 Subject: [PATCH 012/242] Revert "Revert "Folding the Channel class into the grpc_impl namespace."" --- BUILD | 1 + CMakeLists.txt | 3 + Makefile | 3 + build.yaml | 1 + gRPC-C++.podspec | 1 + include/grpcpp/channel.h | 86 +------------ include/grpcpp/channel_impl.h | 115 ++++++++++++++++++ include/grpcpp/impl/codegen/client_callback.h | 5 +- include/grpcpp/impl/codegen/client_context.h | 13 +- .../grpcpp/impl/codegen/client_interceptor.h | 6 +- .../grpcpp/impl/codegen/completion_queue.h | 8 +- .../grpcpp/impl/codegen/server_interface.h | 5 +- include/grpcpp/security/credentials.h | 16 ++- include/grpcpp/server.h | 1 + src/compiler/cpp_generator.cc | 4 +- src/cpp/client/channel_cc.cc | 60 ++++----- src/cpp/client/client_context.cc | 9 +- src/cpp/client/create_channel.cc | 4 +- src/cpp/client/create_channel_internal.cc | 9 +- src/cpp/client/create_channel_internal.h | 9 +- src/cpp/client/create_channel_posix.cc | 6 +- src/cpp/client/cronet_credentials.cc | 2 +- src/cpp/client/insecure_credentials.cc | 2 +- src/cpp/client/secure_credentials.cc | 2 +- src/cpp/client/secure_credentials.h | 9 +- src/cpp/server/server_cc.cc | 4 +- test/cpp/codegen/compiler_test_golden | 5 +- test/cpp/codegen/golden_file_test.cc | 2 +- test/cpp/microbenchmarks/bm_call_create.cc | 2 +- test/cpp/microbenchmarks/fullstack_fixtures.h | 2 +- test/cpp/performance/writes_per_rpc_test.cc | 2 +- test/cpp/util/create_test_channel.h | 18 +-- tools/doxygen/Doxyfile.c++ | 1 + tools/doxygen/Doxyfile.c++.internal | 1 + .../generated/sources_and_headers.json | 2 + 35 files changed, 258 insertions(+), 161 deletions(-) create mode 100644 include/grpcpp/channel_impl.h diff --git a/BUILD b/BUILD index 24c1fb31ced..be2261b825c 100644 --- a/BUILD +++ b/BUILD @@ -216,6 +216,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/alarm.h", "include/grpcpp/alarm_impl.h", "include/grpcpp/channel.h", + "include/grpcpp/channel_impl.h", "include/grpcpp/client_context.h", "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bab5e6cba2..41b7ce683eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2998,6 +2998,7 @@ foreach(_hdr include/grpcpp/alarm.h include/grpcpp/alarm_impl.h include/grpcpp/channel.h + include/grpcpp/channel_impl.h include/grpcpp/client_context.h include/grpcpp/completion_queue.h include/grpcpp/create_channel.h @@ -3589,6 +3590,7 @@ foreach(_hdr include/grpcpp/alarm.h include/grpcpp/alarm_impl.h include/grpcpp/channel.h + include/grpcpp/channel_impl.h include/grpcpp/client_context.h include/grpcpp/completion_queue.h include/grpcpp/create_channel.h @@ -4544,6 +4546,7 @@ foreach(_hdr include/grpcpp/alarm.h include/grpcpp/alarm_impl.h include/grpcpp/channel.h + include/grpcpp/channel_impl.h include/grpcpp/client_context.h include/grpcpp/completion_queue.h include/grpcpp/create_channel.h diff --git a/Makefile b/Makefile index a2789e40431..65fb0479bf6 100644 --- a/Makefile +++ b/Makefile @@ -5419,6 +5419,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/alarm.h \ include/grpcpp/alarm_impl.h \ include/grpcpp/channel.h \ + include/grpcpp/channel_impl.h \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ @@ -6019,6 +6020,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/alarm.h \ include/grpcpp/alarm_impl.h \ include/grpcpp/channel.h \ + include/grpcpp/channel_impl.h \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ @@ -6931,6 +6933,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/alarm.h \ include/grpcpp/alarm_impl.h \ include/grpcpp/channel.h \ + include/grpcpp/channel_impl.h \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ diff --git a/build.yaml b/build.yaml index c18630ecdd3..8f6b03ae322 100644 --- a/build.yaml +++ b/build.yaml @@ -1339,6 +1339,7 @@ filegroups: - include/grpcpp/alarm.h - include/grpcpp/alarm_impl.h - include/grpcpp/channel.h + - include/grpcpp/channel_impl.h - include/grpcpp/client_context.h - include/grpcpp/completion_queue.h - include/grpcpp/create_channel.h diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 0f3888975c9..9fb40d752a9 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -82,6 +82,7 @@ Pod::Spec.new do |s| ss.source_files = 'include/grpcpp/alarm.h', 'include/grpcpp/alarm_impl.h', 'include/grpcpp/channel.h', + 'include/grpcpp/channel_impl.h', 'include/grpcpp/client_context.h', 'include/grpcpp/completion_queue.h', 'include/grpcpp/create_channel.h', diff --git a/include/grpcpp/channel.h b/include/grpcpp/channel.h index ee833960698..05a45680916 100644 --- a/include/grpcpp/channel.h +++ b/include/grpcpp/channel.h @@ -19,96 +19,16 @@ #ifndef GRPCPP_CHANNEL_H #define GRPCPP_CHANNEL_H -#include -#include - -#include -#include -#include -#include -#include -#include - -struct grpc_channel; +#include namespace grpc { +typedef ::grpc_impl::Channel Channel; + namespace experimental { -/// Resets the channel's connection backoff. -/// TODO(roth): Once we see whether this proves useful, either create a gRFC -/// and change this to be a method of the Channel class, or remove it. void ChannelResetConnectionBackoff(Channel* channel); } // namespace experimental -/// Channels represent a connection to an endpoint. Created by \a CreateChannel. -class Channel final : public ChannelInterface, - public internal::CallHook, - public std::enable_shared_from_this, - private GrpcLibraryCodegen { - public: - ~Channel(); - - /// Get the current channel state. If the channel is in IDLE and - /// \a try_to_connect is set to true, try to connect. - grpc_connectivity_state GetState(bool try_to_connect) override; - - /// Returns the LB policy name, or the empty string if not yet available. - grpc::string GetLoadBalancingPolicyName() const; - - /// Returns the service config in JSON form, or the empty string if - /// not available. - grpc::string GetServiceConfigJSON() const; - - private: - template - friend class internal::BlockingUnaryCallImpl; - friend void experimental::ChannelResetConnectionBackoff(Channel* channel); - friend std::shared_ptr CreateChannelInternal( - const grpc::string& host, grpc_channel* c_channel, - std::vector< - std::unique_ptr> - interceptor_creators); - friend class internal::InterceptedChannel; - Channel(const grpc::string& host, grpc_channel* c_channel, - std::vector< - std::unique_ptr> - interceptor_creators); - - internal::Call CreateCall(const internal::RpcMethod& method, - ClientContext* context, - CompletionQueue* cq) override; - void PerformOpsOnCall(internal::CallOpSetInterface* ops, - internal::Call* call) override; - void* RegisterMethod(const char* method) override; - - void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, - gpr_timespec deadline, CompletionQueue* cq, - void* tag) override; - bool WaitForStateChangeImpl(grpc_connectivity_state last_observed, - gpr_timespec deadline) override; - - CompletionQueue* CallbackCQ() override; - - internal::Call CreateCallInternal(const internal::RpcMethod& method, - ClientContext* context, CompletionQueue* cq, - size_t interceptor_pos) override; - - const grpc::string host_; - grpc_channel* const c_channel_; // owned - - // mu_ protects callback_cq_ (the per-channel callbackable completion queue) - std::mutex mu_; - - // callback_cq_ references the callbackable completion queue associated - // with this channel (if any). It is set on the first call to CallbackCQ(). - // It is _not owned_ by the channel; ownership belongs with its internal - // shutdown callback tag (invoked when the CQ is fully shutdown). - CompletionQueue* callback_cq_ = nullptr; - - std::vector> - interceptor_creators_; -}; - } // namespace grpc #endif // GRPCPP_CHANNEL_H diff --git a/include/grpcpp/channel_impl.h b/include/grpcpp/channel_impl.h new file mode 100644 index 00000000000..ea90e5b8f7b --- /dev/null +++ b/include/grpcpp/channel_impl.h @@ -0,0 +1,115 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_CHANNEL_IMPL_H +#define GRPCPP_CHANNEL_IMPL_H + +#include +#include + +#include +#include +#include +#include +#include +#include + +struct grpc_channel; + +namespace grpc_impl { + +namespace experimental { +/// Resets the channel's connection backoff. +/// TODO(roth): Once we see whether this proves useful, either create a gRFC +/// and change this to be a method of the Channel class, or remove it. +void ChannelResetConnectionBackoff(Channel* channel); +} // namespace experimental + +/// Channels represent a connection to an endpoint. Created by \a CreateChannel. +class Channel final : public ::grpc::ChannelInterface, + public ::grpc::internal::CallHook, + public std::enable_shared_from_this, + private ::grpc::GrpcLibraryCodegen { + public: + ~Channel(); + + /// Get the current channel state. If the channel is in IDLE and + /// \a try_to_connect is set to true, try to connect. + grpc_connectivity_state GetState(bool try_to_connect) override; + + /// Returns the LB policy name, or the empty string if not yet available. + grpc::string GetLoadBalancingPolicyName() const; + + /// Returns the service config in JSON form, or the empty string if + /// not available. + grpc::string GetServiceConfigJSON() const; + + private: + template + friend class ::grpc::internal::BlockingUnaryCallImpl; + friend void experimental::ChannelResetConnectionBackoff(Channel* channel); + friend std::shared_ptr CreateChannelInternal( + const grpc::string& host, grpc_channel* c_channel, + std::vector> + interceptor_creators); + friend class ::grpc::internal::InterceptedChannel; + Channel(const grpc::string& host, grpc_channel* c_channel, + std::vector> + interceptor_creators); + + ::grpc::internal::Call CreateCall(const ::grpc::internal::RpcMethod& method, + ::grpc::ClientContext* context, + ::grpc::CompletionQueue* cq) override; + void PerformOpsOnCall(::grpc::internal::CallOpSetInterface* ops, + ::grpc::internal::Call* call) override; + void* RegisterMethod(const char* method) override; + + void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, + gpr_timespec deadline, + ::grpc::CompletionQueue* cq, void* tag) override; + bool WaitForStateChangeImpl(grpc_connectivity_state last_observed, + gpr_timespec deadline) override; + + ::grpc::CompletionQueue* CallbackCQ() override; + + ::grpc::internal::Call CreateCallInternal( + const ::grpc::internal::RpcMethod& method, ::grpc::ClientContext* context, + ::grpc::CompletionQueue* cq, size_t interceptor_pos) override; + + const grpc::string host_; + grpc_channel* const c_channel_; // owned + + // mu_ protects callback_cq_ (the per-channel callbackable completion queue) + std::mutex mu_; + + // callback_cq_ references the callbackable completion queue associated + // with this channel (if any). It is set on the first call to CallbackCQ(). + // It is _not owned_ by the channel; ownership belongs with its internal + // shutdown callback tag (invoked when the CQ is fully shutdown). + ::grpc::CompletionQueue* callback_cq_ = nullptr; + + std::vector< + std::unique_ptr<::grpc::experimental::ClientInterceptorFactoryInterface>> + interceptor_creators_; +}; + +} // namespace grpc_impl + +#endif // GRPCPP_CHANNEL_IMPL_H diff --git a/include/grpcpp/impl/codegen/client_callback.h b/include/grpcpp/impl/codegen/client_callback.h index 0b2631014a2..7b287f0a3ad 100644 --- a/include/grpcpp/impl/codegen/client_callback.h +++ b/include/grpcpp/impl/codegen/client_callback.h @@ -29,9 +29,12 @@ #include #include +namespace grpc_impl { +class Channel; +} + namespace grpc { -class Channel; class ClientContext; class CompletionQueue; diff --git a/include/grpcpp/impl/codegen/client_context.h b/include/grpcpp/impl/codegen/client_context.h index 5946488566e..e6579b5b7a7 100644 --- a/include/grpcpp/impl/codegen/client_context.h +++ b/include/grpcpp/impl/codegen/client_context.h @@ -56,9 +56,13 @@ struct census_context; struct grpc_call; -namespace grpc { +namespace grpc_impl { class Channel; +} + +namespace grpc { + class ChannelInterface; class CompletionQueue; class CallCredentials; @@ -391,7 +395,7 @@ class ClientContext { friend class ::grpc::testing::InteropClientContextInspector; friend class ::grpc::internal::CallOpClientRecvStatus; friend class ::grpc::internal::CallOpRecvInitialMetadata; - friend class Channel; + friend class ::grpc_impl::Channel; template friend class ::grpc::ClientReader; template @@ -423,7 +427,8 @@ class ClientContext { } grpc_call* call() const { return call_; } - void set_call(grpc_call* call, const std::shared_ptr& channel); + void set_call(grpc_call* call, + const std::shared_ptr<::grpc_impl::Channel>& channel); experimental::ClientRpcInfo* set_client_rpc_info( const char* method, internal::RpcMethod::RpcType type, @@ -456,7 +461,7 @@ class ClientContext { bool wait_for_ready_explicitly_set_; bool idempotent_; bool cacheable_; - std::shared_ptr channel_; + std::shared_ptr<::grpc_impl::Channel> channel_; std::mutex mu_; grpc_call* call_; bool call_canceled_; diff --git a/include/grpcpp/impl/codegen/client_interceptor.h b/include/grpcpp/impl/codegen/client_interceptor.h index e36a9da79d2..1096b7a2b5d 100644 --- a/include/grpcpp/impl/codegen/client_interceptor.h +++ b/include/grpcpp/impl/codegen/client_interceptor.h @@ -26,10 +26,14 @@ #include #include +namespace grpc_impl { + +class Channel; +} + namespace grpc { class ClientContext; -class Channel; namespace internal { class InterceptorBatchMethodsImpl; diff --git a/include/grpcpp/impl/codegen/completion_queue.h b/include/grpcpp/impl/codegen/completion_queue.h index 4812f0253d4..79a2805cb5f 100644 --- a/include/grpcpp/impl/codegen/completion_queue.h +++ b/include/grpcpp/impl/codegen/completion_queue.h @@ -41,6 +41,11 @@ struct grpc_completion_queue; +namespace grpc_impl { + +class Channel; +} + namespace grpc { template @@ -58,7 +63,6 @@ template class ServerReaderWriterBody; } // namespace internal -class Channel; class ChannelInterface; class ClientContext; class CompletionQueue; @@ -278,7 +282,7 @@ class CompletionQueue : private GrpcLibraryCodegen { friend class ::grpc::internal::BlockingUnaryCallImpl; // Friends that need access to constructor for callback CQ - friend class ::grpc::Channel; + friend class ::grpc_impl::Channel; // For access to Register/CompleteAvalanching template diff --git a/include/grpcpp/impl/codegen/server_interface.h b/include/grpcpp/impl/codegen/server_interface.h index 890a5650d02..b056643269a 100644 --- a/include/grpcpp/impl/codegen/server_interface.h +++ b/include/grpcpp/impl/codegen/server_interface.h @@ -28,10 +28,13 @@ #include #include +namespace grpc_impl { +class Channel; +} + namespace grpc { class AsyncGenericService; -class Channel; class GenericServerContext; class ServerCompletionQueue; class ServerContext; diff --git a/include/grpcpp/security/credentials.h b/include/grpcpp/security/credentials.h index dfea3900048..e8b1544b2c2 100644 --- a/include/grpcpp/security/credentials.h +++ b/include/grpcpp/security/credentials.h @@ -32,9 +32,13 @@ struct grpc_call; +namespace grpc_impl { + +class Channel; +} + namespace grpc { class ChannelArguments; -class Channel; class SecureChannelCredentials; class CallCredentials; class SecureCallCredentials; @@ -42,7 +46,7 @@ class SecureCallCredentials; class ChannelCredentials; namespace experimental { -std::shared_ptr CreateCustomChannelWithInterceptors( +std::shared_ptr<::grpc_impl::Channel> CreateCustomChannelWithInterceptors( const grpc::string& target, const std::shared_ptr& creds, const ChannelArguments& args, @@ -70,12 +74,12 @@ class ChannelCredentials : private GrpcLibraryCodegen { virtual SecureChannelCredentials* AsSecureCredentials() = 0; private: - friend std::shared_ptr CreateCustomChannel( + friend std::shared_ptr<::grpc_impl::Channel> CreateCustomChannel( const grpc::string& target, const std::shared_ptr& creds, const ChannelArguments& args); - friend std::shared_ptr + friend std::shared_ptr<::grpc_impl::Channel> experimental::CreateCustomChannelWithInterceptors( const grpc::string& target, const std::shared_ptr& creds, @@ -84,12 +88,12 @@ class ChannelCredentials : private GrpcLibraryCodegen { std::unique_ptr> interceptor_creators); - virtual std::shared_ptr CreateChannel( + virtual std::shared_ptr<::grpc_impl::Channel> CreateChannel( const grpc::string& target, const ChannelArguments& args) = 0; // This function should have been a pure virtual function, but it is // implemented as a virtual function so that it does not break API. - virtual std::shared_ptr CreateChannelWithInterceptors( + virtual std::shared_ptr<::grpc_impl::Channel> CreateChannelWithInterceptors( const grpc::string& target, const ChannelArguments& args, std::vector< std::unique_ptr> diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index 248f20452a5..159a94c0c81 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -27,6 +27,7 @@ #include #include +#include #include #include #include diff --git a/src/compiler/cpp_generator.cc b/src/compiler/cpp_generator.cc index 96e9ab8dcfb..6b53b3f64ce 100644 --- a/src/compiler/cpp_generator.cc +++ b/src/compiler/cpp_generator.cc @@ -145,9 +145,11 @@ grpc::string GetHeaderIncludes(grpc_generator::File* file, PrintIncludes(printer.get(), headers, params.use_system_headers, params.grpc_search_path); printer->Print(vars, "\n"); + printer->Print(vars, "namespace grpc_impl {\n"); + printer->Print(vars, "class Channel;\n"); + printer->Print(vars, "} // namespace grpc_impl\n\n"); printer->Print(vars, "namespace grpc {\n"); printer->Print(vars, "class CompletionQueue;\n"); - printer->Print(vars, "class Channel;\n"); printer->Print(vars, "class ServerCompletionQueue;\n"); printer->Print(vars, "class ServerContext;\n"); printer->Print(vars, "} // namespace grpc\n\n"); diff --git a/src/cpp/client/channel_cc.cc b/src/cpp/client/channel_cc.cc index a31d0b30b15..b4bb1b41a21 100644 --- a/src/cpp/client/channel_cc.cc +++ b/src/cpp/client/channel_cc.cc @@ -49,14 +49,18 @@ #include "src/core/lib/profiling/timers.h" #include "src/core/lib/surface/completion_queue.h" -namespace grpc { +void grpc::experimental::ChannelResetConnectionBackoff( + ::grpc::Channel* channel) { + grpc_impl::experimental::ChannelResetConnectionBackoff(channel); +} -static internal::GrpcLibraryInitializer g_gli_initializer; -Channel::Channel( - const grpc::string& host, grpc_channel* channel, - std::vector< - std::unique_ptr> - interceptor_creators) +namespace grpc_impl { + +static ::grpc::internal::GrpcLibraryInitializer g_gli_initializer; +Channel::Channel(const grpc::string& host, grpc_channel* channel, + std::vector> + interceptor_creators) : host_(host), c_channel_(channel) { interceptor_creators_ = std::move(interceptor_creators); g_gli_initializer.summon(); @@ -72,7 +76,8 @@ Channel::~Channel() { namespace { inline grpc_slice SliceFromArray(const char* arr, size_t len) { - return g_core_codegen_interface->grpc_slice_from_copied_buffer(arr, len); + return ::grpc::g_core_codegen_interface->grpc_slice_from_copied_buffer(arr, + len); } grpc::string GetChannelInfoField(grpc_channel* channel, @@ -110,10 +115,9 @@ void ChannelResetConnectionBackoff(Channel* channel) { } // namespace experimental -internal::Call Channel::CreateCallInternal(const internal::RpcMethod& method, - ClientContext* context, - CompletionQueue* cq, - size_t interceptor_pos) { +::grpc::internal::Call Channel::CreateCallInternal( + const ::grpc::internal::RpcMethod& method, ::grpc::ClientContext* context, + ::grpc::CompletionQueue* cq, size_t interceptor_pos) { const bool kRegistered = method.channel_tag() && context->authority().empty(); grpc_call* c_call = nullptr; if (kRegistered) { @@ -122,7 +126,7 @@ internal::Call Channel::CreateCallInternal(const internal::RpcMethod& method, context->propagation_options_.c_bitmask(), cq->cq(), method.channel_tag(), context->raw_deadline(), nullptr); } else { - const string* host_str = nullptr; + const ::grpc::string* host_str = nullptr; if (!context->authority_.empty()) { host_str = &context->authority_; } else if (!host_.empty()) { @@ -132,7 +136,7 @@ internal::Call Channel::CreateCallInternal(const internal::RpcMethod& method, SliceFromArray(method.name(), strlen(method.name())); grpc_slice host_slice; if (host_str != nullptr) { - host_slice = SliceFromCopiedString(*host_str); + host_slice = ::grpc::SliceFromCopiedString(*host_str); } c_call = grpc_channel_create_call( c_channel_, context->propagate_from_call_, @@ -154,17 +158,17 @@ internal::Call Channel::CreateCallInternal(const internal::RpcMethod& method, interceptor_creators_, interceptor_pos); context->set_call(c_call, shared_from_this()); - return internal::Call(c_call, this, cq, info); + return ::grpc::internal::Call(c_call, this, cq, info); } -internal::Call Channel::CreateCall(const internal::RpcMethod& method, - ClientContext* context, - CompletionQueue* cq) { +::grpc::internal::Call Channel::CreateCall( + const ::grpc::internal::RpcMethod& method, ::grpc::ClientContext* context, + ::grpc::CompletionQueue* cq) { return CreateCallInternal(method, context, cq, 0); } -void Channel::PerformOpsOnCall(internal::CallOpSetInterface* ops, - internal::Call* call) { +void Channel::PerformOpsOnCall(::grpc::internal::CallOpSetInterface* ops, + ::grpc::internal::Call* call) { ops->FillOps( call); // Make a copy of call. It's fine since Call just has pointers } @@ -180,7 +184,7 @@ grpc_connectivity_state Channel::GetState(bool try_to_connect) { namespace { -class TagSaver final : public internal::CompletionQueueTag { +class TagSaver final : public ::grpc::internal::CompletionQueueTag { public: explicit TagSaver(void* tag) : tag_(tag) {} ~TagSaver() override {} @@ -198,7 +202,7 @@ class TagSaver final : public internal::CompletionQueueTag { void Channel::NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline, - CompletionQueue* cq, void* tag) { + ::grpc::CompletionQueue* cq, void* tag) { TagSaver* tag_saver = new TagSaver(tag); grpc_channel_watch_connectivity_state(c_channel_, last_observed, deadline, cq->cq(), tag_saver); @@ -206,7 +210,7 @@ void Channel::NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, bool Channel::WaitForStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline) { - CompletionQueue cq; + ::grpc::CompletionQueue cq; bool ok = false; void* tag = nullptr; NotifyOnStateChangeImpl(last_observed, deadline, &cq, nullptr); @@ -221,7 +225,7 @@ class ShutdownCallback : public grpc_experimental_completion_queue_functor { ShutdownCallback() { functor_run = &ShutdownCallback::Run; } // TakeCQ takes ownership of the cq into the shutdown callback // so that the shutdown callback will be responsible for destroying it - void TakeCQ(CompletionQueue* cq) { cq_ = cq; } + void TakeCQ(::grpc::CompletionQueue* cq) { cq_ = cq; } // The Run function will get invoked by the completion queue library // when the shutdown is actually complete @@ -232,17 +236,17 @@ class ShutdownCallback : public grpc_experimental_completion_queue_functor { } private: - CompletionQueue* cq_ = nullptr; + ::grpc::CompletionQueue* cq_ = nullptr; }; } // namespace -CompletionQueue* Channel::CallbackCQ() { +::grpc::CompletionQueue* Channel::CallbackCQ() { // TODO(vjpai): Consider using a single global CQ for the default CQ // if there is no explicit per-channel CQ registered std::lock_guard l(mu_); if (callback_cq_ == nullptr) { auto* shutdown_callback = new ShutdownCallback; - callback_cq_ = new CompletionQueue(grpc_completion_queue_attributes{ + callback_cq_ = new ::grpc::CompletionQueue(grpc_completion_queue_attributes{ GRPC_CQ_CURRENT_VERSION, GRPC_CQ_CALLBACK, GRPC_CQ_DEFAULT_POLLING, shutdown_callback}); @@ -252,4 +256,4 @@ CompletionQueue* Channel::CallbackCQ() { return callback_cq_; } -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc index efb59c71a8c..b3c52acd5f6 100644 --- a/src/cpp/client/client_context.cc +++ b/src/cpp/client/client_context.cc @@ -30,6 +30,11 @@ #include #include +namespace grpc_impl { + +class Channel; +} + namespace grpc { class DefaultGlobalClientCallbacks final @@ -82,8 +87,8 @@ void ClientContext::AddMetadata(const grpc::string& meta_key, send_initial_metadata_.insert(std::make_pair(meta_key, meta_value)); } -void ClientContext::set_call(grpc_call* call, - const std::shared_ptr& channel) { +void ClientContext::set_call( + grpc_call* call, const std::shared_ptr<::grpc_impl::Channel>& channel) { std::unique_lock lock(mu_); GPR_ASSERT(call_ == nullptr); call_ = call; diff --git a/src/cpp/client/create_channel.cc b/src/cpp/client/create_channel.cc index 457daa674c7..409edd207f4 100644 --- a/src/cpp/client/create_channel.cc +++ b/src/cpp/client/create_channel.cc @@ -40,7 +40,7 @@ std::shared_ptr CreateCustomChannel( const ChannelArguments& args) { GrpcLibraryCodegen init_lib; // We need to call init in case of a bad creds. return creds ? creds->CreateChannel(target, args) - : CreateChannelInternal( + : ::grpc_impl::CreateChannelInternal( "", grpc_lame_client_channel_create( nullptr, GRPC_STATUS_INVALID_ARGUMENT, @@ -70,7 +70,7 @@ std::shared_ptr CreateCustomChannelWithInterceptors( interceptor_creators) { return creds ? creds->CreateChannelWithInterceptors( target, args, std::move(interceptor_creators)) - : CreateChannelInternal( + : ::grpc_impl::CreateChannelInternal( "", grpc_lame_client_channel_create( nullptr, GRPC_STATUS_INVALID_ARGUMENT, diff --git a/src/cpp/client/create_channel_internal.cc b/src/cpp/client/create_channel_internal.cc index a0efb97f7ef..77fd00fb3fe 100644 --- a/src/cpp/client/create_channel_internal.cc +++ b/src/cpp/client/create_channel_internal.cc @@ -22,14 +22,15 @@ struct grpc_channel; -namespace grpc { +namespace grpc_impl { std::shared_ptr CreateChannelInternal( const grpc::string& host, grpc_channel* c_channel, - std::vector< - std::unique_ptr> + std::vector> interceptor_creators) { return std::shared_ptr( new Channel(host, c_channel, std::move(interceptor_creators))); } -} // namespace grpc + +} // namespace grpc_impl diff --git a/src/cpp/client/create_channel_internal.h b/src/cpp/client/create_channel_internal.h index a90c92c518d..7dab6473a9c 100644 --- a/src/cpp/client/create_channel_internal.h +++ b/src/cpp/client/create_channel_internal.h @@ -26,15 +26,16 @@ struct grpc_channel; -namespace grpc { +namespace grpc_impl { + class Channel; std::shared_ptr CreateChannelInternal( const grpc::string& host, grpc_channel* c_channel, - std::vector< - std::unique_ptr> + std::vector> interceptor_creators); -} // namespace grpc +} // namespace grpc_impl #endif // GRPC_INTERNAL_CPP_CLIENT_CREATE_CHANNEL_INTERNAL_H diff --git a/src/cpp/client/create_channel_posix.cc b/src/cpp/client/create_channel_posix.cc index 3affc1ef391..79bf10d2801 100644 --- a/src/cpp/client/create_channel_posix.cc +++ b/src/cpp/client/create_channel_posix.cc @@ -32,7 +32,7 @@ std::shared_ptr CreateInsecureChannelFromFd(const grpc::string& target, int fd) { internal::GrpcLibrary init_lib; init_lib.init(); - return CreateChannelInternal( + return ::grpc_impl::CreateChannelInternal( "", grpc_insecure_channel_create_from_fd(target.c_str(), fd, nullptr), std::vector< std::unique_ptr>()); @@ -44,7 +44,7 @@ std::shared_ptr CreateCustomInsecureChannelFromFd( init_lib.init(); grpc_channel_args channel_args; args.SetChannelArgs(&channel_args); - return CreateChannelInternal( + return ::grpc_impl::CreateChannelInternal( "", grpc_insecure_channel_create_from_fd(target.c_str(), fd, &channel_args), std::vector< @@ -62,7 +62,7 @@ std::shared_ptr CreateCustomInsecureChannelWithInterceptorsFromFd( init_lib.init(); grpc_channel_args channel_args; args.SetChannelArgs(&channel_args); - return CreateChannelInternal( + return ::grpc_impl::CreateChannelInternal( "", grpc_insecure_channel_create_from_fd(target.c_str(), fd, &channel_args), std::move(interceptor_creators)); diff --git a/src/cpp/client/cronet_credentials.cc b/src/cpp/client/cronet_credentials.cc index b2801764f20..0f8b988674b 100644 --- a/src/cpp/client/cronet_credentials.cc +++ b/src/cpp/client/cronet_credentials.cc @@ -47,7 +47,7 @@ class CronetChannelCredentialsImpl final : public ChannelCredentials { interceptor_creators) override { grpc_channel_args channel_args; args.SetChannelArgs(&channel_args); - return CreateChannelInternal( + return ::grpc_impl::CreateChannelInternal( "", grpc_cronet_secure_channel_create(engine_, target.c_str(), &channel_args, nullptr), diff --git a/src/cpp/client/insecure_credentials.cc b/src/cpp/client/insecure_credentials.cc index 241ce918034..1fa832528b1 100644 --- a/src/cpp/client/insecure_credentials.cc +++ b/src/cpp/client/insecure_credentials.cc @@ -45,7 +45,7 @@ class InsecureChannelCredentialsImpl final : public ChannelCredentials { interceptor_creators) override { grpc_channel_args channel_args; args.SetChannelArgs(&channel_args); - return CreateChannelInternal( + return ::grpc_impl::CreateChannelInternal( "", grpc_insecure_channel_create(target.c_str(), &channel_args, nullptr), std::move(interceptor_creators)); diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc index 4d0ed355aba..9ac07f58557 100644 --- a/src/cpp/client/secure_credentials.cc +++ b/src/cpp/client/secure_credentials.cc @@ -50,7 +50,7 @@ SecureChannelCredentials::CreateChannelWithInterceptors( interceptor_creators) { grpc_channel_args channel_args; args.SetChannelArgs(&channel_args); - return CreateChannelInternal( + return ::grpc_impl::CreateChannelInternal( args.GetSslTargetNameOverride(), grpc_secure_channel_create(c_creds_, target.c_str(), &channel_args, nullptr), diff --git a/src/cpp/client/secure_credentials.h b/src/cpp/client/secure_credentials.h index 4918bd5a4d7..5db4af143b4 100644 --- a/src/cpp/client/secure_credentials.h +++ b/src/cpp/client/secure_credentials.h @@ -27,6 +27,11 @@ #include "src/core/lib/security/credentials/credentials.h" #include "src/cpp/server/thread_pool_interface.h" +namespace grpc_impl { + +class Channel; +} + namespace grpc { class SecureChannelCredentials final : public ChannelCredentials { @@ -37,13 +42,13 @@ class SecureChannelCredentials final : public ChannelCredentials { } grpc_channel_credentials* GetRawCreds() { return c_creds_; } - std::shared_ptr CreateChannel( + std::shared_ptr<::grpc_impl::Channel> CreateChannel( const string& target, const grpc::ChannelArguments& args) override; SecureChannelCredentials* AsSecureCredentials() override { return this; } private: - std::shared_ptr CreateChannelWithInterceptors( + std::shared_ptr<::grpc_impl::Channel> CreateChannelWithInterceptors( const string& target, const grpc::ChannelArguments& args, std::vector< std::unique_ptr> diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 7eb0f2372b6..17b6bc897c8 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -794,7 +794,7 @@ grpc_server* Server::c_server() { return server_; } std::shared_ptr Server::InProcessChannel( const ChannelArguments& args) { grpc_channel_args channel_args = args.c_channel_args(); - return CreateChannelInternal( + return ::grpc_impl::CreateChannelInternal( "inproc", grpc_inproc_channel_create(server_, &channel_args, nullptr), std::vector< std::unique_ptr>()); @@ -807,7 +807,7 @@ Server::experimental_type::InProcessChannelWithInterceptors( std::unique_ptr> interceptor_creators) { grpc_channel_args channel_args = args.c_channel_args(); - return CreateChannelInternal( + return ::grpc_impl::CreateChannelInternal( "inproc", grpc_inproc_channel_create(server_->server_, &channel_args, nullptr), std::move(interceptor_creators)); diff --git a/test/cpp/codegen/compiler_test_golden b/test/cpp/codegen/compiler_test_golden index 7f9fd29026e..9202585535b 100644 --- a/test/cpp/codegen/compiler_test_golden +++ b/test/cpp/codegen/compiler_test_golden @@ -40,9 +40,12 @@ #include #include +namespace grpc_impl { +class Channel; +} // namespace grpc_impl + namespace grpc { class CompletionQueue; -class Channel; class ServerCompletionQueue; class ServerContext; } // namespace grpc diff --git a/test/cpp/codegen/golden_file_test.cc b/test/cpp/codegen/golden_file_test.cc index bfd36494941..19f267dd4b5 100644 --- a/test/cpp/codegen/golden_file_test.cc +++ b/test/cpp/codegen/golden_file_test.cc @@ -31,7 +31,7 @@ using namespace gflags; DEFINE_string( generated_file_path, "", - "path to the directory containing generated files compiler_test.grpc.pb.h" + "path to the directory containing generated files compiler_test.grpc.pb.h " "and compiler_test_mock.grpc.pb.h"); const char kGoldenFilePath[] = "test/cpp/codegen/compiler_test_golden"; diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc index e57650fe5b7..52ff5a3d79d 100644 --- a/test/cpp/microbenchmarks/bm_call_create.cc +++ b/test/cpp/microbenchmarks/bm_call_create.cc @@ -131,7 +131,7 @@ static void* tag(int i) { static void BM_LameChannelCallCreateCpp(benchmark::State& state) { TrackCounters track_counters; auto stub = - grpc::testing::EchoTestService::NewStub(grpc::CreateChannelInternal( + grpc::testing::EchoTestService::NewStub(grpc_impl::CreateChannelInternal( "", grpc_lame_client_channel_create("localhost:1234", GRPC_STATUS_UNAUTHENTICATED, "blah"), diff --git a/test/cpp/microbenchmarks/fullstack_fixtures.h b/test/cpp/microbenchmarks/fullstack_fixtures.h index 6bbf553bbd8..2d488d8b227 100644 --- a/test/cpp/microbenchmarks/fullstack_fixtures.h +++ b/test/cpp/microbenchmarks/fullstack_fixtures.h @@ -218,7 +218,7 @@ class EndpointPairFixture : public BaseFixture { "target", &c_args, GRPC_CLIENT_DIRECT_CHANNEL, client_transport_); grpc_chttp2_transport_start_reading(client_transport_, nullptr, nullptr); - channel_ = CreateChannelInternal( + channel_ = ::grpc_impl::CreateChannelInternal( "", channel, std::vector>()); diff --git a/test/cpp/performance/writes_per_rpc_test.cc b/test/cpp/performance/writes_per_rpc_test.cc index 7b22f23cf00..b531e08138a 100644 --- a/test/cpp/performance/writes_per_rpc_test.cc +++ b/test/cpp/performance/writes_per_rpc_test.cc @@ -118,7 +118,7 @@ class EndpointPairFixture { "target", &c_args, GRPC_CLIENT_DIRECT_CHANNEL, transport); grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); - channel_ = CreateChannelInternal( + channel_ = ::grpc_impl::CreateChannelInternal( "", channel, std::vector>()); diff --git a/test/cpp/util/create_test_channel.h b/test/cpp/util/create_test_channel.h index c615fb76536..f94f0ac30a2 100644 --- a/test/cpp/util/create_test_channel.h +++ b/test/cpp/util/create_test_channel.h @@ -23,8 +23,12 @@ #include -namespace grpc { +namespace grpc_impl { + class Channel; +} + +namespace grpc { namespace testing { @@ -32,31 +36,31 @@ typedef enum { INSECURE = 0, TLS, ALTS } transport_security; } // namespace testing -std::shared_ptr CreateTestChannel( +std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( const grpc::string& server, testing::transport_security security_type); -std::shared_ptr CreateTestChannel( +std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( const grpc::string& server, const grpc::string& override_hostname, testing::transport_security security_type, bool use_prod_roots); -std::shared_ptr CreateTestChannel( +std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( const grpc::string& server, const grpc::string& override_hostname, testing::transport_security security_type, bool use_prod_roots, const std::shared_ptr& creds); -std::shared_ptr CreateTestChannel( +std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( const grpc::string& server, const grpc::string& override_hostname, testing::transport_security security_type, bool use_prod_roots, const std::shared_ptr& creds, const ChannelArguments& args); -std::shared_ptr CreateTestChannel( +std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( const grpc::string& server, const grpc::string& cred_type, const grpc::string& override_hostname, bool use_prod_roots, const std::shared_ptr& creds, const ChannelArguments& args); -std::shared_ptr CreateTestChannel( +std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( const grpc::string& server, const grpc::string& credential_type, const std::shared_ptr& creds); diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 9f17a25298a..cbc601921e1 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -927,6 +927,7 @@ include/grpc/support/workaround_list.h \ include/grpcpp/alarm.h \ include/grpcpp/alarm_impl.h \ include/grpcpp/channel.h \ +include/grpcpp/channel_impl.h \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 664a6b3acfe..2d761199047 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -928,6 +928,7 @@ include/grpc/support/workaround_list.h \ include/grpcpp/alarm.h \ include/grpcpp/alarm_impl.h \ include/grpcpp/channel.h \ +include/grpcpp/channel_impl.h \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 95b6ae65008..4bec0074ae7 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -11363,6 +11363,7 @@ "include/grpcpp/alarm.h", "include/grpcpp/alarm_impl.h", "include/grpcpp/channel.h", + "include/grpcpp/channel_impl.h", "include/grpcpp/client_context.h", "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", @@ -11472,6 +11473,7 @@ "include/grpcpp/alarm.h", "include/grpcpp/alarm_impl.h", "include/grpcpp/channel.h", + "include/grpcpp/channel_impl.h", "include/grpcpp/client_context.h", "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", From 82c6e012d85626eac14baaa1b7cef2f1bbb0492c Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Tue, 12 Mar 2019 14:01:05 -0700 Subject: [PATCH 013/242] Revert "Revert "Moving ::grpc::ResourceQuota to ::grpc_impl::ResouceQuota"" --- BUILD | 3 +- CMakeLists.txt | 3 + Makefile | 3 + build.yaml | 1 + gRPC-C++.podspec | 1 + include/grpcpp/resource_quota.h | 45 +----------- include/grpcpp/resource_quota_impl.h | 68 +++++++++++++++++++ include/grpcpp/server_builder.h | 9 ++- include/grpcpp/support/channel_arguments.h | 9 ++- src/cpp/common/channel_arguments.cc | 2 +- src/cpp/common/resource_quota_cc.cc | 4 +- src/cpp/server/server_builder.cc | 7 +- test/cpp/end2end/end2end_test.cc | 5 ++ test/cpp/end2end/thread_stress_test.cc | 5 ++ test/cpp/qps/server.h | 5 ++ test/cpp/qps/server_async.cc | 1 - tools/doxygen/Doxyfile.c++ | 1 + tools/doxygen/Doxyfile.c++.internal | 1 + .../generated/sources_and_headers.json | 2 + 19 files changed, 122 insertions(+), 53 deletions(-) create mode 100644 include/grpcpp/resource_quota_impl.h diff --git a/BUILD b/BUILD index 4bf387cec3a..191661fdd9a 100644 --- a/BUILD +++ b/BUILD @@ -192,8 +192,8 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpc++/impl/service_type.h", "include/grpc++/impl/sync_cxx11.h", "include/grpc++/impl/sync_no_cxx11.h", - "include/grpc++/resource_quota.h", "include/grpc++/security/auth_context.h", + "include/grpc++/resource_quota.h", "include/grpc++/security/auth_metadata_processor.h", "include/grpc++/security/credentials.h", "include/grpc++/security/server_credentials.h", @@ -241,6 +241,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/impl/sync_cxx11.h", "include/grpcpp/impl/sync_no_cxx11.h", "include/grpcpp/resource_quota.h", + "include/grpcpp/resource_quota_impl.h", "include/grpcpp/security/auth_context.h", "include/grpcpp/security/auth_metadata_processor.h", "include/grpcpp/security/credentials.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ccda85b125..40719422aa8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3014,6 +3014,7 @@ foreach(_hdr include/grpcpp/impl/server_initializer.h include/grpcpp/impl/service_type.h include/grpcpp/resource_quota.h + include/grpcpp/resource_quota_impl.h include/grpcpp/security/auth_context.h include/grpcpp/security/auth_metadata_processor.h include/grpcpp/security/credentials.h @@ -3604,6 +3605,7 @@ foreach(_hdr include/grpcpp/impl/server_initializer.h include/grpcpp/impl/service_type.h include/grpcpp/resource_quota.h + include/grpcpp/resource_quota_impl.h include/grpcpp/security/auth_context.h include/grpcpp/security/auth_metadata_processor.h include/grpcpp/security/credentials.h @@ -4559,6 +4561,7 @@ foreach(_hdr include/grpcpp/impl/server_initializer.h include/grpcpp/impl/service_type.h include/grpcpp/resource_quota.h + include/grpcpp/resource_quota_impl.h include/grpcpp/security/auth_context.h include/grpcpp/security/auth_metadata_processor.h include/grpcpp/security/credentials.h diff --git a/Makefile b/Makefile index 91516de9a27..f47184b3436 100644 --- a/Makefile +++ b/Makefile @@ -5438,6 +5438,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ + include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ @@ -6037,6 +6038,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ + include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ @@ -6949,6 +6951,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ + include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ diff --git a/build.yaml b/build.yaml index 02ecaa221e6..cfd6cdb18a4 100644 --- a/build.yaml +++ b/build.yaml @@ -1360,6 +1360,7 @@ filegroups: - include/grpcpp/impl/server_initializer.h - include/grpcpp/impl/service_type.h - include/grpcpp/resource_quota.h + - include/grpcpp/resource_quota_impl.h - include/grpcpp/security/auth_context.h - include/grpcpp/security/auth_metadata_processor.h - include/grpcpp/security/credentials.h diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index e755b7aa602..2d50f28ff2a 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -105,6 +105,7 @@ Pod::Spec.new do |s| 'include/grpcpp/impl/server_initializer.h', 'include/grpcpp/impl/service_type.h', 'include/grpcpp/resource_quota.h', + 'include/grpcpp/resource_quota_impl.h', 'include/grpcpp/security/auth_context.h', 'include/grpcpp/security/auth_metadata_processor.h', 'include/grpcpp/security/credentials.h', diff --git a/include/grpcpp/resource_quota.h b/include/grpcpp/resource_quota.h index 50bd1cb849a..333767b95c5 100644 --- a/include/grpcpp/resource_quota.h +++ b/include/grpcpp/resource_quota.h @@ -1,6 +1,6 @@ /* * - * Copyright 2016 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,50 +19,11 @@ #ifndef GRPCPP_RESOURCE_QUOTA_H #define GRPCPP_RESOURCE_QUOTA_H -struct grpc_resource_quota; - -#include -#include +#include namespace grpc { -/// ResourceQuota represents a bound on memory and thread usage by the gRPC -/// library. A ResourceQuota can be attached to a server (via \a ServerBuilder), -/// or a client channel (via \a ChannelArguments). -/// gRPC will attempt to keep memory and threads used by all attached entities -/// below the ResourceQuota bound. -class ResourceQuota final : private GrpcLibraryCodegen { - public: - /// \param name - a unique name for this ResourceQuota. - explicit ResourceQuota(const grpc::string& name); - ResourceQuota(); - ~ResourceQuota(); - - /// Resize this \a ResourceQuota to a new size. If \a new_size is smaller - /// than the current size of the pool, memory usage will be monotonically - /// decreased until it falls under \a new_size. - /// No time bound is given for this to occur however. - ResourceQuota& Resize(size_t new_size); - - /// Set the max number of threads that can be allocated from this - /// ResourceQuota object. - /// - /// If the new_max_threads value is smaller than the current value, no new - /// threads are allocated until the number of active threads fall below - /// new_max_threads. There is no time bound on when this may happen i.e none - /// of the current threads are forcefully destroyed and all threads run their - /// normal course. - ResourceQuota& SetMaxThreads(int new_max_threads); - - grpc_resource_quota* c_resource_quota() const { return impl_; } - - private: - ResourceQuota(const ResourceQuota& rhs); - ResourceQuota& operator=(const ResourceQuota& rhs); - - grpc_resource_quota* const impl_; -}; - +typedef ::grpc_impl::ResourceQuota ResourceQuota; } // namespace grpc #endif // GRPCPP_RESOURCE_QUOTA_H diff --git a/include/grpcpp/resource_quota_impl.h b/include/grpcpp/resource_quota_impl.h new file mode 100644 index 00000000000..16c0e35385b --- /dev/null +++ b/include/grpcpp/resource_quota_impl.h @@ -0,0 +1,68 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_RESOURCE_QUOTA_IMPL_H +#define GRPCPP_RESOURCE_QUOTA_IMPL_H + +struct grpc_resource_quota; + +#include +#include + +namespace grpc_impl { + +/// ResourceQuota represents a bound on memory and thread usage by the gRPC +/// library. A ResourceQuota can be attached to a server (via \a ServerBuilder), +/// or a client channel (via \a ChannelArguments). +/// gRPC will attempt to keep memory and threads used by all attached entities +/// below the ResourceQuota bound. +class ResourceQuota final : private ::grpc::GrpcLibraryCodegen { + public: + /// \param name - a unique name for this ResourceQuota. + explicit ResourceQuota(const grpc::string& name); + ResourceQuota(); + ~ResourceQuota(); + + /// Resize this \a ResourceQuota to a new size. If \a new_size is smaller + /// than the current size of the pool, memory usage will be monotonically + /// decreased until it falls under \a new_size. + /// No time bound is given for this to occur however. + ResourceQuota& Resize(size_t new_size); + + /// Set the max number of threads that can be allocated from this + /// ResourceQuota object. + /// + /// If the new_max_threads value is smaller than the current value, no new + /// threads are allocated until the number of active threads fall below + /// new_max_threads. There is no time bound on when this may happen i.e none + /// of the current threads are forcefully destroyed and all threads run their + /// normal course. + ResourceQuota& SetMaxThreads(int new_max_threads); + + grpc_resource_quota* c_resource_quota() const { return impl_; } + + private: + ResourceQuota(const ResourceQuota& rhs); + ResourceQuota& operator=(const ResourceQuota& rhs); + + grpc_resource_quota* const impl_; +}; + +} // namespace grpc_impl + +#endif // GRPCPP_RESOURCE_QUOTA_IMPL_H diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h index 498e5b7bb31..4c00f021d11 100644 --- a/include/grpcpp/server_builder.h +++ b/include/grpcpp/server_builder.h @@ -35,10 +35,14 @@ struct grpc_resource_quota; +namespace grpc_impl { + +class ResourceQuota; +} + namespace grpc { class AsyncGenericService; -class ResourceQuota; class CompletionQueue; class Server; class ServerCompletionQueue; @@ -186,7 +190,8 @@ class ServerBuilder { grpc_compression_algorithm algorithm); /// Set the attached buffer pool for this server - ServerBuilder& SetResourceQuota(const ResourceQuota& resource_quota); + ServerBuilder& SetResourceQuota( + const ::grpc_impl::ResourceQuota& resource_quota); ServerBuilder& SetOption(std::unique_ptr option); diff --git a/include/grpcpp/support/channel_arguments.h b/include/grpcpp/support/channel_arguments.h index 217929d4aca..48ae4246462 100644 --- a/include/grpcpp/support/channel_arguments.h +++ b/include/grpcpp/support/channel_arguments.h @@ -26,13 +26,16 @@ #include #include +namespace grpc_impl { + +class ResourceQuota; +} + namespace grpc { namespace testing { class ChannelArgumentsTest; } // namespace testing -class ResourceQuota; - /// Options for channel creation. The user can use generic setters to pass /// key value pairs down to C channel creation code. For gRPC related options, /// concrete setters are provided. @@ -83,7 +86,7 @@ class ChannelArguments { void SetUserAgentPrefix(const grpc::string& user_agent_prefix); /// Set the buffer pool to be attached to the constructed channel. - void SetResourceQuota(const ResourceQuota& resource_quota); + void SetResourceQuota(const ::grpc_impl::ResourceQuota& resource_quota); /// Set the max receive and send message sizes. void SetMaxReceiveMessageSize(int size); diff --git a/src/cpp/common/channel_arguments.cc b/src/cpp/common/channel_arguments.cc index 214d72f853f..c3d75054b9b 100644 --- a/src/cpp/common/channel_arguments.cc +++ b/src/cpp/common/channel_arguments.cc @@ -143,7 +143,7 @@ void ChannelArguments::SetUserAgentPrefix( } void ChannelArguments::SetResourceQuota( - const grpc::ResourceQuota& resource_quota) { + const grpc_impl::ResourceQuota& resource_quota) { SetPointerWithVtable(GRPC_ARG_RESOURCE_QUOTA, resource_quota.c_resource_quota(), grpc_resource_quota_arg_vtable()); diff --git a/src/cpp/common/resource_quota_cc.cc b/src/cpp/common/resource_quota_cc.cc index 276e5f79548..4fab2975d89 100644 --- a/src/cpp/common/resource_quota_cc.cc +++ b/src/cpp/common/resource_quota_cc.cc @@ -19,7 +19,7 @@ #include #include -namespace grpc { +namespace grpc_impl { ResourceQuota::ResourceQuota() : impl_(grpc_resource_quota_create(nullptr)) {} @@ -37,4 +37,4 @@ ResourceQuota& ResourceQuota::SetMaxThreads(int new_max_threads) { grpc_resource_quota_set_max_threads(impl_, new_max_threads); return *this; } -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index cd0e516d9a3..f60c77dc8d6 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -29,6 +29,11 @@ #include "src/core/lib/gpr/useful.h" #include "src/cpp/server/thread_pool_interface.h" +namespace grpc_impl { + +class ResourceQuota; +} + namespace grpc { static std::vector (*)()>* @@ -164,7 +169,7 @@ ServerBuilder& ServerBuilder::SetDefaultCompressionAlgorithm( } ServerBuilder& ServerBuilder::SetResourceQuota( - const grpc::ResourceQuota& resource_quota) { + const grpc_impl::ResourceQuota& resource_quota) { if (resource_quota_ != nullptr) { grpc_resource_quota_unref(resource_quota_); } diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index f58a472bfaf..f7b9ee4b0b0 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -64,6 +64,11 @@ using std::chrono::system_clock; } \ } while (0) +namespace grpc_impl { + +class ResourceQuota; +} + namespace grpc { namespace testing { namespace { diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc index e30ce0dbcbf..e308e591d1a 100644 --- a/test/cpp/end2end/thread_stress_test.cc +++ b/test/cpp/end2end/thread_stress_test.cc @@ -48,6 +48,11 @@ const int kNumAsyncReceiveThreads = 50; const int kNumAsyncServerThreads = 50; const int kNumRpcs = 1000; // Number of RPCs per thread +namespace grpc_impl { + +class ResourceQuota; +} + namespace grpc { namespace testing { diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h index 89b0e3af4b2..3aec8644a94 100644 --- a/test/cpp/qps/server.h +++ b/test/cpp/qps/server.h @@ -34,6 +34,11 @@ #include "test/cpp/qps/usage_timer.h" #include "test/cpp/util/test_credentials_provider.h" +namespace grpc_impl { + +class ResourceQuota; +} + namespace grpc { namespace testing { diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc index a5f8347c269..9343fd311e1 100644 --- a/test/cpp/qps/server_async.cc +++ b/test/cpp/qps/server_async.cc @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 9f17a25298a..367160a0ca9 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -995,6 +995,7 @@ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ +include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index c0078bf2764..4c1ba9d4f9d 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -997,6 +997,7 @@ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ +include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 7a72a885336..96fa00e387e 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -11391,6 +11391,7 @@ "include/grpcpp/impl/server_initializer.h", "include/grpcpp/impl/service_type.h", "include/grpcpp/resource_quota.h", + "include/grpcpp/resource_quota_impl.h", "include/grpcpp/security/auth_context.h", "include/grpcpp/security/auth_metadata_processor.h", "include/grpcpp/security/credentials.h", @@ -11500,6 +11501,7 @@ "include/grpcpp/impl/server_initializer.h", "include/grpcpp/impl/service_type.h", "include/grpcpp/resource_quota.h", + "include/grpcpp/resource_quota_impl.h", "include/grpcpp/security/auth_context.h", "include/grpcpp/security/auth_metadata_processor.h", "include/grpcpp/security/credentials.h", From d8d8bec7c8a254b1f8bc152b71b0b1c2b41bfe3f Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Fri, 1 Mar 2019 13:32:36 -0800 Subject: [PATCH 014/242] Moving ::grpc::ResourceQuota to ::grpc_impl::ResouceQuota This change moves ResourceQuota class fron grpc namespace to grpc_impl namespace. Signed-off-by: Karthik Ravi Shankar --- BUILD | 3 +- CMakeLists.txt | 3 + Makefile | 3 + build.yaml | 1 + gRPC-C++.podspec | 1 + include/grpcpp/resource_quota.h | 45 +------------- include/grpcpp/resource_quota_impl.h | 68 ++++++++++++++++++++++ include/grpcpp/server_builder.h | 8 ++- include/grpcpp/support/channel_arguments.h | 8 ++- src/cpp/common/channel_arguments.cc | 2 +- src/cpp/common/resource_quota_cc.cc | 2 +- src/cpp/server/server_builder.cc | 7 ++- test/cpp/end2end/end2end_test.cc | 5 ++ test/cpp/end2end/thread_stress_test.cc | 5 ++ test/cpp/qps/server.h | 5 ++ test/cpp/qps/server_async.cc | 2 +- 16 files changed, 117 insertions(+), 51 deletions(-) create mode 100644 include/grpcpp/resource_quota_impl.h diff --git a/BUILD b/BUILD index 0b6fff354f4..e60ce691443 100644 --- a/BUILD +++ b/BUILD @@ -192,8 +192,8 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpc++/impl/service_type.h", "include/grpc++/impl/sync_cxx11.h", "include/grpc++/impl/sync_no_cxx11.h", - "include/grpc++/resource_quota.h", "include/grpc++/security/auth_context.h", + "include/grpc++/resource_quota.h", "include/grpc++/security/auth_metadata_processor.h", "include/grpc++/security/credentials.h", "include/grpc++/security/server_credentials.h", @@ -241,6 +241,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/impl/sync_cxx11.h", "include/grpcpp/impl/sync_no_cxx11.h", "include/grpcpp/resource_quota.h", + "include/grpcpp/resource_quota_impl.h", "include/grpcpp/security/auth_context.h", "include/grpcpp/security/auth_metadata_processor.h", "include/grpcpp/security/credentials.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 0030c9eb9af..614fd2efca1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3014,6 +3014,7 @@ foreach(_hdr include/grpcpp/impl/server_initializer.h include/grpcpp/impl/service_type.h include/grpcpp/resource_quota.h + include/grpcpp/resource_quota_impl.h include/grpcpp/security/auth_context.h include/grpcpp/security/auth_metadata_processor.h include/grpcpp/security/credentials.h @@ -3604,6 +3605,7 @@ foreach(_hdr include/grpcpp/impl/server_initializer.h include/grpcpp/impl/service_type.h include/grpcpp/resource_quota.h + include/grpcpp/resource_quota_impl.h include/grpcpp/security/auth_context.h include/grpcpp/security/auth_metadata_processor.h include/grpcpp/security/credentials.h @@ -4563,6 +4565,7 @@ foreach(_hdr include/grpcpp/impl/server_initializer.h include/grpcpp/impl/service_type.h include/grpcpp/resource_quota.h + include/grpcpp/resource_quota_impl.h include/grpcpp/security/auth_context.h include/grpcpp/security/auth_metadata_processor.h include/grpcpp/security/credentials.h diff --git a/Makefile b/Makefile index 5a31d648b32..7ad32e1291f 100644 --- a/Makefile +++ b/Makefile @@ -5438,6 +5438,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ + include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ @@ -6037,6 +6038,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ + include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ @@ -6949,6 +6951,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ + include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ diff --git a/build.yaml b/build.yaml index d8322b176b7..82e652878bd 100644 --- a/build.yaml +++ b/build.yaml @@ -1360,6 +1360,7 @@ filegroups: - include/grpcpp/impl/server_initializer.h - include/grpcpp/impl/service_type.h - include/grpcpp/resource_quota.h + - include/grpcpp/resource_quota_impl.h - include/grpcpp/security/auth_context.h - include/grpcpp/security/auth_metadata_processor.h - include/grpcpp/security/credentials.h diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index e755b7aa602..2d50f28ff2a 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -105,6 +105,7 @@ Pod::Spec.new do |s| 'include/grpcpp/impl/server_initializer.h', 'include/grpcpp/impl/service_type.h', 'include/grpcpp/resource_quota.h', + 'include/grpcpp/resource_quota_impl.h', 'include/grpcpp/security/auth_context.h', 'include/grpcpp/security/auth_metadata_processor.h', 'include/grpcpp/security/credentials.h', diff --git a/include/grpcpp/resource_quota.h b/include/grpcpp/resource_quota.h index 50bd1cb849a..333767b95c5 100644 --- a/include/grpcpp/resource_quota.h +++ b/include/grpcpp/resource_quota.h @@ -1,6 +1,6 @@ /* * - * Copyright 2016 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,50 +19,11 @@ #ifndef GRPCPP_RESOURCE_QUOTA_H #define GRPCPP_RESOURCE_QUOTA_H -struct grpc_resource_quota; - -#include -#include +#include namespace grpc { -/// ResourceQuota represents a bound on memory and thread usage by the gRPC -/// library. A ResourceQuota can be attached to a server (via \a ServerBuilder), -/// or a client channel (via \a ChannelArguments). -/// gRPC will attempt to keep memory and threads used by all attached entities -/// below the ResourceQuota bound. -class ResourceQuota final : private GrpcLibraryCodegen { - public: - /// \param name - a unique name for this ResourceQuota. - explicit ResourceQuota(const grpc::string& name); - ResourceQuota(); - ~ResourceQuota(); - - /// Resize this \a ResourceQuota to a new size. If \a new_size is smaller - /// than the current size of the pool, memory usage will be monotonically - /// decreased until it falls under \a new_size. - /// No time bound is given for this to occur however. - ResourceQuota& Resize(size_t new_size); - - /// Set the max number of threads that can be allocated from this - /// ResourceQuota object. - /// - /// If the new_max_threads value is smaller than the current value, no new - /// threads are allocated until the number of active threads fall below - /// new_max_threads. There is no time bound on when this may happen i.e none - /// of the current threads are forcefully destroyed and all threads run their - /// normal course. - ResourceQuota& SetMaxThreads(int new_max_threads); - - grpc_resource_quota* c_resource_quota() const { return impl_; } - - private: - ResourceQuota(const ResourceQuota& rhs); - ResourceQuota& operator=(const ResourceQuota& rhs); - - grpc_resource_quota* const impl_; -}; - +typedef ::grpc_impl::ResourceQuota ResourceQuota; } // namespace grpc #endif // GRPCPP_RESOURCE_QUOTA_H diff --git a/include/grpcpp/resource_quota_impl.h b/include/grpcpp/resource_quota_impl.h new file mode 100644 index 00000000000..16c0e35385b --- /dev/null +++ b/include/grpcpp/resource_quota_impl.h @@ -0,0 +1,68 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_RESOURCE_QUOTA_IMPL_H +#define GRPCPP_RESOURCE_QUOTA_IMPL_H + +struct grpc_resource_quota; + +#include +#include + +namespace grpc_impl { + +/// ResourceQuota represents a bound on memory and thread usage by the gRPC +/// library. A ResourceQuota can be attached to a server (via \a ServerBuilder), +/// or a client channel (via \a ChannelArguments). +/// gRPC will attempt to keep memory and threads used by all attached entities +/// below the ResourceQuota bound. +class ResourceQuota final : private ::grpc::GrpcLibraryCodegen { + public: + /// \param name - a unique name for this ResourceQuota. + explicit ResourceQuota(const grpc::string& name); + ResourceQuota(); + ~ResourceQuota(); + + /// Resize this \a ResourceQuota to a new size. If \a new_size is smaller + /// than the current size of the pool, memory usage will be monotonically + /// decreased until it falls under \a new_size. + /// No time bound is given for this to occur however. + ResourceQuota& Resize(size_t new_size); + + /// Set the max number of threads that can be allocated from this + /// ResourceQuota object. + /// + /// If the new_max_threads value is smaller than the current value, no new + /// threads are allocated until the number of active threads fall below + /// new_max_threads. There is no time bound on when this may happen i.e none + /// of the current threads are forcefully destroyed and all threads run their + /// normal course. + ResourceQuota& SetMaxThreads(int new_max_threads); + + grpc_resource_quota* c_resource_quota() const { return impl_; } + + private: + ResourceQuota(const ResourceQuota& rhs); + ResourceQuota& operator=(const ResourceQuota& rhs); + + grpc_resource_quota* const impl_; +}; + +} // namespace grpc_impl + +#endif // GRPCPP_RESOURCE_QUOTA_IMPL_H diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h index 498e5b7bb31..662581a40bb 100644 --- a/include/grpcpp/server_builder.h +++ b/include/grpcpp/server_builder.h @@ -35,10 +35,14 @@ struct grpc_resource_quota; +namespace grpc_impl { + +class ResourceQuota; +} + namespace grpc { class AsyncGenericService; -class ResourceQuota; class CompletionQueue; class Server; class ServerCompletionQueue; @@ -186,7 +190,7 @@ class ServerBuilder { grpc_compression_algorithm algorithm); /// Set the attached buffer pool for this server - ServerBuilder& SetResourceQuota(const ResourceQuota& resource_quota); + ServerBuilder& SetResourceQuota(const ::grpc_impl::ResourceQuota& resource_quota); ServerBuilder& SetOption(std::unique_ptr option); diff --git a/include/grpcpp/support/channel_arguments.h b/include/grpcpp/support/channel_arguments.h index 217929d4aca..e0014977cff 100644 --- a/include/grpcpp/support/channel_arguments.h +++ b/include/grpcpp/support/channel_arguments.h @@ -26,12 +26,16 @@ #include #include +namespace grpc_impl { + +class ResourceQuota; +} + namespace grpc { namespace testing { class ChannelArgumentsTest; } // namespace testing -class ResourceQuota; /// Options for channel creation. The user can use generic setters to pass /// key value pairs down to C channel creation code. For gRPC related options, @@ -83,7 +87,7 @@ class ChannelArguments { void SetUserAgentPrefix(const grpc::string& user_agent_prefix); /// Set the buffer pool to be attached to the constructed channel. - void SetResourceQuota(const ResourceQuota& resource_quota); + void SetResourceQuota(const ::grpc_impl::ResourceQuota& resource_quota); /// Set the max receive and send message sizes. void SetMaxReceiveMessageSize(int size); diff --git a/src/cpp/common/channel_arguments.cc b/src/cpp/common/channel_arguments.cc index 214d72f853f..c3d75054b9b 100644 --- a/src/cpp/common/channel_arguments.cc +++ b/src/cpp/common/channel_arguments.cc @@ -143,7 +143,7 @@ void ChannelArguments::SetUserAgentPrefix( } void ChannelArguments::SetResourceQuota( - const grpc::ResourceQuota& resource_quota) { + const grpc_impl::ResourceQuota& resource_quota) { SetPointerWithVtable(GRPC_ARG_RESOURCE_QUOTA, resource_quota.c_resource_quota(), grpc_resource_quota_arg_vtable()); diff --git a/src/cpp/common/resource_quota_cc.cc b/src/cpp/common/resource_quota_cc.cc index 276e5f79548..bbf42fd1f3e 100644 --- a/src/cpp/common/resource_quota_cc.cc +++ b/src/cpp/common/resource_quota_cc.cc @@ -19,7 +19,7 @@ #include #include -namespace grpc { +namespace grpc_impl { ResourceQuota::ResourceQuota() : impl_(grpc_resource_quota_create(nullptr)) {} diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index cd0e516d9a3..f60c77dc8d6 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -29,6 +29,11 @@ #include "src/core/lib/gpr/useful.h" #include "src/cpp/server/thread_pool_interface.h" +namespace grpc_impl { + +class ResourceQuota; +} + namespace grpc { static std::vector (*)()>* @@ -164,7 +169,7 @@ ServerBuilder& ServerBuilder::SetDefaultCompressionAlgorithm( } ServerBuilder& ServerBuilder::SetResourceQuota( - const grpc::ResourceQuota& resource_quota) { + const grpc_impl::ResourceQuota& resource_quota) { if (resource_quota_ != nullptr) { grpc_resource_quota_unref(resource_quota_); } diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index f58a472bfaf..f7b9ee4b0b0 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -64,6 +64,11 @@ using std::chrono::system_clock; } \ } while (0) +namespace grpc_impl { + +class ResourceQuota; +} + namespace grpc { namespace testing { namespace { diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc index e30ce0dbcbf..e308e591d1a 100644 --- a/test/cpp/end2end/thread_stress_test.cc +++ b/test/cpp/end2end/thread_stress_test.cc @@ -48,6 +48,11 @@ const int kNumAsyncReceiveThreads = 50; const int kNumAsyncServerThreads = 50; const int kNumRpcs = 1000; // Number of RPCs per thread +namespace grpc_impl { + +class ResourceQuota; +} + namespace grpc { namespace testing { diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h index 89b0e3af4b2..3aec8644a94 100644 --- a/test/cpp/qps/server.h +++ b/test/cpp/qps/server.h @@ -34,6 +34,11 @@ #include "test/cpp/qps/usage_timer.h" #include "test/cpp/util/test_credentials_provider.h" +namespace grpc_impl { + +class ResourceQuota; +} + namespace grpc { namespace testing { diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc index a5f8347c269..8f20de7e714 100644 --- a/test/cpp/qps/server_async.cc +++ b/test/cpp/qps/server_async.cc @@ -27,7 +27,7 @@ #include #include #include -#include +//#include #include #include #include From 90edf47fe938886c18dbfac447991a6f252124be Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Thu, 14 Mar 2019 14:26:25 -0700 Subject: [PATCH 015/242] Move server_posix from grpc to grpc_impl namespace --- BUILD | 1 + CMakeLists.txt | 3 ++ Makefile | 3 ++ include/grpcpp/server_builder.h | 3 +- include/grpcpp/server_posix.h | 20 +---------- include/grpcpp/server_posix_impl.h | 42 ++++++++++++++++++++++ include/grpcpp/support/channel_arguments.h | 1 - src/cpp/common/resource_quota_cc.cc | 2 +- 8 files changed, 53 insertions(+), 22 deletions(-) create mode 100644 include/grpcpp/server_posix_impl.h diff --git a/BUILD b/BUILD index e60ce691443..9070a66c978 100644 --- a/BUILD +++ b/BUILD @@ -250,6 +250,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/server_builder.h", "include/grpcpp/server_context.h", "include/grpcpp/server_posix.h", + "include/grpcpp/server_posix_impl.h", "include/grpcpp/support/async_stream.h", "include/grpcpp/support/async_unary_call.h", "include/grpcpp/support/byte_buffer.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 614fd2efca1..a49a5b1f938 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3023,6 +3023,7 @@ foreach(_hdr include/grpcpp/server_builder.h include/grpcpp/server_context.h include/grpcpp/server_posix.h + include/grpcpp/server_posix_impl.h include/grpcpp/support/async_stream.h include/grpcpp/support/async_unary_call.h include/grpcpp/support/byte_buffer.h @@ -3614,6 +3615,7 @@ foreach(_hdr include/grpcpp/server_builder.h include/grpcpp/server_context.h include/grpcpp/server_posix.h + include/grpcpp/server_posix_impl.h include/grpcpp/support/async_stream.h include/grpcpp/support/async_unary_call.h include/grpcpp/support/byte_buffer.h @@ -4574,6 +4576,7 @@ foreach(_hdr include/grpcpp/server_builder.h include/grpcpp/server_context.h include/grpcpp/server_posix.h + include/grpcpp/server_posix_impl.h include/grpcpp/support/async_stream.h include/grpcpp/support/async_unary_call.h include/grpcpp/support/byte_buffer.h diff --git a/Makefile b/Makefile index 7ad32e1291f..f65ce2addf0 100644 --- a/Makefile +++ b/Makefile @@ -5447,6 +5447,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ include/grpcpp/server_posix.h \ + include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ @@ -6047,6 +6048,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ include/grpcpp/server_posix.h \ + include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ @@ -6960,6 +6962,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ include/grpcpp/server_posix.h \ + include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h index 662581a40bb..4c00f021d11 100644 --- a/include/grpcpp/server_builder.h +++ b/include/grpcpp/server_builder.h @@ -190,7 +190,8 @@ class ServerBuilder { grpc_compression_algorithm algorithm); /// Set the attached buffer pool for this server - ServerBuilder& SetResourceQuota(const ::grpc_impl::ResourceQuota& resource_quota); + ServerBuilder& SetResourceQuota( + const ::grpc_impl::ResourceQuota& resource_quota); ServerBuilder& SetOption(std::unique_ptr option); diff --git a/include/grpcpp/server_posix.h b/include/grpcpp/server_posix.h index ef3ee01a5c6..7b46967a8ba 100644 --- a/include/grpcpp/server_posix.h +++ b/include/grpcpp/server_posix.h @@ -19,24 +19,6 @@ #ifndef GRPCPP_SERVER_POSIX_H #define GRPCPP_SERVER_POSIX_H -#include - -#include -#include - -namespace grpc { - -#ifdef GPR_SUPPORT_CHANNELS_FROM_FD - -/// Add a new client to a \a Server communicating over the given -/// file descriptor. -/// -/// \param server The server to add the client to. -/// \param fd The file descriptor representing a socket. -void AddInsecureChannelFromFd(Server* server, int fd); - -#endif // GPR_SUPPORT_CHANNELS_FROM_FD - -} // namespace grpc +#include #endif // GRPCPP_SERVER_POSIX_H diff --git a/include/grpcpp/server_posix_impl.h b/include/grpcpp/server_posix_impl.h new file mode 100644 index 00000000000..c29af271fe9 --- /dev/null +++ b/include/grpcpp/server_posix_impl.h @@ -0,0 +1,42 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_SERVER_POSIX_IMPL_H +#define GRPCPP_SERVER_POSIX_IMPL_H + +#include + +#include +#include + +namespace grpc_impl { + +#ifdef GPR_SUPPORT_CHANNELS_FROM_FD + +/// Add a new client to a \a Server communicating over the given +/// file descriptor. +/// +/// \param server The server to add the client to. +/// \param fd The file descriptor representing a socket. +void AddInsecureChannelFromFd(grpc::Server* server, int fd); + +#endif // GPR_SUPPORT_CHANNELS_FROM_FD + +} // namespace grpc + +#endif // GRPCPP_SERVER_POSIX_IMPL_H diff --git a/include/grpcpp/support/channel_arguments.h b/include/grpcpp/support/channel_arguments.h index e0014977cff..48ae4246462 100644 --- a/include/grpcpp/support/channel_arguments.h +++ b/include/grpcpp/support/channel_arguments.h @@ -36,7 +36,6 @@ namespace testing { class ChannelArgumentsTest; } // namespace testing - /// Options for channel creation. The user can use generic setters to pass /// key value pairs down to C channel creation code. For gRPC related options, /// concrete setters are provided. diff --git a/src/cpp/common/resource_quota_cc.cc b/src/cpp/common/resource_quota_cc.cc index bbf42fd1f3e..4fab2975d89 100644 --- a/src/cpp/common/resource_quota_cc.cc +++ b/src/cpp/common/resource_quota_cc.cc @@ -37,4 +37,4 @@ ResourceQuota& ResourceQuota::SetMaxThreads(int new_max_threads) { grpc_resource_quota_set_max_threads(impl_, new_max_threads); return *this; } -} // namespace grpc +} // namespace grpc_impl From 2c574381037816ee8bdf90fe388c3f6c7ba27506 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Thu, 14 Mar 2019 17:07:36 -0700 Subject: [PATCH 016/242] Fix errors from tests --- CMakeLists.txt | 3 --- Makefile | 3 --- tools/doxygen/Doxyfile.c++ | 1 + tools/doxygen/Doxyfile.c++.internal | 1 + tools/run_tests/generated/sources_and_headers.json | 2 ++ 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a49a5b1f938..614fd2efca1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3023,7 +3023,6 @@ foreach(_hdr include/grpcpp/server_builder.h include/grpcpp/server_context.h include/grpcpp/server_posix.h - include/grpcpp/server_posix_impl.h include/grpcpp/support/async_stream.h include/grpcpp/support/async_unary_call.h include/grpcpp/support/byte_buffer.h @@ -3615,7 +3614,6 @@ foreach(_hdr include/grpcpp/server_builder.h include/grpcpp/server_context.h include/grpcpp/server_posix.h - include/grpcpp/server_posix_impl.h include/grpcpp/support/async_stream.h include/grpcpp/support/async_unary_call.h include/grpcpp/support/byte_buffer.h @@ -4576,7 +4574,6 @@ foreach(_hdr include/grpcpp/server_builder.h include/grpcpp/server_context.h include/grpcpp/server_posix.h - include/grpcpp/server_posix_impl.h include/grpcpp/support/async_stream.h include/grpcpp/support/async_unary_call.h include/grpcpp/support/byte_buffer.h diff --git a/Makefile b/Makefile index f65ce2addf0..7ad32e1291f 100644 --- a/Makefile +++ b/Makefile @@ -5447,7 +5447,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ include/grpcpp/server_posix.h \ - include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ @@ -6048,7 +6047,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ include/grpcpp/server_posix.h \ - include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ @@ -6962,7 +6960,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ include/grpcpp/server_posix.h \ - include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 9f17a25298a..367160a0ca9 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -995,6 +995,7 @@ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ +include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index c0078bf2764..4c1ba9d4f9d 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -997,6 +997,7 @@ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ +include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 8adde9ec602..bcf2cf4f5ec 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -11411,6 +11411,7 @@ "include/grpcpp/impl/server_initializer.h", "include/grpcpp/impl/service_type.h", "include/grpcpp/resource_quota.h", + "include/grpcpp/resource_quota_impl.h", "include/grpcpp/security/auth_context.h", "include/grpcpp/security/auth_metadata_processor.h", "include/grpcpp/security/credentials.h", @@ -11520,6 +11521,7 @@ "include/grpcpp/impl/server_initializer.h", "include/grpcpp/impl/service_type.h", "include/grpcpp/resource_quota.h", + "include/grpcpp/resource_quota_impl.h", "include/grpcpp/security/auth_context.h", "include/grpcpp/security/auth_metadata_processor.h", "include/grpcpp/security/credentials.h", From 49164c8aebb464b39c110832b8afbdf8172fea01 Mon Sep 17 00:00:00 2001 From: Adam Lemmon Date: Fri, 15 Mar 2019 09:45:30 -0600 Subject: [PATCH 017/242] Update Channel.cs Simple spelling or wording fixes to make comments read more cleanly --- src/csharp/Grpc.Core/Channel.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs index 7ce929dfa31..97f79b0fb4f 100644 --- a/src/csharp/Grpc.Core/Channel.cs +++ b/src/csharp/Grpc.Core/Channel.cs @@ -59,7 +59,7 @@ namespace Grpc.Core /// /// Creates a channel that connects to a specific host. - /// Port will default to 80 for an unsecure channel and to 443 for a secure channel. + /// Port will default to 80 for an unsecure channel or to 443 for a secure channel. /// /// Target of the channel. /// Credentials to secure the channel. @@ -112,7 +112,7 @@ namespace Grpc.Core /// /// Gets current connectivity state of this channel. - /// After channel is has been shutdown, ChannelState.Shutdown will be returned. + /// After channel has been shutdown, ChannelState.Shutdown will be returned. /// public ChannelState State { @@ -132,7 +132,7 @@ namespace Grpc.Core /// /// Returned tasks completes once channel state has become different from /// given lastObservedState. - /// If deadline is reached or and error occurs, returned task is cancelled. + /// If deadline is reached or an error occurs, returned task is cancelled. /// public async Task WaitForStateChangedAsync(ChannelState lastObservedState, DateTime? deadline = null) { From f66b6547959e1964932872e15498042156ee8c08 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Fri, 15 Mar 2019 11:30:23 -0700 Subject: [PATCH 018/242] Revert "Revert "Fold opencensus into grpc_impl namespace"" --- BUILD | 1 + include/grpcpp/opencensus.h | 26 +------- include/grpcpp/opencensus_impl.h | 51 +++++++++++++++ src/cpp/ext/filters/census/grpc_plugin.cc | 65 ++++++++++--------- src/cpp/ext/filters/census/grpc_plugin.h | 6 +- src/cpp/ext/filters/census/views.cc | 32 ++++----- .../census/stats_plugin_end2end_test.cc | 2 +- .../microbenchmarks/bm_opencensus_plugin.cc | 6 +- 8 files changed, 114 insertions(+), 75 deletions(-) create mode 100644 include/grpcpp/opencensus_impl.h diff --git a/BUILD b/BUILD index 835edbfb48f..afeacf0239a 100644 --- a/BUILD +++ b/BUILD @@ -2283,6 +2283,7 @@ grpc_cc_library( ], hdrs = [ "include/grpcpp/opencensus.h", + "include/grpcpp/opencensus_impl.h", "src/cpp/ext/filters/census/channel_filter.h", "src/cpp/ext/filters/census/client_filter.h", "src/cpp/ext/filters/census/context.h", diff --git a/include/grpcpp/opencensus.h b/include/grpcpp/opencensus.h index 29b221f7674..3b170336834 100644 --- a/include/grpcpp/opencensus.h +++ b/include/grpcpp/opencensus.h @@ -19,30 +19,6 @@ #ifndef GRPCPP_OPENCENSUS_H #define GRPCPP_OPENCENSUS_H -#include "opencensus/trace/span.h" - -namespace grpc { -// These symbols in this file will not be included in the binary unless -// grpc_opencensus_plugin build target was added as a dependency. At the moment -// it is only setup to be built with Bazel. - -// Registers the OpenCensus plugin with gRPC, so that it will be used for future -// RPCs. This must be called before any views are created. -void RegisterOpenCensusPlugin(); - -// RPC stats definitions, defined by -// https://github.com/census-instrumentation/opencensus-specs/blob/master/stats/gRPC.md - -// Registers the cumulative gRPC views so that they will be exported by any -// registered stats exporter. For on-task stats, construct a View using the -// ViewDescriptors below. -void RegisterOpenCensusViewsForExport(); - -class ServerContext; - -// Returns the tracing Span for the current RPC. -::opencensus::trace::Span GetSpanFromServerContext(ServerContext* context); - -} // namespace grpc +#include "grpcpp/opencensus_impl.h" #endif // GRPCPP_OPENCENSUS_H diff --git a/include/grpcpp/opencensus_impl.h b/include/grpcpp/opencensus_impl.h new file mode 100644 index 00000000000..631d2b861fd --- /dev/null +++ b/include/grpcpp/opencensus_impl.h @@ -0,0 +1,51 @@ +/* + * + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_OPENCENSUS_IMPL_H +#define GRPCPP_OPENCENSUS_IMPL_H + +#include "opencensus/trace/span.h" + +namespace grpc { + +class ServerContext; +} +namespace grpc_impl { +// These symbols in this file will not be included in the binary unless +// grpc_opencensus_plugin build target was added as a dependency. At the moment +// it is only setup to be built with Bazel. + +// Registers the OpenCensus plugin with gRPC, so that it will be used for future +// RPCs. This must be called before any views are created. +void RegisterOpenCensusPlugin(); + +// RPC stats definitions, defined by +// https://github.com/census-instrumentation/opencensus-specs/blob/master/stats/gRPC.md + +// Registers the cumulative gRPC views so that they will be exported by any +// registered stats exporter. For on-task stats, construct a View using the +// ViewDescriptors below. +void RegisterOpenCensusViewsForExport(); + +// Returns the tracing Span for the current RPC. +::opencensus::trace::Span GetSpanFromServerContext( + grpc::ServerContext* context); + +} // namespace grpc_impl + +#endif // GRPCPP_OPENCENSUS_IMPL_H diff --git a/src/cpp/ext/filters/census/grpc_plugin.cc b/src/cpp/ext/filters/census/grpc_plugin.cc index f978ed3bf51..c5018f0673a 100644 --- a/src/cpp/ext/filters/census/grpc_plugin.cc +++ b/src/cpp/ext/filters/census/grpc_plugin.cc @@ -30,35 +30,6 @@ namespace grpc { -void RegisterOpenCensusPlugin() { - RegisterChannelFilter( - "opencensus_client", GRPC_CLIENT_CHANNEL, INT_MAX /* priority */, - nullptr /* condition function */); - RegisterChannelFilter( - "opencensus_server", GRPC_SERVER_CHANNEL, INT_MAX /* priority */, - nullptr /* condition function */); - - // Access measures to ensure they are initialized. Otherwise, creating a view - // before the first RPC would cause an error. - RpcClientSentBytesPerRpc(); - RpcClientReceivedBytesPerRpc(); - RpcClientRoundtripLatency(); - RpcClientServerLatency(); - RpcClientSentMessagesPerRpc(); - RpcClientReceivedMessagesPerRpc(); - - RpcServerSentBytesPerRpc(); - RpcServerReceivedBytesPerRpc(); - RpcServerServerLatency(); - RpcServerSentMessagesPerRpc(); - RpcServerReceivedMessagesPerRpc(); -} - -::opencensus::trace::Span GetSpanFromServerContext(ServerContext* context) { - return reinterpret_cast(context->census_context()) - ->Span(); -} - // These measure definitions should be kept in sync across opencensus // implementations--see // https://github.com/census-instrumentation/opencensus-java/blob/master/contrib/grpc_metrics/src/main/java/io/opencensus/contrib/grpc/metrics/RpcMeasureConstants.java. @@ -126,5 +97,39 @@ ABSL_CONST_INIT const absl::string_view ABSL_CONST_INIT const absl::string_view kRpcServerServerLatencyMeasureName = "grpc.io/server/server_latency"; - } // namespace grpc +namespace grpc_impl { + +void RegisterOpenCensusPlugin() { + grpc::RegisterChannelFilter( + "opencensus_client", GRPC_CLIENT_CHANNEL, INT_MAX /* priority */, + nullptr /* condition function */); + grpc::RegisterChannelFilter( + "opencensus_server", GRPC_SERVER_CHANNEL, INT_MAX /* priority */, + nullptr /* condition function */); + + // Access measures to ensure they are initialized. Otherwise, creating a view + // before the first RPC would cause an error. + grpc::RpcClientSentBytesPerRpc(); + grpc::RpcClientReceivedBytesPerRpc(); + grpc::RpcClientRoundtripLatency(); + grpc::RpcClientServerLatency(); + grpc::RpcClientSentMessagesPerRpc(); + grpc::RpcClientReceivedMessagesPerRpc(); + + grpc::RpcServerSentBytesPerRpc(); + grpc::RpcServerReceivedBytesPerRpc(); + grpc::RpcServerServerLatency(); + grpc::RpcServerSentMessagesPerRpc(); + grpc::RpcServerReceivedMessagesPerRpc(); +} + +::opencensus::trace::Span GetSpanFromServerContext( + grpc::ServerContext* context) { + return reinterpret_cast(context->census_context()) + ->Span(); +} + +} // namespace grpc_impl diff --git a/src/cpp/ext/filters/census/grpc_plugin.h b/src/cpp/ext/filters/census/grpc_plugin.h index 9e319cb994e..209fad139ce 100644 --- a/src/cpp/ext/filters/census/grpc_plugin.h +++ b/src/cpp/ext/filters/census/grpc_plugin.h @@ -22,12 +22,14 @@ #include #include "absl/strings/string_view.h" -#include "include/grpcpp/opencensus.h" +#include "include/grpcpp/opencensus_impl.h" #include "opencensus/stats/stats.h" -namespace grpc { +namespace grpc_impl { class ServerContext; +} +namespace grpc { // The tag keys set when recording RPC stats. ::opencensus::stats::TagKey ClientMethodTagKey(); diff --git a/src/cpp/ext/filters/census/views.cc b/src/cpp/ext/filters/census/views.cc index 2c0c5f72950..d7e3c81a955 100644 --- a/src/cpp/ext/filters/census/views.cc +++ b/src/cpp/ext/filters/census/views.cc @@ -25,6 +25,23 @@ #include "opencensus/stats/internal/set_aggregation_window.h" #include "opencensus/stats/stats.h" +namespace grpc_impl { + +void RegisterOpenCensusViewsForExport() { + grpc::ClientSentMessagesPerRpcCumulative().RegisterForExport(); + grpc::ClientSentBytesPerRpcCumulative().RegisterForExport(); + grpc::ClientReceivedMessagesPerRpcCumulative().RegisterForExport(); + grpc::ClientReceivedBytesPerRpcCumulative().RegisterForExport(); + grpc::ClientRoundtripLatencyCumulative().RegisterForExport(); + grpc::ClientServerLatencyCumulative().RegisterForExport(); + + grpc::ServerSentMessagesPerRpcCumulative().RegisterForExport(); + grpc::ServerSentBytesPerRpcCumulative().RegisterForExport(); + grpc::ServerReceivedMessagesPerRpcCumulative().RegisterForExport(); + grpc::ServerReceivedBytesPerRpcCumulative().RegisterForExport(); + grpc::ServerServerLatencyCumulative().RegisterForExport(); +} +} // namespace grpc_impl namespace grpc { using ::opencensus::stats::Aggregation; @@ -71,21 +88,6 @@ ViewDescriptor HourDescriptor() { } // namespace -void RegisterOpenCensusViewsForExport() { - ClientSentMessagesPerRpcCumulative().RegisterForExport(); - ClientSentBytesPerRpcCumulative().RegisterForExport(); - ClientReceivedMessagesPerRpcCumulative().RegisterForExport(); - ClientReceivedBytesPerRpcCumulative().RegisterForExport(); - ClientRoundtripLatencyCumulative().RegisterForExport(); - ClientServerLatencyCumulative().RegisterForExport(); - - ServerSentMessagesPerRpcCumulative().RegisterForExport(); - ServerSentBytesPerRpcCumulative().RegisterForExport(); - ServerReceivedMessagesPerRpcCumulative().RegisterForExport(); - ServerReceivedBytesPerRpcCumulative().RegisterForExport(); - ServerServerLatencyCumulative().RegisterForExport(); -} - // client cumulative const ViewDescriptor& ClientSentBytesPerRpcCumulative() { const static ViewDescriptor descriptor = diff --git a/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc b/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc index 73394028309..ad788a2dd68 100644 --- a/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc +++ b/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc @@ -58,7 +58,7 @@ class EchoServer final : public EchoTestService::Service { class StatsPluginEnd2EndTest : public ::testing::Test { protected: - static void SetUpTestCase() { RegisterOpenCensusPlugin(); } + static void SetUpTestCase() { grpc_impl::RegisterOpenCensusPlugin(); } void SetUp() { // Set up a synchronous server on a different thread to avoid the asynch diff --git a/test/cpp/microbenchmarks/bm_opencensus_plugin.cc b/test/cpp/microbenchmarks/bm_opencensus_plugin.cc index 9d42eb891df..d23c4f0573f 100644 --- a/test/cpp/microbenchmarks/bm_opencensus_plugin.cc +++ b/test/cpp/microbenchmarks/bm_opencensus_plugin.cc @@ -29,7 +29,9 @@ #include "test/cpp/microbenchmarks/helpers.h" absl::once_flag once; -void RegisterOnce() { absl::call_once(once, grpc::RegisterOpenCensusPlugin); } +void RegisterOnce() { + absl::call_once(once, grpc_impl::RegisterOpenCensusPlugin); +} class EchoServer final : public grpc::testing::EchoTestService::Service { grpc::Status Echo(grpc::ServerContext* context, @@ -99,7 +101,7 @@ static void BM_E2eLatencyCensusEnabled(benchmark::State& state) { RegisterOnce(); // This we can safely repeat, and doing so clears accumulated data to avoid // initialization costs varying between runs. - grpc::RegisterOpenCensusViewsForExport(); + grpc_impl::RegisterOpenCensusViewsForExport(); EchoServerThread server; std::unique_ptr stub = From f570c5ce7e8b0e237b5ad047b22ef39f62c1a990 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Fri, 15 Mar 2019 11:43:28 -0700 Subject: [PATCH 019/242] Make changes for making opencensus API visible from gRPC namespace --- include/grpcpp/opencensus.h | 15 +++++++++++++++ .../filters/census/stats_plugin_end2end_test.cc | 3 ++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/include/grpcpp/opencensus.h b/include/grpcpp/opencensus.h index 3b170336834..14c6add1d9e 100644 --- a/include/grpcpp/opencensus.h +++ b/include/grpcpp/opencensus.h @@ -21,4 +21,19 @@ #include "grpcpp/opencensus_impl.h" +namespace grpc { + +static inline void RegisterOpenCensusPlugin() { + ::grpc_impl::RegisterOpenCensusPlugin(); +} +static inline void RegisterOpenCensusViewsForExport() { + ::grpc_impl::RegisterOpenCensusViewsForExport(); +} +static inline ::opencensus::trace::Span GetSpanFromServerContext( + ServerContext* context) { + return ::grpc_impl::GetSpanFromServerContext(context); +} + +} // namespace grpc + #endif // GRPCPP_OPENCENSUS_H diff --git a/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc b/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc index ad788a2dd68..1b40ca42254 100644 --- a/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc +++ b/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc @@ -25,6 +25,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" #include "include/grpc++/grpc++.h" +#include "include/grpcpp/opencensus.h" #include "opencensus/stats/stats.h" #include "opencensus/stats/testing/test_utils.h" #include "src/cpp/ext/filters/census/grpc_plugin.h" @@ -58,7 +59,7 @@ class EchoServer final : public EchoTestService::Service { class StatsPluginEnd2EndTest : public ::testing::Test { protected: - static void SetUpTestCase() { grpc_impl::RegisterOpenCensusPlugin(); } + static void SetUpTestCase() { grpc::RegisterOpenCensusPlugin(); } void SetUp() { // Set up a synchronous server on a different thread to avoid the asynch From 29bcbb24c284a28b89ae52592926807ef090fcf2 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Thu, 14 Mar 2019 14:53:10 -0700 Subject: [PATCH 020/242] Moving create_channel from grpc to grpc_impl --- BUILD | 1 + CMakeLists.txt | 3 ++ Makefile | 3 ++ build.yaml | 1 + gRPC-C++.podspec | 1 + include/grpcpp/create_channel.h | 59 +-------------------- include/grpcpp/create_channel_impl.h | 79 ++++++++++++++++++++++++++++ 7 files changed, 90 insertions(+), 57 deletions(-) create mode 100644 include/grpcpp/create_channel_impl.h diff --git a/BUILD b/BUILD index 835edbfb48f..a8824d8f650 100644 --- a/BUILD +++ b/BUILD @@ -219,6 +219,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/client_context.h", "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", + "include/grpcpp/create_channel_impl.h", "include/grpcpp/create_channel_posix.h", "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 2308582c2f4..98ac1ea7752 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2999,6 +2999,7 @@ foreach(_hdr include/grpcpp/client_context.h include/grpcpp/completion_queue.h include/grpcpp/create_channel.h + include/grpcpp/create_channel_impl.h include/grpcpp/create_channel_posix.h include/grpcpp/ext/health_check_service_server_builder_option.h include/grpcpp/generic/async_generic_service.h @@ -3589,6 +3590,7 @@ foreach(_hdr include/grpcpp/client_context.h include/grpcpp/completion_queue.h include/grpcpp/create_channel.h + include/grpcpp/create_channel_impl.h include/grpcpp/create_channel_posix.h include/grpcpp/ext/health_check_service_server_builder_option.h include/grpcpp/generic/async_generic_service.h @@ -4548,6 +4550,7 @@ foreach(_hdr include/grpcpp/client_context.h include/grpcpp/completion_queue.h include/grpcpp/create_channel.h + include/grpcpp/create_channel_impl.h include/grpcpp/create_channel_posix.h include/grpcpp/ext/health_check_service_server_builder_option.h include/grpcpp/generic/async_generic_service.h diff --git a/Makefile b/Makefile index 69a2abbc8ca..5f1f297457c 100644 --- a/Makefile +++ b/Makefile @@ -5424,6 +5424,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ + include/grpcpp/create_channel_impl.h \ include/grpcpp/create_channel_posix.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ @@ -6023,6 +6024,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ + include/grpcpp/create_channel_impl.h \ include/grpcpp/create_channel_posix.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ @@ -6935,6 +6937,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ + include/grpcpp/create_channel_impl.h \ include/grpcpp/create_channel_posix.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ diff --git a/build.yaml b/build.yaml index 34b271f58de..fe430652c90 100644 --- a/build.yaml +++ b/build.yaml @@ -1344,6 +1344,7 @@ filegroups: - include/grpcpp/client_context.h - include/grpcpp/completion_queue.h - include/grpcpp/create_channel.h + - include/grpcpp/create_channel_impl.h - include/grpcpp/create_channel_posix.h - include/grpcpp/ext/health_check_service_server_builder_option.h - include/grpcpp/generic/async_generic_service.h diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 5a850bc8438..1766342285a 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -85,6 +85,7 @@ Pod::Spec.new do |s| 'include/grpcpp/client_context.h', 'include/grpcpp/completion_queue.h', 'include/grpcpp/create_channel.h', + 'include/grpcpp/create_channel_impl.h', 'include/grpcpp/create_channel_posix.h', 'include/grpcpp/ext/health_check_service_server_builder_option.h', 'include/grpcpp/generic/async_generic_service.h', diff --git a/include/grpcpp/create_channel.h b/include/grpcpp/create_channel.h index e8a2a70581d..40d4717071a 100644 --- a/include/grpcpp/create_channel.h +++ b/include/grpcpp/create_channel.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,61 +19,6 @@ #ifndef GRPCPP_CREATE_CHANNEL_H #define GRPCPP_CREATE_CHANNEL_H -#include - -#include -#include -#include -#include -#include - -namespace grpc { - -/// Create a new \a Channel pointing to \a target. -/// -/// \param target The URI of the endpoint to connect to. -/// \param creds Credentials to use for the created channel. If it does not -/// hold an object or is invalid, a lame channel (one on which all operations -/// fail) is returned. -std::shared_ptr CreateChannel( - const grpc::string& target, - const std::shared_ptr& creds); - -/// Create a new \em custom \a Channel pointing to \a target. -/// -/// \warning For advanced use and testing ONLY. Override default channel -/// arguments only if necessary. -/// -/// \param target The URI of the endpoint to connect to. -/// \param creds Credentials to use for the created channel. If it does not -/// hold an object or is invalid, a lame channel (one on which all operations -/// fail) is returned. -/// \param args Options for channel creation. -std::shared_ptr CreateCustomChannel( - const grpc::string& target, - const std::shared_ptr& creds, - const ChannelArguments& args); - -namespace experimental { -/// Create a new \em custom \a Channel pointing to \a target with \a -/// interceptors being invoked per call. -/// -/// \warning For advanced use and testing ONLY. Override default channel -/// arguments only if necessary. -/// -/// \param target The URI of the endpoint to connect to. -/// \param creds Credentials to use for the created channel. If it does not -/// hold an object or is invalid, a lame channel (one on which all operations -/// fail) is returned. -/// \param args Options for channel creation. -std::shared_ptr CreateCustomChannelWithInterceptors( - const grpc::string& target, - const std::shared_ptr& creds, - const ChannelArguments& args, - std::vector< - std::unique_ptr> - interceptor_creators); -} // namespace experimental -} // namespace grpc +#include #endif // GRPCPP_CREATE_CHANNEL_H diff --git a/include/grpcpp/create_channel_impl.h b/include/grpcpp/create_channel_impl.h new file mode 100644 index 00000000000..9eaeb7c17f6 --- /dev/null +++ b/include/grpcpp/create_channel_impl.h @@ -0,0 +1,79 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_CREATE_CHANNEL_IMPL_H +#define GRPCPP_CREATE_CHANNEL_IMPL_H + +#include + +#include +#include +#include +#include +#include + +namespace grpc_impl { + +/// Create a new \a Channel pointing to \a target. +/// +/// \param target The URI of the endpoint to connect to. +/// \param creds Credentials to use for the created channel. If it does not +/// hold an object or is invalid, a lame channel (one on which all operations +/// fail) is returned. +std::shared_ptr CreateChannel( + const grpc::string& target, + const std::shared_ptr& creds); + +/// Create a new \em custom \a Channel pointing to \a target. +/// +/// \warning For advanced use and testing ONLY. Override default channel +/// arguments only if necessary. +/// +/// \param target The URI of the endpoint to connect to. +/// \param creds Credentials to use for the created channel. If it does not +/// hold an object or is invalid, a lame channel (one on which all operations +/// fail) is returned. +/// \param args Options for channel creation. +std::shared_ptr CreateCustomChannel( + const grpc::string& target, + const std::shared_ptr& creds, + const ChannelArguments& args); + +namespace experimental { +/// Create a new \em custom \a Channel pointing to \a target with \a +/// interceptors being invoked per call. +/// +/// \warning For advanced use and testing ONLY. Override default channel +/// arguments only if necessary. +/// +/// \param target The URI of the endpoint to connect to. +/// \param creds Credentials to use for the created channel. If it does not +/// hold an object or is invalid, a lame channel (one on which all operations +/// fail) is returned. +/// \param args Options for channel creation. +std::shared_ptr CreateCustomChannelWithInterceptors( + const grpc::string& target, + const std::shared_ptr& creds, + const ChannelArguments& args, + std::vector< + std::unique_ptr> + interceptor_creators); +} // namespace experimental +} // namespace grpc_impl + +#endif // GRPCPP_CREATE_CHANNEL_IMPL_H From 4a0c3b848f4bc8c50d03971f627c28675a766243 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Thu, 14 Mar 2019 22:24:01 -0700 Subject: [PATCH 021/242] Fix broken tests --- examples/BUILD | 2 +- include/grpcpp/create_channel.h | 30 +++++++++++++++++++++ include/grpcpp/create_channel_impl.h | 18 ++++++------- include/grpcpp/security/credentials.h | 31 ++++++++++++++-------- src/cpp/client/create_channel.cc | 38 ++++++++++++++------------- 5 files changed, 80 insertions(+), 39 deletions(-) diff --git a/examples/BUILD b/examples/BUILD index 0a1ca94a649..c67c582964a 100644 --- a/examples/BUILD +++ b/examples/BUILD @@ -112,4 +112,4 @@ cc_binary( srcs = ["cpp/keyvaluestore/server.cc"], defines = ["BAZEL_BUILD"], deps = [":keyvaluestore", "//:grpc++"], -) \ No newline at end of file +) diff --git a/include/grpcpp/create_channel.h b/include/grpcpp/create_channel.h index 40d4717071a..7d92716b773 100644 --- a/include/grpcpp/create_channel.h +++ b/include/grpcpp/create_channel.h @@ -21,4 +21,34 @@ #include +namespace grpc { + +static inline std::shared_ptr CreateChannel( + const grpc::string& target, + const std::shared_ptr& creds) { + return ::grpc_impl::CreateChannel(target, creds); +} + +static inline std::shared_ptr CreateCustomChannel( + const grpc::string& target, + const std::shared_ptr& creds, + const ChannelArguments& args) { + return ::grpc_impl::CreateCustomChannel(target, creds, args); +} + +namespace experimental { + +static inline std::shared_ptr CreateCustomChannelWithInterceptors( + const grpc::string& target, + const std::shared_ptr& creds, + const ChannelArguments& args, + std::vector< + std::unique_ptr> + interceptor_creators) { + return ::grpc_impl::experimental::CreateCustomChannelWithInterceptors(target, creds, args, std::move(interceptor_creators)); +} + +} // namespace experimental +} // namespace grpc + #endif // GRPCPP_CREATE_CHANNEL_H diff --git a/include/grpcpp/create_channel_impl.h b/include/grpcpp/create_channel_impl.h index 9eaeb7c17f6..214a537a3cb 100644 --- a/include/grpcpp/create_channel_impl.h +++ b/include/grpcpp/create_channel_impl.h @@ -35,9 +35,9 @@ namespace grpc_impl { /// \param creds Credentials to use for the created channel. If it does not /// hold an object or is invalid, a lame channel (one on which all operations /// fail) is returned. -std::shared_ptr CreateChannel( +std::shared_ptr CreateChannel( const grpc::string& target, - const std::shared_ptr& creds); + const std::shared_ptr& creds); /// Create a new \em custom \a Channel pointing to \a target. /// @@ -49,10 +49,10 @@ std::shared_ptr CreateChannel( /// hold an object or is invalid, a lame channel (one on which all operations /// fail) is returned. /// \param args Options for channel creation. -std::shared_ptr CreateCustomChannel( +std::shared_ptr CreateCustomChannel( const grpc::string& target, - const std::shared_ptr& creds, - const ChannelArguments& args); + const std::shared_ptr& creds, + const grpc::ChannelArguments& args); namespace experimental { /// Create a new \em custom \a Channel pointing to \a target with \a @@ -66,12 +66,12 @@ namespace experimental { /// hold an object or is invalid, a lame channel (one on which all operations /// fail) is returned. /// \param args Options for channel creation. -std::shared_ptr CreateCustomChannelWithInterceptors( +std::shared_ptr CreateCustomChannelWithInterceptors( const grpc::string& target, - const std::shared_ptr& creds, - const ChannelArguments& args, + const std::shared_ptr& creds, + const grpc::ChannelArguments& args, std::vector< - std::unique_ptr> + std::unique_ptr> interceptor_creators); } // namespace experimental } // namespace grpc_impl diff --git a/include/grpcpp/security/credentials.h b/include/grpcpp/security/credentials.h index dfea3900048..f17e295975a 100644 --- a/include/grpcpp/security/credentials.h +++ b/include/grpcpp/security/credentials.h @@ -33,23 +33,32 @@ struct grpc_call; namespace grpc { -class ChannelArguments; -class Channel; -class SecureChannelCredentials; -class CallCredentials; -class SecureCallCredentials; +class CallCredentials; +class ChannelArguments; class ChannelCredentials; +} +namespace grpc_impl { +std::shared_ptr CreateCustomChannel( + const grpc::string& target, + const std::shared_ptr& creds, + const grpc::ChannelArguments& args); namespace experimental { -std::shared_ptr CreateCustomChannelWithInterceptors( +std::shared_ptr CreateCustomChannelWithInterceptors( const grpc::string& target, - const std::shared_ptr& creds, - const ChannelArguments& args, + const std::shared_ptr& creds, + const grpc::ChannelArguments& args, std::vector< - std::unique_ptr> + std::unique_ptr> interceptor_creators); } // namespace experimental +} // namespace grpc_impl +namespace grpc { +class Channel; +class SecureChannelCredentials; +class SecureCallCredentials; + /// A channel credentials object encapsulates all the state needed by a client /// to authenticate with a server for a given channel. @@ -70,13 +79,13 @@ class ChannelCredentials : private GrpcLibraryCodegen { virtual SecureChannelCredentials* AsSecureCredentials() = 0; private: - friend std::shared_ptr CreateCustomChannel( + friend std::shared_ptr grpc_impl::CreateCustomChannel( const grpc::string& target, const std::shared_ptr& creds, const ChannelArguments& args); friend std::shared_ptr - experimental::CreateCustomChannelWithInterceptors( + grpc_impl::experimental::CreateCustomChannelWithInterceptors( const grpc::string& target, const std::shared_ptr& creds, const ChannelArguments& args, diff --git a/src/cpp/client/create_channel.cc b/src/cpp/client/create_channel.cc index 457daa674c7..4a4298684cb 100644 --- a/src/cpp/client/create_channel.cc +++ b/src/cpp/client/create_channel.cc @@ -19,34 +19,36 @@ #include #include -#include +#include #include #include #include "src/cpp/client/create_channel_internal.h" namespace grpc { -class ChannelArguments; -std::shared_ptr CreateChannel( +class ChannelArguments; +} +namespace grpc_impl { +std::shared_ptr CreateChannel( const grpc::string& target, - const std::shared_ptr& creds) { - return CreateCustomChannel(target, creds, ChannelArguments()); + const std::shared_ptr& creds) { + return CreateCustomChannel(target, creds, grpc::ChannelArguments()); } -std::shared_ptr CreateCustomChannel( +std::shared_ptr CreateCustomChannel( const grpc::string& target, - const std::shared_ptr& creds, - const ChannelArguments& args) { - GrpcLibraryCodegen init_lib; // We need to call init in case of a bad creds. + const std::shared_ptr& creds, + const grpc::ChannelArguments& args) { + grpc::GrpcLibraryCodegen init_lib; // We need to call init in case of a bad creds. return creds ? creds->CreateChannel(target, args) - : CreateChannelInternal( + : grpc::CreateChannelInternal( "", grpc_lame_client_channel_create( nullptr, GRPC_STATUS_INVALID_ARGUMENT, "Invalid credentials."), std::vector>()); + grpc::experimental::ClientInterceptorFactoryInterface>>()); } namespace experimental { @@ -61,23 +63,23 @@ namespace experimental { /// hold an object or is invalid, a lame channel (one on which all operations /// fail) is returned. /// \param args Options for channel creation. -std::shared_ptr CreateCustomChannelWithInterceptors( +std::shared_ptr CreateCustomChannelWithInterceptors( const grpc::string& target, - const std::shared_ptr& creds, - const ChannelArguments& args, + const std::shared_ptr& creds, + const grpc::ChannelArguments& args, std::vector< - std::unique_ptr> + std::unique_ptr> interceptor_creators) { return creds ? creds->CreateChannelWithInterceptors( target, args, std::move(interceptor_creators)) - : CreateChannelInternal( + : grpc::CreateChannelInternal( "", grpc_lame_client_channel_create( nullptr, GRPC_STATUS_INVALID_ARGUMENT, "Invalid credentials."), std::vector>()); + grpc::experimental::ClientInterceptorFactoryInterface>>()); } } // namespace experimental -} // namespace grpc +} // namespace grpc_impl From 2772f519e63ee42e2d151aa202f13e4b649ad673 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Fri, 15 Mar 2019 14:28:32 -0700 Subject: [PATCH 022/242] Fix errors from presubmit scripts. --- include/grpcpp/create_channel.h | 9 +++++---- include/grpcpp/security/credentials.h | 9 ++++----- src/cpp/client/create_channel.cc | 9 ++++++--- tools/doxygen/Doxyfile.c++ | 1 + tools/doxygen/Doxyfile.c++.internal | 1 + tools/run_tests/generated/sources_and_headers.json | 2 ++ 6 files changed, 19 insertions(+), 12 deletions(-) diff --git a/include/grpcpp/create_channel.h b/include/grpcpp/create_channel.h index 7d92716b773..6d444be9803 100644 --- a/include/grpcpp/create_channel.h +++ b/include/grpcpp/create_channel.h @@ -42,13 +42,14 @@ static inline std::shared_ptr CreateCustomChannelWithInterceptors( const grpc::string& target, const std::shared_ptr& creds, const ChannelArguments& args, - std::vector< + std::vector< std::unique_ptr> interceptor_creators) { - return ::grpc_impl::experimental::CreateCustomChannelWithInterceptors(target, creds, args, std::move(interceptor_creators)); + return ::grpc_impl::experimental::CreateCustomChannelWithInterceptors( + target, creds, args, std::move(interceptor_creators)); } -} // namespace experimental -} // namespace grpc +} // namespace experimental +} // namespace grpc #endif // GRPCPP_CREATE_CHANNEL_H diff --git a/include/grpcpp/security/credentials.h b/include/grpcpp/security/credentials.h index f17e295975a..f6a1c62b668 100644 --- a/include/grpcpp/security/credentials.h +++ b/include/grpcpp/security/credentials.h @@ -37,12 +37,12 @@ namespace grpc { class CallCredentials; class ChannelArguments; class ChannelCredentials; -} +} // namespace grpc namespace grpc_impl { std::shared_ptr CreateCustomChannel( - const grpc::string& target, - const std::shared_ptr& creds, - const grpc::ChannelArguments& args); + const grpc::string& target, + const std::shared_ptr& creds, + const grpc::ChannelArguments& args); namespace experimental { std::shared_ptr CreateCustomChannelWithInterceptors( @@ -59,7 +59,6 @@ class Channel; class SecureChannelCredentials; class SecureCallCredentials; - /// A channel credentials object encapsulates all the state needed by a client /// to authenticate with a server for a given channel. /// It can make various assertions, e.g., about the client’s identity, role diff --git a/src/cpp/client/create_channel.cc b/src/cpp/client/create_channel.cc index 4a4298684cb..9426a4e7f6e 100644 --- a/src/cpp/client/create_channel.cc +++ b/src/cpp/client/create_channel.cc @@ -40,7 +40,8 @@ std::shared_ptr CreateCustomChannel( const grpc::string& target, const std::shared_ptr& creds, const grpc::ChannelArguments& args) { - grpc::GrpcLibraryCodegen init_lib; // We need to call init in case of a bad creds. + grpc::GrpcLibraryCodegen + init_lib; // We need to call init in case of a bad creds. return creds ? creds->CreateChannel(target, args) : grpc::CreateChannelInternal( "", @@ -48,7 +49,8 @@ std::shared_ptr CreateCustomChannel( nullptr, GRPC_STATUS_INVALID_ARGUMENT, "Invalid credentials."), std::vector>()); + grpc::experimental:: + ClientInterceptorFactoryInterface>>()); } namespace experimental { @@ -78,7 +80,8 @@ std::shared_ptr CreateCustomChannelWithInterceptors( nullptr, GRPC_STATUS_INVALID_ARGUMENT, "Invalid credentials."), std::vector>()); + grpc::experimental:: + ClientInterceptorFactoryInterface>>()); } } // namespace experimental diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 9f17a25298a..a4f7803304d 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -930,6 +930,7 @@ include/grpcpp/channel.h \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ +include/grpcpp/create_channel_impl.h \ include/grpcpp/create_channel_posix.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index c0078bf2764..cb10f98bbd5 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -931,6 +931,7 @@ include/grpcpp/channel.h \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ +include/grpcpp/create_channel_impl.h \ include/grpcpp/create_channel_posix.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 2d427804d07..cb1810da31a 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -11414,6 +11414,7 @@ "include/grpcpp/client_context.h", "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", + "include/grpcpp/create_channel_impl.h", "include/grpcpp/create_channel_posix.h", "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", @@ -11523,6 +11524,7 @@ "include/grpcpp/client_context.h", "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", + "include/grpcpp/create_channel_impl.h", "include/grpcpp/create_channel_posix.h", "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", From 5906b86119bf7f9234fe2b174c6bd897fc7cd8da Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Fri, 15 Mar 2019 16:08:24 -0700 Subject: [PATCH 023/242] Fix tests to use grpc namespace --- test/cpp/end2end/end2end_test.cc | 5 ----- test/cpp/end2end/thread_stress_test.cc | 5 ----- test/cpp/qps/server.h | 5 ----- test/cpp/qps/server_async.cc | 1 + 4 files changed, 1 insertion(+), 15 deletions(-) diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index f7b9ee4b0b0..f58a472bfaf 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -64,11 +64,6 @@ using std::chrono::system_clock; } \ } while (0) -namespace grpc_impl { - -class ResourceQuota; -} - namespace grpc { namespace testing { namespace { diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc index e308e591d1a..e30ce0dbcbf 100644 --- a/test/cpp/end2end/thread_stress_test.cc +++ b/test/cpp/end2end/thread_stress_test.cc @@ -48,11 +48,6 @@ const int kNumAsyncReceiveThreads = 50; const int kNumAsyncServerThreads = 50; const int kNumRpcs = 1000; // Number of RPCs per thread -namespace grpc_impl { - -class ResourceQuota; -} - namespace grpc { namespace testing { diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h index 3aec8644a94..89b0e3af4b2 100644 --- a/test/cpp/qps/server.h +++ b/test/cpp/qps/server.h @@ -34,11 +34,6 @@ #include "test/cpp/qps/usage_timer.h" #include "test/cpp/util/test_credentials_provider.h" -namespace grpc_impl { - -class ResourceQuota; -} - namespace grpc { namespace testing { diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc index 9343fd311e1..a5f8347c269 100644 --- a/test/cpp/qps/server_async.cc +++ b/test/cpp/qps/server_async.cc @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include From 0692dcc16aefa821fe96935836456a64e40986d9 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Fri, 15 Mar 2019 16:33:11 -0700 Subject: [PATCH 024/242] Fix tests namespaces --- test/cpp/end2end/end2end_test.cc | 5 ----- test/cpp/end2end/thread_stress_test.cc | 5 ----- test/cpp/qps/server.h | 5 ----- test/cpp/qps/server_async.cc | 1 - 4 files changed, 16 deletions(-) diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index f7b9ee4b0b0..f58a472bfaf 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -64,11 +64,6 @@ using std::chrono::system_clock; } \ } while (0) -namespace grpc_impl { - -class ResourceQuota; -} - namespace grpc { namespace testing { namespace { diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc index e308e591d1a..e30ce0dbcbf 100644 --- a/test/cpp/end2end/thread_stress_test.cc +++ b/test/cpp/end2end/thread_stress_test.cc @@ -48,11 +48,6 @@ const int kNumAsyncReceiveThreads = 50; const int kNumAsyncServerThreads = 50; const int kNumRpcs = 1000; // Number of RPCs per thread -namespace grpc_impl { - -class ResourceQuota; -} - namespace grpc { namespace testing { diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h index 3aec8644a94..89b0e3af4b2 100644 --- a/test/cpp/qps/server.h +++ b/test/cpp/qps/server.h @@ -34,11 +34,6 @@ #include "test/cpp/qps/usage_timer.h" #include "test/cpp/util/test_credentials_provider.h" -namespace grpc_impl { - -class ResourceQuota; -} - namespace grpc { namespace testing { diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc index 8f20de7e714..9343fd311e1 100644 --- a/test/cpp/qps/server_async.cc +++ b/test/cpp/qps/server_async.cc @@ -27,7 +27,6 @@ #include #include #include -//#include #include #include #include From 2a8f3f79abcb5628991605b2c9a442e4ced18fea Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Fri, 15 Mar 2019 17:08:58 -0700 Subject: [PATCH 025/242] Fix more namespace stuff --- test/cpp/microbenchmarks/bm_opencensus_plugin.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/cpp/microbenchmarks/bm_opencensus_plugin.cc b/test/cpp/microbenchmarks/bm_opencensus_plugin.cc index d23c4f0573f..c3fa6f3031a 100644 --- a/test/cpp/microbenchmarks/bm_opencensus_plugin.cc +++ b/test/cpp/microbenchmarks/bm_opencensus_plugin.cc @@ -23,6 +23,7 @@ #include "absl/base/call_once.h" #include "absl/strings/str_cat.h" #include "include/grpc++/grpc++.h" +#include "include/grpcpp/opencensus.h" #include "opencensus/stats/stats.h" #include "src/cpp/ext/filters/census/grpc_plugin.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" @@ -30,7 +31,7 @@ absl::once_flag once; void RegisterOnce() { - absl::call_once(once, grpc_impl::RegisterOpenCensusPlugin); + absl::call_once(once, grpc::RegisterOpenCensusPlugin); } class EchoServer final : public grpc::testing::EchoTestService::Service { @@ -101,7 +102,7 @@ static void BM_E2eLatencyCensusEnabled(benchmark::State& state) { RegisterOnce(); // This we can safely repeat, and doing so clears accumulated data to avoid // initialization costs varying between runs. - grpc_impl::RegisterOpenCensusViewsForExport(); + grpc::RegisterOpenCensusViewsForExport(); EchoServerThread server; std::unique_ptr stub = From c08e5bee404b46b37f9d3356b1ec8730371f7b0d Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Sun, 17 Mar 2019 22:15:21 -0700 Subject: [PATCH 026/242] Fix make errors --- include/grpcpp/security/credentials.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/grpcpp/security/credentials.h b/include/grpcpp/security/credentials.h index f6a1c62b668..159a6f0c908 100644 --- a/include/grpcpp/security/credentials.h +++ b/include/grpcpp/security/credentials.h @@ -81,15 +81,15 @@ class ChannelCredentials : private GrpcLibraryCodegen { friend std::shared_ptr grpc_impl::CreateCustomChannel( const grpc::string& target, const std::shared_ptr& creds, - const ChannelArguments& args); + const grpc::ChannelArguments& args); friend std::shared_ptr grpc_impl::experimental::CreateCustomChannelWithInterceptors( const grpc::string& target, const std::shared_ptr& creds, - const ChannelArguments& args, + const grpc::ChannelArguments& args, std::vector< - std::unique_ptr> + std::unique_ptr> interceptor_creators); virtual std::shared_ptr CreateChannel( From 1061604a018ab706661f482ba9e6af44cc5cd34a Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Mon, 18 Mar 2019 10:06:10 -0700 Subject: [PATCH 027/242] Fix clang_format_code.sh errors --- include/grpcpp/security/credentials.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/grpcpp/security/credentials.h b/include/grpcpp/security/credentials.h index 159a6f0c908..34d2e2ea463 100644 --- a/include/grpcpp/security/credentials.h +++ b/include/grpcpp/security/credentials.h @@ -88,8 +88,8 @@ class ChannelCredentials : private GrpcLibraryCodegen { const grpc::string& target, const std::shared_ptr& creds, const grpc::ChannelArguments& args, - std::vector< - std::unique_ptr> + std::vector> interceptor_creators); virtual std::shared_ptr CreateChannel( From e9593285a81a7bbabb6f436467df1a2127b7c3c2 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Mon, 18 Mar 2019 13:20:42 -0700 Subject: [PATCH 028/242] Move LoadReportingServiceServerBuilderOption from grpc to grpc_impl --- BUILD | 1 + include/grpcpp/ext/server_load_reporting.h | 26 +++------ .../grpcpp/ext/server_load_reporting_impl.h | 53 +++++++++++++++++++ ...reporting_service_server_builder_option.cc | 6 +-- src/cpp/server/load_reporter/util.cc | 4 +- 5 files changed, 65 insertions(+), 25 deletions(-) create mode 100644 include/grpcpp/ext/server_load_reporting_impl.h diff --git a/BUILD b/BUILD index 835edbfb48f..ce448f1d2a8 100644 --- a/BUILD +++ b/BUILD @@ -1475,6 +1475,7 @@ grpc_cc_library( language = "c++", public_hdrs = [ "include/grpcpp/ext/server_load_reporting.h", + "include/grpcpp/ext/server_load_reporting_impl.h", ], deps = [ "lb_server_load_reporting_filter", diff --git a/include/grpcpp/ext/server_load_reporting.h b/include/grpcpp/ext/server_load_reporting.h index 939569c19aa..462c995b263 100644 --- a/include/grpcpp/ext/server_load_reporting.h +++ b/include/grpcpp/ext/server_load_reporting.h @@ -19,32 +19,18 @@ #ifndef GRPCPP_EXT_SERVER_LOAD_REPORTING_H #define GRPCPP_EXT_SERVER_LOAD_REPORTING_H -#include - -#include -#include -#include -#include +#include namespace grpc { namespace load_reporter { namespace experimental { -// The ServerBuilderOption to enable server-side load reporting feature. To -// enable the feature, please make sure the binary builds with the -// grpcpp_server_load_reporting library and set this option in the -// ServerBuilder. -class LoadReportingServiceServerBuilderOption : public ServerBuilderOption { - public: - void UpdateArguments(::grpc::ChannelArguments* args) override; - void UpdatePlugins(std::vector>* - plugins) override; -}; +typedef ::grpc_impl::load_reporter::experimental::LoadReportingServiceServerBuilderOption LoadReportingServiceServerBuilderOption; -// Adds the load reporting cost with \a cost_name and \a cost_value in the -// trailing metadata of the server context. -void AddLoadReportingCost(grpc::ServerContext* ctx, - const grpc::string& cost_name, double cost_value); +static inline void AddLoadReportingCost(grpc::ServerContext* ctx, + const grpc::string& cost_name, double cost_value) { + ::grpc_impl::load_reporter::experimental::AddLoadReportingCost(ctx, cost_name, cost_value); +} } // namespace experimental } // namespace load_reporter diff --git a/include/grpcpp/ext/server_load_reporting_impl.h b/include/grpcpp/ext/server_load_reporting_impl.h new file mode 100644 index 00000000000..20343a56f33 --- /dev/null +++ b/include/grpcpp/ext/server_load_reporting_impl.h @@ -0,0 +1,53 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_EXT_SERVER_LOAD_REPORTING_IMPL_H +#define GRPCPP_EXT_SERVER_LOAD_REPORTING_IMPL_H + +#include + +#include +#include +#include +#include + +namespace grpc_impl { +namespace load_reporter { +namespace experimental { + +// The ServerBuilderOption to enable server-side load reporting feature. To +// enable the feature, please make sure the binary builds with the +// grpcpp_server_load_reporting library and set this option in the +// ServerBuilder. +class LoadReportingServiceServerBuilderOption : public grpc::ServerBuilderOption { + public: + void UpdateArguments(::grpc::ChannelArguments* args) override; + void UpdatePlugins(std::vector>* + plugins) override; +}; + +// Adds the load reporting cost with \a cost_name and \a cost_value in the +// trailing metadata of the server context. +void AddLoadReportingCost(grpc::ServerContext* ctx, + const grpc::string& cost_name, double cost_value); + +} // namespace experimental +} // namespace load_reporter +} // namespace grpc + +#endif // GRPCPP_EXT_SERVER_LOAD_REPORTING_IMPL_H diff --git a/src/cpp/server/load_reporter/load_reporting_service_server_builder_option.cc b/src/cpp/server/load_reporter/load_reporting_service_server_builder_option.cc index 81cf6ac562d..320b1c9b5f9 100644 --- a/src/cpp/server/load_reporter/load_reporting_service_server_builder_option.cc +++ b/src/cpp/server/load_reporter/load_reporting_service_server_builder_option.cc @@ -22,7 +22,7 @@ #include "src/cpp/server/load_reporter/load_reporting_service_server_builder_plugin.h" -namespace grpc { +namespace grpc_impl { namespace load_reporter { namespace experimental { @@ -33,9 +33,9 @@ void LoadReportingServiceServerBuilderOption::UpdateArguments( void LoadReportingServiceServerBuilderOption::UpdatePlugins( std::vector>* plugins) { - plugins->emplace_back(new LoadReportingServiceServerBuilderPlugin()); + plugins->emplace_back(new grpc::load_reporter::LoadReportingServiceServerBuilderPlugin()); } } // namespace experimental } // namespace load_reporter -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/server/load_reporter/util.cc b/src/cpp/server/load_reporter/util.cc index 89bdf57049c..b69705a6994 100644 --- a/src/cpp/server/load_reporter/util.cc +++ b/src/cpp/server/load_reporter/util.cc @@ -24,7 +24,7 @@ #include -namespace grpc { +namespace grpc_impl { namespace load_reporter { namespace experimental { @@ -44,4 +44,4 @@ void AddLoadReportingCost(grpc::ServerContext* ctx, } // namespace experimental } // namespace load_reporter -} // namespace grpc +} // namespace grpc_impl From 1d357572cf1d33d6529ff74bbaf84aafc9cc2ed7 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Tue, 19 Mar 2019 10:43:02 -0700 Subject: [PATCH 029/242] Revert "Moving ::grpc::ResourceQuota to ::grpc_impl::ResouceQuota" This reverts commit d8d8bec7c8a254b1f8bc152b71b0b1c2b41bfe3f. --- BUILD | 3 +- CMakeLists.txt | 3 - Makefile | 3 - build.yaml | 1 - gRPC-C++.podspec | 1 - include/grpcpp/resource_quota.h | 45 +++++++++++++- include/grpcpp/resource_quota_impl.h | 68 ---------------------- include/grpcpp/server_builder.h | 9 +-- include/grpcpp/support/channel_arguments.h | 9 +-- src/cpp/common/channel_arguments.cc | 2 +- src/cpp/common/resource_quota_cc.cc | 2 +- src/cpp/server/server_builder.cc | 7 +-- test/cpp/qps/server_async.cc | 1 + 13 files changed, 52 insertions(+), 102 deletions(-) delete mode 100644 include/grpcpp/resource_quota_impl.h diff --git a/BUILD b/BUILD index 9070a66c978..d80ffd9d459 100644 --- a/BUILD +++ b/BUILD @@ -192,8 +192,8 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpc++/impl/service_type.h", "include/grpc++/impl/sync_cxx11.h", "include/grpc++/impl/sync_no_cxx11.h", - "include/grpc++/security/auth_context.h", "include/grpc++/resource_quota.h", + "include/grpc++/security/auth_context.h", "include/grpc++/security/auth_metadata_processor.h", "include/grpc++/security/credentials.h", "include/grpc++/security/server_credentials.h", @@ -241,7 +241,6 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/impl/sync_cxx11.h", "include/grpcpp/impl/sync_no_cxx11.h", "include/grpcpp/resource_quota.h", - "include/grpcpp/resource_quota_impl.h", "include/grpcpp/security/auth_context.h", "include/grpcpp/security/auth_metadata_processor.h", "include/grpcpp/security/credentials.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 614fd2efca1..0030c9eb9af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3014,7 +3014,6 @@ foreach(_hdr include/grpcpp/impl/server_initializer.h include/grpcpp/impl/service_type.h include/grpcpp/resource_quota.h - include/grpcpp/resource_quota_impl.h include/grpcpp/security/auth_context.h include/grpcpp/security/auth_metadata_processor.h include/grpcpp/security/credentials.h @@ -3605,7 +3604,6 @@ foreach(_hdr include/grpcpp/impl/server_initializer.h include/grpcpp/impl/service_type.h include/grpcpp/resource_quota.h - include/grpcpp/resource_quota_impl.h include/grpcpp/security/auth_context.h include/grpcpp/security/auth_metadata_processor.h include/grpcpp/security/credentials.h @@ -4565,7 +4563,6 @@ foreach(_hdr include/grpcpp/impl/server_initializer.h include/grpcpp/impl/service_type.h include/grpcpp/resource_quota.h - include/grpcpp/resource_quota_impl.h include/grpcpp/security/auth_context.h include/grpcpp/security/auth_metadata_processor.h include/grpcpp/security/credentials.h diff --git a/Makefile b/Makefile index 7ad32e1291f..5a31d648b32 100644 --- a/Makefile +++ b/Makefile @@ -5438,7 +5438,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ - include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ @@ -6038,7 +6037,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ - include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ @@ -6951,7 +6949,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ - include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ diff --git a/build.yaml b/build.yaml index 82e652878bd..d8322b176b7 100644 --- a/build.yaml +++ b/build.yaml @@ -1360,7 +1360,6 @@ filegroups: - include/grpcpp/impl/server_initializer.h - include/grpcpp/impl/service_type.h - include/grpcpp/resource_quota.h - - include/grpcpp/resource_quota_impl.h - include/grpcpp/security/auth_context.h - include/grpcpp/security/auth_metadata_processor.h - include/grpcpp/security/credentials.h diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 2d50f28ff2a..e755b7aa602 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -105,7 +105,6 @@ Pod::Spec.new do |s| 'include/grpcpp/impl/server_initializer.h', 'include/grpcpp/impl/service_type.h', 'include/grpcpp/resource_quota.h', - 'include/grpcpp/resource_quota_impl.h', 'include/grpcpp/security/auth_context.h', 'include/grpcpp/security/auth_metadata_processor.h', 'include/grpcpp/security/credentials.h', diff --git a/include/grpcpp/resource_quota.h b/include/grpcpp/resource_quota.h index 333767b95c5..50bd1cb849a 100644 --- a/include/grpcpp/resource_quota.h +++ b/include/grpcpp/resource_quota.h @@ -1,6 +1,6 @@ /* * - * Copyright 2019 gRPC authors. + * Copyright 2016 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,11 +19,50 @@ #ifndef GRPCPP_RESOURCE_QUOTA_H #define GRPCPP_RESOURCE_QUOTA_H -#include +struct grpc_resource_quota; + +#include +#include namespace grpc { -typedef ::grpc_impl::ResourceQuota ResourceQuota; +/// ResourceQuota represents a bound on memory and thread usage by the gRPC +/// library. A ResourceQuota can be attached to a server (via \a ServerBuilder), +/// or a client channel (via \a ChannelArguments). +/// gRPC will attempt to keep memory and threads used by all attached entities +/// below the ResourceQuota bound. +class ResourceQuota final : private GrpcLibraryCodegen { + public: + /// \param name - a unique name for this ResourceQuota. + explicit ResourceQuota(const grpc::string& name); + ResourceQuota(); + ~ResourceQuota(); + + /// Resize this \a ResourceQuota to a new size. If \a new_size is smaller + /// than the current size of the pool, memory usage will be monotonically + /// decreased until it falls under \a new_size. + /// No time bound is given for this to occur however. + ResourceQuota& Resize(size_t new_size); + + /// Set the max number of threads that can be allocated from this + /// ResourceQuota object. + /// + /// If the new_max_threads value is smaller than the current value, no new + /// threads are allocated until the number of active threads fall below + /// new_max_threads. There is no time bound on when this may happen i.e none + /// of the current threads are forcefully destroyed and all threads run their + /// normal course. + ResourceQuota& SetMaxThreads(int new_max_threads); + + grpc_resource_quota* c_resource_quota() const { return impl_; } + + private: + ResourceQuota(const ResourceQuota& rhs); + ResourceQuota& operator=(const ResourceQuota& rhs); + + grpc_resource_quota* const impl_; +}; + } // namespace grpc #endif // GRPCPP_RESOURCE_QUOTA_H diff --git a/include/grpcpp/resource_quota_impl.h b/include/grpcpp/resource_quota_impl.h deleted file mode 100644 index 16c0e35385b..00000000000 --- a/include/grpcpp/resource_quota_impl.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef GRPCPP_RESOURCE_QUOTA_IMPL_H -#define GRPCPP_RESOURCE_QUOTA_IMPL_H - -struct grpc_resource_quota; - -#include -#include - -namespace grpc_impl { - -/// ResourceQuota represents a bound on memory and thread usage by the gRPC -/// library. A ResourceQuota can be attached to a server (via \a ServerBuilder), -/// or a client channel (via \a ChannelArguments). -/// gRPC will attempt to keep memory and threads used by all attached entities -/// below the ResourceQuota bound. -class ResourceQuota final : private ::grpc::GrpcLibraryCodegen { - public: - /// \param name - a unique name for this ResourceQuota. - explicit ResourceQuota(const grpc::string& name); - ResourceQuota(); - ~ResourceQuota(); - - /// Resize this \a ResourceQuota to a new size. If \a new_size is smaller - /// than the current size of the pool, memory usage will be monotonically - /// decreased until it falls under \a new_size. - /// No time bound is given for this to occur however. - ResourceQuota& Resize(size_t new_size); - - /// Set the max number of threads that can be allocated from this - /// ResourceQuota object. - /// - /// If the new_max_threads value is smaller than the current value, no new - /// threads are allocated until the number of active threads fall below - /// new_max_threads. There is no time bound on when this may happen i.e none - /// of the current threads are forcefully destroyed and all threads run their - /// normal course. - ResourceQuota& SetMaxThreads(int new_max_threads); - - grpc_resource_quota* c_resource_quota() const { return impl_; } - - private: - ResourceQuota(const ResourceQuota& rhs); - ResourceQuota& operator=(const ResourceQuota& rhs); - - grpc_resource_quota* const impl_; -}; - -} // namespace grpc_impl - -#endif // GRPCPP_RESOURCE_QUOTA_IMPL_H diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h index 4c00f021d11..498e5b7bb31 100644 --- a/include/grpcpp/server_builder.h +++ b/include/grpcpp/server_builder.h @@ -35,14 +35,10 @@ struct grpc_resource_quota; -namespace grpc_impl { - -class ResourceQuota; -} - namespace grpc { class AsyncGenericService; +class ResourceQuota; class CompletionQueue; class Server; class ServerCompletionQueue; @@ -190,8 +186,7 @@ class ServerBuilder { grpc_compression_algorithm algorithm); /// Set the attached buffer pool for this server - ServerBuilder& SetResourceQuota( - const ::grpc_impl::ResourceQuota& resource_quota); + ServerBuilder& SetResourceQuota(const ResourceQuota& resource_quota); ServerBuilder& SetOption(std::unique_ptr option); diff --git a/include/grpcpp/support/channel_arguments.h b/include/grpcpp/support/channel_arguments.h index 48ae4246462..217929d4aca 100644 --- a/include/grpcpp/support/channel_arguments.h +++ b/include/grpcpp/support/channel_arguments.h @@ -26,16 +26,13 @@ #include #include -namespace grpc_impl { - -class ResourceQuota; -} - namespace grpc { namespace testing { class ChannelArgumentsTest; } // namespace testing +class ResourceQuota; + /// Options for channel creation. The user can use generic setters to pass /// key value pairs down to C channel creation code. For gRPC related options, /// concrete setters are provided. @@ -86,7 +83,7 @@ class ChannelArguments { void SetUserAgentPrefix(const grpc::string& user_agent_prefix); /// Set the buffer pool to be attached to the constructed channel. - void SetResourceQuota(const ::grpc_impl::ResourceQuota& resource_quota); + void SetResourceQuota(const ResourceQuota& resource_quota); /// Set the max receive and send message sizes. void SetMaxReceiveMessageSize(int size); diff --git a/src/cpp/common/channel_arguments.cc b/src/cpp/common/channel_arguments.cc index c3d75054b9b..214d72f853f 100644 --- a/src/cpp/common/channel_arguments.cc +++ b/src/cpp/common/channel_arguments.cc @@ -143,7 +143,7 @@ void ChannelArguments::SetUserAgentPrefix( } void ChannelArguments::SetResourceQuota( - const grpc_impl::ResourceQuota& resource_quota) { + const grpc::ResourceQuota& resource_quota) { SetPointerWithVtable(GRPC_ARG_RESOURCE_QUOTA, resource_quota.c_resource_quota(), grpc_resource_quota_arg_vtable()); diff --git a/src/cpp/common/resource_quota_cc.cc b/src/cpp/common/resource_quota_cc.cc index 4fab2975d89..1ed92d7396d 100644 --- a/src/cpp/common/resource_quota_cc.cc +++ b/src/cpp/common/resource_quota_cc.cc @@ -19,7 +19,7 @@ #include #include -namespace grpc_impl { +namespace grpc { ResourceQuota::ResourceQuota() : impl_(grpc_resource_quota_create(nullptr)) {} diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index f60c77dc8d6..cd0e516d9a3 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -29,11 +29,6 @@ #include "src/core/lib/gpr/useful.h" #include "src/cpp/server/thread_pool_interface.h" -namespace grpc_impl { - -class ResourceQuota; -} - namespace grpc { static std::vector (*)()>* @@ -169,7 +164,7 @@ ServerBuilder& ServerBuilder::SetDefaultCompressionAlgorithm( } ServerBuilder& ServerBuilder::SetResourceQuota( - const grpc_impl::ResourceQuota& resource_quota) { + const grpc::ResourceQuota& resource_quota) { if (resource_quota_ != nullptr) { grpc_resource_quota_unref(resource_quota_); } diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc index 9343fd311e1..a5f8347c269 100644 --- a/test/cpp/qps/server_async.cc +++ b/test/cpp/qps/server_async.cc @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include From f58aed2d060440c17adeadbdd24632461730e5ed Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Tue, 19 Mar 2019 10:50:53 -0700 Subject: [PATCH 030/242] Make changes to server_posix to expose method outside --- include/grpcpp/server_posix.h | 12 ++++++++++++ src/cpp/common/resource_quota_cc.cc | 2 +- src/cpp/server/server_posix.cc | 6 +++--- tools/doxygen/Doxyfile.c++ | 1 - tools/doxygen/Doxyfile.c++.internal | 1 - tools/run_tests/generated/sources_and_headers.json | 2 -- 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/include/grpcpp/server_posix.h b/include/grpcpp/server_posix.h index 7b46967a8ba..3d209cbc14f 100644 --- a/include/grpcpp/server_posix.h +++ b/include/grpcpp/server_posix.h @@ -21,4 +21,16 @@ #include +namespace grpc { + +#ifdef GPR_SUPPORT_CHANNELS_FROM_FD + +static inline void AddInsecureChannelFromFd(Server* server, int fd) { + ::grpc_impl::AddInsecureChannelFromFd(server, fd); +} + +#endif // GPR_SUPPORT_CHANNELS_FROM_FD + +} // namespace grpc + #endif // GRPCPP_SERVER_POSIX_H diff --git a/src/cpp/common/resource_quota_cc.cc b/src/cpp/common/resource_quota_cc.cc index 1ed92d7396d..276e5f79548 100644 --- a/src/cpp/common/resource_quota_cc.cc +++ b/src/cpp/common/resource_quota_cc.cc @@ -37,4 +37,4 @@ ResourceQuota& ResourceQuota::SetMaxThreads(int new_max_threads) { grpc_resource_quota_set_max_threads(impl_, new_max_threads); return *this; } -} // namespace grpc_impl +} // namespace grpc diff --git a/src/cpp/server/server_posix.cc b/src/cpp/server/server_posix.cc index 7c221ed036a..7b77e24bc0e 100644 --- a/src/cpp/server/server_posix.cc +++ b/src/cpp/server/server_posix.cc @@ -20,14 +20,14 @@ #include -namespace grpc { +namespace grpc_impl { #ifdef GPR_SUPPORT_CHANNELS_FROM_FD -void AddInsecureChannelFromFd(Server* server, int fd) { +void AddInsecureChannelFromFd(grpc::Server* server, int fd) { grpc_server_add_insecure_channel_from_fd(server->c_server(), nullptr, fd); } #endif // GPR_SUPPORT_CHANNELS_FROM_FD -} // namespace grpc +} // namespace grpc_impl diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 367160a0ca9..9f17a25298a 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -995,7 +995,6 @@ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ -include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 4c1ba9d4f9d..c0078bf2764 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -997,7 +997,6 @@ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ -include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/credentials.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index bcf2cf4f5ec..8adde9ec602 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -11411,7 +11411,6 @@ "include/grpcpp/impl/server_initializer.h", "include/grpcpp/impl/service_type.h", "include/grpcpp/resource_quota.h", - "include/grpcpp/resource_quota_impl.h", "include/grpcpp/security/auth_context.h", "include/grpcpp/security/auth_metadata_processor.h", "include/grpcpp/security/credentials.h", @@ -11521,7 +11520,6 @@ "include/grpcpp/impl/server_initializer.h", "include/grpcpp/impl/service_type.h", "include/grpcpp/resource_quota.h", - "include/grpcpp/resource_quota_impl.h", "include/grpcpp/security/auth_context.h", "include/grpcpp/security/auth_metadata_processor.h", "include/grpcpp/security/credentials.h", From 526bf39f89322012b9da7d93de09c4b8ca7dfa7e Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Tue, 19 Mar 2019 12:27:22 -0700 Subject: [PATCH 031/242] Fold GenericStub from grpc_impl to grpc --- BUILD | 1 + CMakeLists.txt | 3 + Makefile | 3 + build.yaml | 1 + gRPC-C++.podspec | 1 + include/grpcpp/generic/generic_stub.h | 73 +------------ include/grpcpp/generic/generic_stub_impl.h | 103 ++++++++++++++++++ src/cpp/client/generic_stub.cc | 82 ++++++++------ tools/doxygen/Doxyfile.c++ | 1 + tools/doxygen/Doxyfile.c++.internal | 1 + .../generated/sources_and_headers.json | 2 + 11 files changed, 165 insertions(+), 106 deletions(-) create mode 100644 include/grpcpp/generic/generic_stub_impl.h diff --git a/BUILD b/BUILD index 9e052dcf0c2..1cc84247ab7 100644 --- a/BUILD +++ b/BUILD @@ -223,6 +223,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", "include/grpcpp/generic/generic_stub.h", + "include/grpcpp/generic/generic_stub_impl.h", "include/grpcpp/grpcpp.h", "include/grpcpp/health_check_service_interface.h", "include/grpcpp/impl/call.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 2308582c2f4..545d3b01e66 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3003,6 +3003,7 @@ foreach(_hdr include/grpcpp/ext/health_check_service_server_builder_option.h include/grpcpp/generic/async_generic_service.h include/grpcpp/generic/generic_stub.h + include/grpcpp/generic/generic_stub_impl.h include/grpcpp/grpcpp.h include/grpcpp/health_check_service_interface.h include/grpcpp/impl/call.h @@ -3593,6 +3594,7 @@ foreach(_hdr include/grpcpp/ext/health_check_service_server_builder_option.h include/grpcpp/generic/async_generic_service.h include/grpcpp/generic/generic_stub.h + include/grpcpp/generic/generic_stub_impl.h include/grpcpp/grpcpp.h include/grpcpp/health_check_service_interface.h include/grpcpp/impl/call.h @@ -4552,6 +4554,7 @@ foreach(_hdr include/grpcpp/ext/health_check_service_server_builder_option.h include/grpcpp/generic/async_generic_service.h include/grpcpp/generic/generic_stub.h + include/grpcpp/generic/generic_stub_impl.h include/grpcpp/grpcpp.h include/grpcpp/health_check_service_interface.h include/grpcpp/impl/call.h diff --git a/Makefile b/Makefile index 69a2abbc8ca..d5ca0a7f546 100644 --- a/Makefile +++ b/Makefile @@ -5428,6 +5428,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ + include/grpcpp/generic/generic_stub_impl.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ include/grpcpp/impl/call.h \ @@ -6027,6 +6028,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ + include/grpcpp/generic/generic_stub_impl.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ include/grpcpp/impl/call.h \ @@ -6939,6 +6941,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ + include/grpcpp/generic/generic_stub_impl.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ include/grpcpp/impl/call.h \ diff --git a/build.yaml b/build.yaml index 34b271f58de..d81dbd3fc51 100644 --- a/build.yaml +++ b/build.yaml @@ -1348,6 +1348,7 @@ filegroups: - include/grpcpp/ext/health_check_service_server_builder_option.h - include/grpcpp/generic/async_generic_service.h - include/grpcpp/generic/generic_stub.h + - include/grpcpp/generic/generic_stub_impl.h - include/grpcpp/grpcpp.h - include/grpcpp/health_check_service_interface.h - include/grpcpp/impl/call.h diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 5a850bc8438..0aee981b5f9 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -89,6 +89,7 @@ Pod::Spec.new do |s| 'include/grpcpp/ext/health_check_service_server_builder_option.h', 'include/grpcpp/generic/async_generic_service.h', 'include/grpcpp/generic/generic_stub.h', + 'include/grpcpp/generic/generic_stub_impl.h', 'include/grpcpp/grpcpp.h', 'include/grpcpp/health_check_service_interface.h', 'include/grpcpp/impl/call.h', diff --git a/include/grpcpp/generic/generic_stub.h b/include/grpcpp/generic/generic_stub.h index eb014184e4a..f4c4664f53c 100644 --- a/include/grpcpp/generic/generic_stub.h +++ b/include/grpcpp/generic/generic_stub.h @@ -19,80 +19,11 @@ #ifndef GRPCPP_GENERIC_GENERIC_STUB_H #define GRPCPP_GENERIC_GENERIC_STUB_H -#include - -#include -#include -#include -#include -#include +#include namespace grpc { -class CompletionQueue; -typedef ClientAsyncReaderWriter - GenericClientAsyncReaderWriter; -typedef ClientAsyncResponseReader GenericClientAsyncResponseReader; - -/// Generic stubs provide a type-unsafe interface to call gRPC methods -/// by name. -class GenericStub final { - public: - explicit GenericStub(std::shared_ptr channel) - : channel_(channel) {} - - /// Setup a call to a named method \a method using \a context, but don't - /// start it. Let it be started explicitly with StartCall and a tag. - /// The return value only indicates whether or not registration of the call - /// succeeded (i.e. the call won't proceed if the return value is nullptr). - std::unique_ptr PrepareCall( - ClientContext* context, const grpc::string& method, CompletionQueue* cq); - - /// Setup a unary call to a named method \a method using \a context, and don't - /// start it. Let it be started explicitly with StartCall. - /// The return value only indicates whether or not registration of the call - /// succeeded (i.e. the call won't proceed if the return value is nullptr). - std::unique_ptr PrepareUnaryCall( - ClientContext* context, const grpc::string& method, - const ByteBuffer& request, CompletionQueue* cq); - - /// DEPRECATED for multi-threaded use - /// Begin a call to a named method \a method using \a context. - /// A tag \a tag will be delivered to \a cq when the call has been started - /// (i.e, initial metadata has been sent). - /// The return value only indicates whether or not registration of the call - /// succeeded (i.e. the call won't proceed if the return value is nullptr). - std::unique_ptr Call( - ClientContext* context, const grpc::string& method, CompletionQueue* cq, - void* tag); - - /// NOTE: class experimental_type is not part of the public API of this class - /// TODO(vjpai): Move these contents to the public API of GenericStub when - /// they are no longer experimental - class experimental_type { - public: - explicit experimental_type(GenericStub* stub) : stub_(stub) {} - - void UnaryCall(ClientContext* context, const grpc::string& method, - const ByteBuffer* request, ByteBuffer* response, - std::function on_completion); - - void PrepareBidiStreamingCall( - ClientContext* context, const grpc::string& method, - experimental::ClientBidiReactor* reactor); - - private: - GenericStub* stub_; - }; - - /// NOTE: The function experimental() is not stable public API. It is a view - /// to the experimental components of this class. It may be changed or removed - /// at any time. - experimental_type experimental() { return experimental_type(this); } - - private: - std::shared_ptr channel_; -}; +typedef ::grpc_impl::GenericStub GenericStub; } // namespace grpc diff --git a/include/grpcpp/generic/generic_stub_impl.h b/include/grpcpp/generic/generic_stub_impl.h new file mode 100644 index 00000000000..5c8a8798969 --- /dev/null +++ b/include/grpcpp/generic/generic_stub_impl.h @@ -0,0 +1,103 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_GENERIC_GENERIC_STUB_IMPL_H +#define GRPCPP_GENERIC_GENERIC_STUB_IMPL_H + +#include + +#include +#include +#include +#include +#include + +namespace grpc { + +class CompletionQueue; +typedef ClientAsyncReaderWriter + GenericClientAsyncReaderWriter; +typedef ClientAsyncResponseReader GenericClientAsyncResponseReader; +} // namespace grpc +namespace grpc_impl { + +/// Generic stubs provide a type-unsafe interface to call gRPC methods +/// by name. +class GenericStub final { + public: + explicit GenericStub(std::shared_ptr channel) + : channel_(channel) {} + + /// Setup a call to a named method \a method using \a context, but don't + /// start it. Let it be started explicitly with StartCall and a tag. + /// The return value only indicates whether or not registration of the call + /// succeeded (i.e. the call won't proceed if the return value is nullptr). + std::unique_ptr PrepareCall( + grpc::ClientContext* context, const grpc::string& method, + grpc::CompletionQueue* cq); + + /// Setup a unary call to a named method \a method using \a context, and don't + /// start it. Let it be started explicitly with StartCall. + /// The return value only indicates whether or not registration of the call + /// succeeded (i.e. the call won't proceed if the return value is nullptr). + std::unique_ptr PrepareUnaryCall( + grpc::ClientContext* context, const grpc::string& method, + const grpc::ByteBuffer& request, grpc::CompletionQueue* cq); + + /// DEPRECATED for multi-threaded use + /// Begin a call to a named method \a method using \a context. + /// A tag \a tag will be delivered to \a cq when the call has been started + /// (i.e, initial metadata has been sent). + /// The return value only indicates whether or not registration of the call + /// succeeded (i.e. the call won't proceed if the return value is nullptr). + std::unique_ptr Call( + grpc::ClientContext* context, const grpc::string& method, + grpc::CompletionQueue* cq, void* tag); + + /// NOTE: class experimental_type is not part of the public API of this class + /// TODO(vjpai): Move these contents to the public API of GenericStub when + /// they are no longer experimental + class experimental_type { + public: + explicit experimental_type(GenericStub* stub) : stub_(stub) {} + + void UnaryCall(grpc::ClientContext* context, const grpc::string& method, + const grpc::ByteBuffer* request, grpc::ByteBuffer* response, + std::function on_completion); + + void PrepareBidiStreamingCall( + grpc::ClientContext* context, const grpc::string& method, + grpc::experimental::ClientBidiReactor* reactor); + + private: + GenericStub* stub_; + }; + + /// NOTE: The function experimental() is not stable public API. It is a view + /// to the experimental components of this class. It may be changed or removed + /// at any time. + experimental_type experimental() { return experimental_type(this); } + + private: + std::shared_ptr channel_; +}; + +} // namespace grpc_impl + +#endif // GRPCPP_GENERIC_GENERIC_STUB_IMPL_H diff --git a/src/cpp/client/generic_stub.cc b/src/cpp/client/generic_stub.cc index f61c1b5317b..41631c794f2 100644 --- a/src/cpp/client/generic_stub.cc +++ b/src/cpp/client/generic_stub.cc @@ -22,63 +22,75 @@ #include #include -namespace grpc { +namespace grpc_impl { namespace { -std::unique_ptr CallInternal( - ChannelInterface* channel, ClientContext* context, - const grpc::string& method, CompletionQueue* cq, bool start, void* tag) { - return std::unique_ptr( - internal::ClientAsyncReaderWriterFactory::Create( - channel, cq, - internal::RpcMethod(method.c_str(), - internal::RpcMethod::BIDI_STREAMING), - context, start, tag)); +std::unique_ptr CallInternal( + grpc::ChannelInterface* channel, grpc::ClientContext* context, + const grpc::string& method, grpc::CompletionQueue* cq, bool start, + void* tag) { + return std::unique_ptr( + grpc::internal::ClientAsyncReaderWriterFactory:: + Create(channel, cq, + grpc::internal::RpcMethod( + method.c_str(), grpc::internal::RpcMethod::BIDI_STREAMING), + context, start, tag)); } } // namespace // begin a call to a named method -std::unique_ptr GenericStub::Call( - ClientContext* context, const grpc::string& method, CompletionQueue* cq, - void* tag) { +std::unique_ptr GenericStub::Call( + grpc::ClientContext* context, const grpc::string& method, + grpc::CompletionQueue* cq, void* tag) { return CallInternal(channel_.get(), context, method, cq, true, tag); } // setup a call to a named method -std::unique_ptr GenericStub::PrepareCall( - ClientContext* context, const grpc::string& method, CompletionQueue* cq) { +std::unique_ptr GenericStub::PrepareCall( + grpc::ClientContext* context, const grpc::string& method, + grpc::CompletionQueue* cq) { return CallInternal(channel_.get(), context, method, cq, false, nullptr); } // setup a unary call to a named method -std::unique_ptr GenericStub::PrepareUnaryCall( - ClientContext* context, const grpc::string& method, - const ByteBuffer& request, CompletionQueue* cq) { - return std::unique_ptr( - internal::ClientAsyncResponseReaderFactory::Create( - channel_.get(), cq, - internal::RpcMethod(method.c_str(), internal::RpcMethod::NORMAL_RPC), - context, request, false)); +std::unique_ptr +GenericStub::PrepareUnaryCall(grpc::ClientContext* context, + const grpc::string& method, + const grpc::ByteBuffer& request, + grpc::CompletionQueue* cq) { + return std::unique_ptr( + grpc::internal::ClientAsyncResponseReaderFactory< + grpc::ByteBuffer>::Create(channel_.get(), cq, + grpc::internal::RpcMethod( + method.c_str(), + grpc::internal::RpcMethod::NORMAL_RPC), + context, request, false)); } void GenericStub::experimental_type::UnaryCall( - ClientContext* context, const grpc::string& method, - const ByteBuffer* request, ByteBuffer* response, - std::function on_completion) { - internal::CallbackUnaryCall( + grpc::ClientContext* context, const grpc::string& method, + const grpc::ByteBuffer* request, grpc::ByteBuffer* response, + std::function on_completion) { + grpc::internal::CallbackUnaryCall( stub_->channel_.get(), - internal::RpcMethod(method.c_str(), internal::RpcMethod::NORMAL_RPC), + grpc::internal::RpcMethod(method.c_str(), + grpc::internal::RpcMethod::NORMAL_RPC), context, request, response, std::move(on_completion)); } void GenericStub::experimental_type::PrepareBidiStreamingCall( - ClientContext* context, const grpc::string& method, - experimental::ClientBidiReactor* reactor) { - internal::ClientCallbackReaderWriterFactory::Create( - stub_->channel_.get(), - internal::RpcMethod(method.c_str(), internal::RpcMethod::BIDI_STREAMING), - context, reactor); + grpc::ClientContext* context, const grpc::string& method, + grpc::experimental::ClientBidiReactor* + reactor) { + grpc::internal::ClientCallbackReaderWriterFactory< + grpc::ByteBuffer, + grpc::ByteBuffer>::Create(stub_->channel_.get(), + grpc::internal::RpcMethod( + method.c_str(), + grpc::internal::RpcMethod::BIDI_STREAMING), + context, reactor); } -} // namespace grpc +} // namespace grpc_impl diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 9f17a25298a..fd6e35aa6ff 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -934,6 +934,7 @@ include/grpcpp/create_channel_posix.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ +include/grpcpp/generic/generic_stub_impl.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ include/grpcpp/impl/call.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index c0078bf2764..ee01a0b0295 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -935,6 +935,7 @@ include/grpcpp/create_channel_posix.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ +include/grpcpp/generic/generic_stub_impl.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ include/grpcpp/impl/call.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 2d427804d07..9d3172f5dcf 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -11418,6 +11418,7 @@ "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", "include/grpcpp/generic/generic_stub.h", + "include/grpcpp/generic/generic_stub_impl.h", "include/grpcpp/grpcpp.h", "include/grpcpp/health_check_service_interface.h", "include/grpcpp/impl/call.h", @@ -11527,6 +11528,7 @@ "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", "include/grpcpp/generic/generic_stub.h", + "include/grpcpp/generic/generic_stub_impl.h", "include/grpcpp/grpcpp.h", "include/grpcpp/health_check_service_interface.h", "include/grpcpp/impl/call.h", From d684ddc7e3091b8b5205b0cadbd786bd5f37487d Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Tue, 19 Mar 2019 12:49:42 -0700 Subject: [PATCH 032/242] Fold AuthMetadataProcessor into grpc_impl from grpc --- BUILD | 1 + build.yaml | 1 + .../grpcpp/security/auth_metadata_processor.h | 37 +---------- .../security/auth_metadata_processor_impl.h | 61 +++++++++++++++++++ 4 files changed, 66 insertions(+), 34 deletions(-) create mode 100644 include/grpcpp/security/auth_metadata_processor_impl.h diff --git a/BUILD b/BUILD index 9e052dcf0c2..21691b19c31 100644 --- a/BUILD +++ b/BUILD @@ -243,6 +243,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/resource_quota.h", "include/grpcpp/security/auth_context.h", "include/grpcpp/security/auth_metadata_processor.h", + "include/grpcpp/security/auth_metadata_processor_impl.h", "include/grpcpp/security/credentials.h", "include/grpcpp/security/server_credentials.h", "include/grpcpp/server.h", diff --git a/build.yaml b/build.yaml index 34b271f58de..23736cddf31 100644 --- a/build.yaml +++ b/build.yaml @@ -1366,6 +1366,7 @@ filegroups: - include/grpcpp/resource_quota.h - include/grpcpp/security/auth_context.h - include/grpcpp/security/auth_metadata_processor.h + - include/grpcpp/security/auth_metadata_processor_impl.h - include/grpcpp/security/credentials.h - include/grpcpp/security/server_credentials.h - include/grpcpp/server.h diff --git a/include/grpcpp/security/auth_metadata_processor.h b/include/grpcpp/security/auth_metadata_processor.h index 30e24c9f0bc..1b66b72b967 100644 --- a/include/grpcpp/security/auth_metadata_processor.h +++ b/include/grpcpp/security/auth_metadata_processor.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,42 +19,11 @@ #ifndef GRPCPP_SECURITY_AUTH_METADATA_PROCESSOR_H #define GRPCPP_SECURITY_AUTH_METADATA_PROCESSOR_H -#include - -#include -#include -#include +#include namespace grpc { -/// Interface allowing custom server-side authorization based on credentials -/// encoded in metadata. Objects of this type can be passed to -/// \a ServerCredentials::SetAuthMetadataProcessor(). -class AuthMetadataProcessor { - public: - typedef std::multimap InputMetadata; - typedef std::multimap OutputMetadata; - - virtual ~AuthMetadataProcessor() {} - - /// If this method returns true, the \a Process function will be scheduled in - /// a different thread from the one processing the call. - virtual bool IsBlocking() const { return true; } - - /// context is read/write: it contains the properties of the channel peer and - /// it is the job of the Process method to augment it with properties derived - /// from the passed-in auth_metadata. - /// consumed_auth_metadata needs to be filled with metadata that has been - /// consumed by the processor and will be removed from the call. - /// response_metadata is the metadata that will be sent as part of the - /// response. - /// If the return value is not Status::OK, the rpc call will be aborted with - /// the error code and error message sent back to the client. - virtual Status Process(const InputMetadata& auth_metadata, - AuthContext* context, - OutputMetadata* consumed_auth_metadata, - OutputMetadata* response_metadata) = 0; -}; +typedef ::grpc_impl::AuthMetadataProcessor AuthMetadataProcessor; } // namespace grpc diff --git a/include/grpcpp/security/auth_metadata_processor_impl.h b/include/grpcpp/security/auth_metadata_processor_impl.h new file mode 100644 index 00000000000..ae454200622 --- /dev/null +++ b/include/grpcpp/security/auth_metadata_processor_impl.h @@ -0,0 +1,61 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_SECURITY_AUTH_METADATA_PROCESSOR_IMPL_H +#define GRPCPP_SECURITY_AUTH_METADATA_PROCESSOR_IMPL_H + +#include + +#include +#include +#include + +namespace grpc_impl { + +/// Interface allowing custom server-side authorization based on credentials +/// encoded in metadata. Objects of this type can be passed to +/// \a ServerCredentials::SetAuthMetadataProcessor(). +class AuthMetadataProcessor { + public: + typedef std::multimap InputMetadata; + typedef std::multimap OutputMetadata; + + virtual ~AuthMetadataProcessor() {} + + /// If this method returns true, the \a Process function will be scheduled in + /// a different thread from the one processing the call. + virtual bool IsBlocking() const { return true; } + + /// context is read/write: it contains the properties of the channel peer and + /// it is the job of the Process method to augment it with properties derived + /// from the passed-in auth_metadata. + /// consumed_auth_metadata needs to be filled with metadata that has been + /// consumed by the processor and will be removed from the call. + /// response_metadata is the metadata that will be sent as part of the + /// response. + /// If the return value is not Status::OK, the rpc call will be aborted with + /// the error code and error message sent back to the client. + virtual grpc::Status Process(const InputMetadata& auth_metadata, + grpc::AuthContext* context, + OutputMetadata* consumed_auth_metadata, + OutputMetadata* response_metadata) = 0; +}; + +} // namespace grpc_impl + +#endif // GRPCPP_SECURITY_AUTH_METADATA_PROCESSOR_IMPL_H From 9c7a0c01ed6158535ae7d05c9ad4a13b6bfe1b9a Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Wed, 20 Mar 2019 05:15:25 +0100 Subject: [PATCH 033/242] Taking care of a last few memsets. --- .../health/health_check_client.cc | 4 --- .../google_default_credentials.cc | 1 - src/core/lib/transport/transport.cc | 1 - src/core/lib/transport/transport.h | 33 ++++++++++--------- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/core/ext/filters/client_channel/health/health_check_client.cc b/src/core/ext/filters/client_channel/health/health_check_client.cc index e845d63d295..84a7f35ed30 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.cc +++ b/src/core/ext/filters/client_channel/health/health_check_client.cc @@ -349,7 +349,6 @@ void HealthCheckClient::CallState::StartCall() { return; } // Initialize payload and batch. - memset(&batch_, 0, sizeof(batch_)); payload_.context = context_; batch_.payload = &payload_; // on_complete callback takes ref, handled manually. @@ -401,8 +400,6 @@ void HealthCheckClient::CallState::StartCall() { // Start batch. StartBatch(&batch_); // Initialize recv_trailing_metadata batch. - memset(&recv_trailing_metadata_batch_, 0, - sizeof(recv_trailing_metadata_batch_)); recv_trailing_metadata_batch_.payload = &payload_; // Add recv_trailing_metadata op. grpc_metadata_batch_init(&recv_trailing_metadata_); @@ -507,7 +504,6 @@ void HealthCheckClient::CallState::DoneReadingRecvMessage(grpc_error* error) { // This re-uses the ref we're holding. // Note: Can't just reuse batch_ here, since we don't know that all // callbacks from the original batch have completed yet. - memset(&recv_message_batch_, 0, sizeof(recv_message_batch_)); recv_message_batch_.payload = &payload_; payload_.recv_message.recv_message = &recv_message_; payload_.recv_message.recv_message_ready = GRPC_CLOSURE_INIT( diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.cc b/src/core/lib/security/credentials/google_default/google_default_credentials.cc index b6a79c1030e..adc76cb1740 100644 --- a/src/core/lib/security/credentials/google_default/google_default_credentials.cc +++ b/src/core/lib/security/credentials/google_default/google_default_credentials.cc @@ -172,7 +172,6 @@ static int is_metadata_server_reachable() { detector.pollent = grpc_polling_entity_create_from_pollset(pollset); detector.is_done = 0; detector.success = 0; - memset(&detector.response, 0, sizeof(detector.response)); memset(&request, 0, sizeof(grpc_httpcli_request)); request.host = (char*)GRPC_COMPUTE_ENGINE_DETECTION_HOST; request.http.path = (char*)"/"; diff --git a/src/core/lib/transport/transport.cc b/src/core/lib/transport/transport.cc index 8be0b91b654..3fc089676ea 100644 --- a/src/core/lib/transport/transport.cc +++ b/src/core/lib/transport/transport.cc @@ -261,7 +261,6 @@ grpc_transport_op* grpc_make_transport_op(grpc_closure* on_complete) { GRPC_CLOSURE_INIT(&op->outer_on_complete, destroy_made_transport_op, op, grpc_schedule_on_exec_ctx); op->inner_on_complete = on_complete; - memset(&op->op, 0, sizeof(op->op)); op->op.on_consumed = &op->outer_on_complete; return &op->op; } diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index 5ce568834e9..8631a1af81f 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -111,10 +111,11 @@ void grpc_transport_move_stats(grpc_transport_stream_stats* from, // currently handling the batch). Once a filter or transport passes control // of the batch to the next handler, it cannot depend on the contents of // this struct anymore, because the next handler may reuse it. -typedef struct { - void* extra_arg; +struct grpc_handler_private_op_data { + void* extra_arg = nullptr; grpc_closure closure; -} grpc_handler_private_op_data; + grpc_handler_private_op_data() { memset(&closure, 0, sizeof(closure)); } +}; typedef struct grpc_transport_stream_op_batch_payload grpc_transport_stream_op_batch_payload; @@ -272,40 +273,40 @@ struct grpc_transport_stream_op_batch_payload { /** Transport op: a set of operations to perform on a transport as a whole */ typedef struct grpc_transport_op { /** Called when processing of this op is done. */ - grpc_closure* on_consumed; + grpc_closure* on_consumed = nullptr; /** connectivity monitoring - set connectivity_state to NULL to unsubscribe */ - grpc_closure* on_connectivity_state_change; - grpc_connectivity_state* connectivity_state; + grpc_closure* on_connectivity_state_change = nullptr; + grpc_connectivity_state* connectivity_state = nullptr; /** should the transport be disconnected * Error contract: the transport that gets this op must cause * disconnect_with_error to be unref'ed after processing it */ - grpc_error* disconnect_with_error; + grpc_error* disconnect_with_error = nullptr; /** what should the goaway contain? * Error contract: the transport that gets this op must cause * goaway_error to be unref'ed after processing it */ - grpc_error* goaway_error; + grpc_error* goaway_error = nullptr; /** set the callback for accepting new streams; this is a permanent callback, unlike the other one-shot closures. If true, the callback is set to set_accept_stream_fn, with its user_data argument set to set_accept_stream_user_data */ - bool set_accept_stream; + bool set_accept_stream = false; void (*set_accept_stream_fn)(void* user_data, grpc_transport* transport, - const void* server_data); - void* set_accept_stream_user_data; + const void* server_data) = nullptr; + void* set_accept_stream_user_data = nullptr; /** add this transport to a pollset */ - grpc_pollset* bind_pollset; + grpc_pollset* bind_pollset = nullptr; /** add this transport to a pollset_set */ - grpc_pollset_set* bind_pollset_set; + grpc_pollset_set* bind_pollset_set = nullptr; /** send a ping, if either on_initiate or on_ack is not NULL */ struct { /** Ping may be delayed by the transport, on_initiate callback will be called when the ping is actually being sent. */ - grpc_closure* on_initiate; + grpc_closure* on_initiate = nullptr; /** Called when the ping ack is received */ - grpc_closure* on_ack; + grpc_closure* on_ack = nullptr; } send_ping; // If true, will reset the channel's connection backoff. - bool reset_connect_backoff; + bool reset_connect_backoff = false; /*************************************************************************** * remaining fields are initialized and used at the discretion of the From 54171e276fc74286cba80ae18021bc414d4caf61 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Wed, 20 Mar 2019 10:00:34 -0700 Subject: [PATCH 034/242] Fold server credentials from grpc to grpc_impl namespace --- BUILD | 1 + .../grpcpp/impl/codegen/server_interface.h | 7 +- include/grpcpp/security/server_credentials.h | 92 ++++----------- .../grpcpp/security/server_credentials_impl.h | 110 ++++++++++++++++++ include/grpcpp/server_builder.h | 11 +- src/cpp/server/insecure_server_credentials.cc | 6 +- src/cpp/server/secure_server_credentials.cc | 14 ++- src/cpp/server/secure_server_credentials.h | 19 ++- src/cpp/server/server_credentials.cc | 4 +- test/cpp/util/grpc_tool_test.cc | 2 +- test/cpp/util/test_credentials_provider.cc | 2 +- 11 files changed, 175 insertions(+), 93 deletions(-) create mode 100644 include/grpcpp/security/server_credentials_impl.h diff --git a/BUILD b/BUILD index 9e052dcf0c2..e0b8060cca1 100644 --- a/BUILD +++ b/BUILD @@ -245,6 +245,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/security/auth_metadata_processor.h", "include/grpcpp/security/credentials.h", "include/grpcpp/security/server_credentials.h", + "include/grpcpp/security/server_credentials_impl.h", "include/grpcpp/server.h", "include/grpcpp/server_builder.h", "include/grpcpp/server_context.h", diff --git a/include/grpcpp/impl/codegen/server_interface.h b/include/grpcpp/impl/codegen/server_interface.h index f599e037fd5..a0b0a580979 100644 --- a/include/grpcpp/impl/codegen/server_interface.h +++ b/include/grpcpp/impl/codegen/server_interface.h @@ -28,6 +28,10 @@ #include #include +namespace grpc_impl { + +class ServerCredentials; +} namespace grpc { class AsyncGenericService; @@ -35,7 +39,6 @@ class Channel; class GenericServerContext; class ServerCompletionQueue; class ServerContext; -class ServerCredentials; class Service; extern CoreCodegenInterface* g_core_codegen_interface; @@ -150,7 +153,7 @@ class ServerInterface : public internal::CallHook { /// /// \warning It's an error to call this method on an already started server. virtual int AddListeningPort(const grpc::string& addr, - ServerCredentials* creds) = 0; + grpc_impl::ServerCredentials* creds) = 0; /// Start the server. /// diff --git a/include/grpcpp/security/server_credentials.h b/include/grpcpp/security/server_credentials.h index bd00a0a1737..f1318b6fb0d 100644 --- a/include/grpcpp/security/server_credentials.h +++ b/include/grpcpp/security/server_credentials.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,87 +19,35 @@ #ifndef GRPCPP_SECURITY_SERVER_CREDENTIALS_H #define GRPCPP_SECURITY_SERVER_CREDENTIALS_H -#include -#include - -#include -#include -#include - -struct grpc_server; +#include namespace grpc { -class Server; -/// Wrapper around \a grpc_server_credentials, a way to authenticate a server. -class ServerCredentials { - public: - virtual ~ServerCredentials(); +typedef ::grpc_impl::ServerCredentials ServerCredentials; +typedef ::grpc_impl::SslServerCredentialsOptions SslServerCredentialsOptions; - /// This method is not thread-safe and has to be called before the server is - /// started. The last call to this function wins. - virtual void SetAuthMetadataProcessor( - const std::shared_ptr& processor) = 0; +static inline std::shared_ptr SslServerCredentials( + const SslServerCredentialsOptions& options) { + return ::grpc_impl::SslServerCredentials(options); +} - private: - friend class ::grpc::Server; - - /// Tries to bind \a server to the given \a addr (eg, localhost:1234, - /// 192.168.1.1:31416, [::1]:27182, etc.) - /// - /// \return bound port number on sucess, 0 on failure. - // TODO(dgq): the "port" part seems to be a misnomer. - virtual int AddPortToServer(const grpc::string& addr, - grpc_server* server) = 0; -}; - -/// Options to create ServerCredentials with SSL -struct SslServerCredentialsOptions { - /// \warning Deprecated - SslServerCredentialsOptions() - : force_client_auth(false), - client_certificate_request(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE) {} - SslServerCredentialsOptions( - grpc_ssl_client_certificate_request_type request_type) - : force_client_auth(false), client_certificate_request(request_type) {} - - struct PemKeyCertPair { - grpc::string private_key; - grpc::string cert_chain; - }; - grpc::string pem_root_certs; - std::vector pem_key_cert_pairs; - /// \warning Deprecated - bool force_client_auth; - - /// If both \a force_client_auth and \a client_certificate_request - /// fields are set, \a force_client_auth takes effect, i.e. - /// \a REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY - /// will be enforced. - grpc_ssl_client_certificate_request_type client_certificate_request; -}; - -/// Builds SSL ServerCredentials given SSL specific options -std::shared_ptr SslServerCredentials( - const SslServerCredentialsOptions& options); - -/// Builds insecure server credentials. -std::shared_ptr InsecureServerCredentials(); +static inline std::shared_ptr InsecureServerCredentials() { + return ::grpc_impl::InsecureServerCredentials(); +} namespace experimental { -/// Options to create ServerCredentials with ALTS -struct AltsServerCredentialsOptions { - /// Add fields if needed. -}; +typedef ::grpc_impl::experimental::AltsServerCredentialsOptions AltsServerCredentialsOptions; -/// Builds ALTS ServerCredentials given ALTS specific options -std::shared_ptr AltsServerCredentials( - const AltsServerCredentialsOptions& options); +static inline std::shared_ptr AltsServerCredentials( + const AltsServerCredentialsOptions& options) { + return ::grpc_impl::experimental::AltsServerCredentials(options); +} -/// Builds Local ServerCredentials. -std::shared_ptr LocalServerCredentials( - grpc_local_connect_type type); +static inline std::shared_ptr LocalServerCredentials( + grpc_local_connect_type type) { + return ::grpc_impl::experimental::LocalServerCredentials(type); +} } // namespace experimental } // namespace grpc diff --git a/include/grpcpp/security/server_credentials_impl.h b/include/grpcpp/security/server_credentials_impl.h new file mode 100644 index 00000000000..f78de305f26 --- /dev/null +++ b/include/grpcpp/security/server_credentials_impl.h @@ -0,0 +1,110 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_SECURITY_SERVER_CREDENTIALS_IMPL_H +#define GRPCPP_SECURITY_SERVER_CREDENTIALS_IMPL_H + +#include +#include + +#include +#include +#include + +struct grpc_server; + +namespace grpc { + +class Server; +} // namespace grpc +namespace grpc_impl { + +/// Wrapper around \a grpc_server_credentials, a way to authenticate a server. +class ServerCredentials { + public: + virtual ~ServerCredentials(); + + /// This method is not thread-safe and has to be called before the server is + /// started. The last call to this function wins. + virtual void SetAuthMetadataProcessor( + const std::shared_ptr& processor) = 0; + + private: + friend class ::grpc::Server; + + /// Tries to bind \a server to the given \a addr (eg, localhost:1234, + /// 192.168.1.1:31416, [::1]:27182, etc.) + /// + /// \return bound port number on sucess, 0 on failure. + // TODO(dgq): the "port" part seems to be a misnomer. + virtual int AddPortToServer(const grpc::string& addr, + grpc_server* server) = 0; +}; + +/// Options to create ServerCredentials with SSL +struct SslServerCredentialsOptions { + /// \warning Deprecated + SslServerCredentialsOptions() + : force_client_auth(false), + client_certificate_request(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE) {} + SslServerCredentialsOptions( + grpc_ssl_client_certificate_request_type request_type) + : force_client_auth(false), client_certificate_request(request_type) {} + + struct PemKeyCertPair { + grpc::string private_key; + grpc::string cert_chain; + }; + grpc::string pem_root_certs; + std::vector pem_key_cert_pairs; + /// \warning Deprecated + bool force_client_auth; + + /// If both \a force_client_auth and \a client_certificate_request + /// fields are set, \a force_client_auth takes effect, i.e. + /// \a REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY + /// will be enforced. + grpc_ssl_client_certificate_request_type client_certificate_request; +}; + +/// Builds SSL ServerCredentials given SSL specific options +std::shared_ptr SslServerCredentials( + const SslServerCredentialsOptions& options); + +/// Builds insecure server credentials. +std::shared_ptr InsecureServerCredentials(); + +namespace experimental { + +/// Options to create ServerCredentials with ALTS +struct AltsServerCredentialsOptions { + /// Add fields if needed. +}; + +/// Builds ALTS ServerCredentials given ALTS specific options +std::shared_ptr AltsServerCredentials( + const AltsServerCredentialsOptions& options); + +/// Builds Local ServerCredentials. +std::shared_ptr LocalServerCredentials( + grpc_local_connect_type type); + +} // namespace experimental +} // namespace grpc_impl + +#endif // GRPCPP_SECURITY_SERVER_CREDENTIALS_IMPL_H diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h index 498e5b7bb31..d657c7151f8 100644 --- a/include/grpcpp/server_builder.h +++ b/include/grpcpp/server_builder.h @@ -35,6 +35,10 @@ struct grpc_resource_quota; +namespace grpc_impl { + +class ServerCredentials; +} namespace grpc { class AsyncGenericService; @@ -42,7 +46,6 @@ class ResourceQuota; class CompletionQueue; class Server; class ServerCompletionQueue; -class ServerCredentials; class Service; namespace testing { @@ -94,7 +97,7 @@ class ServerBuilder { /// it is successfully bound by BuildAndStart(), 0 otherwise. AddListeningPort /// does not modify this pointer. ServerBuilder& AddListeningPort(const grpc::string& addr_uri, - std::shared_ptr creds, + std::shared_ptr creds, int* selected_port = nullptr); /// Add a completion queue for handling asynchronous services. @@ -247,7 +250,7 @@ class ServerBuilder { /// Experimental, to be deprecated struct Port { grpc::string addr; - std::shared_ptr creds; + std::shared_ptr creds; int* selected_port; }; @@ -315,7 +318,7 @@ class ServerBuilder { /// List of completion queues added via \a AddCompletionQueue method. std::vector cqs_; - std::shared_ptr creds_; + std::shared_ptr creds_; std::vector> plugins_; grpc_resource_quota* resource_quota_; AsyncGenericService* generic_service_{nullptr}; diff --git a/src/cpp/server/insecure_server_credentials.cc b/src/cpp/server/insecure_server_credentials.cc index 7d749ddca4d..e4623ececef 100644 --- a/src/cpp/server/insecure_server_credentials.cc +++ b/src/cpp/server/insecure_server_credentials.cc @@ -21,7 +21,7 @@ #include #include -namespace grpc { +namespace grpc_impl { namespace { class InsecureServerCredentialsImpl final : public ServerCredentials { public: @@ -29,7 +29,7 @@ class InsecureServerCredentialsImpl final : public ServerCredentials { return grpc_server_add_insecure_http2_port(server, addr.c_str()); } void SetAuthMetadataProcessor( - const std::shared_ptr& processor) override { + const std::shared_ptr& processor) override { (void)processor; GPR_ASSERT(0); // Should not be called on InsecureServerCredentials. } @@ -41,4 +41,4 @@ std::shared_ptr InsecureServerCredentials() { new InsecureServerCredentialsImpl()); } -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc index 453e76eb25d..fc23ba25d6f 100644 --- a/src/cpp/server/secure_server_credentials.cc +++ b/src/cpp/server/secure_server_credentials.cc @@ -93,17 +93,21 @@ void AuthMetadataProcessorAyncWrapper::InvokeProcessor( status.error_message().c_str()); } +} // namespace grpc + +namespace grpc_impl { + int SecureServerCredentials::AddPortToServer(const grpc::string& addr, grpc_server* server) { return grpc_server_add_secure_http2_port(server, addr.c_str(), creds_); } void SecureServerCredentials::SetAuthMetadataProcessor( - const std::shared_ptr& processor) { - auto* wrapper = new AuthMetadataProcessorAyncWrapper(processor); + const std::shared_ptr& processor) { + auto* wrapper = new grpc::AuthMetadataProcessorAyncWrapper(processor); grpc_server_credentials_set_auth_metadata_processor( - creds_, {AuthMetadataProcessorAyncWrapper::Process, - AuthMetadataProcessorAyncWrapper::Destroy, wrapper}); + creds_, {grpc::AuthMetadataProcessorAyncWrapper::Process, + grpc::AuthMetadataProcessorAyncWrapper::Destroy, wrapper}); } std::shared_ptr SslServerCredentials( @@ -147,4 +151,4 @@ std::shared_ptr LocalServerCredentials( } } // namespace experimental -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/server/secure_server_credentials.h b/src/cpp/server/secure_server_credentials.h index 8a81af2f591..3c7fbe13336 100644 --- a/src/cpp/server/secure_server_credentials.h +++ b/src/cpp/server/secure_server_credentials.h @@ -27,8 +27,15 @@ #include "src/cpp/server/thread_pool_interface.h" +namespace grpc_impl { + +class SecureServerCredentials; +} // namespace grpc_impl + namespace grpc { +typedef ::grpc_impl::SecureServerCredentials SecureServerCredentials; + class AuthMetadataProcessorAyncWrapper final { public: static void Destroy(void* wrapper); @@ -49,6 +56,10 @@ class AuthMetadataProcessorAyncWrapper final { std::shared_ptr processor_; }; +} // namespace grpc + +namespace grpc_impl { + class SecureServerCredentials final : public ServerCredentials { public: explicit SecureServerCredentials(grpc_server_credentials* creds) @@ -60,13 +71,15 @@ class SecureServerCredentials final : public ServerCredentials { int AddPortToServer(const grpc::string& addr, grpc_server* server) override; void SetAuthMetadataProcessor( - const std::shared_ptr& processor) override; + const std::shared_ptr& processor) override; private: grpc_server_credentials* creds_; - std::unique_ptr processor_; + std::unique_ptr processor_; }; -} // namespace grpc +} // namespace grpc_impl + + #endif // GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H diff --git a/src/cpp/server/server_credentials.cc b/src/cpp/server/server_credentials.cc index c3b3a8b3793..7478d06e94e 100644 --- a/src/cpp/server/server_credentials.cc +++ b/src/cpp/server/server_credentials.cc @@ -16,9 +16,9 @@ * */ -#include +#include -namespace grpc { +namespace grpc_impl { ServerCredentials::~ServerCredentials() {} diff --git a/test/cpp/util/grpc_tool_test.cc b/test/cpp/util/grpc_tool_test.cc index 57cdbeb7b76..5707e6b85fa 100644 --- a/test/cpp/util/grpc_tool_test.cc +++ b/test/cpp/util/grpc_tool_test.cc @@ -246,7 +246,7 @@ class GrpcToolTest : public ::testing::Test { SslServerCredentialsOptions ssl_opts; ssl_opts.pem_root_certs = ""; ssl_opts.pem_key_cert_pairs.push_back(pkcp); - creds = SslServerCredentials(ssl_opts); + creds = grpc::SslServerCredentials(ssl_opts); } else { creds = InsecureServerCredentials(); } diff --git a/test/cpp/util/test_credentials_provider.cc b/test/cpp/util/test_credentials_provider.cc index 0cf75f1e5f1..f08b0c2294b 100644 --- a/test/cpp/util/test_credentials_provider.cc +++ b/test/cpp/util/test_credentials_provider.cc @@ -91,7 +91,7 @@ class DefaultCredentialsProvider : public CredentialsProvider { SslServerCredentialsOptions ssl_opts; ssl_opts.pem_root_certs = ""; ssl_opts.pem_key_cert_pairs.push_back(pkcp); - return SslServerCredentials(ssl_opts); + return grpc::SslServerCredentials(ssl_opts); } else { std::unique_lock lock(mu_); auto it(std::find(added_secure_type_names_.begin(), From 338b4cb5c9fb20383a0c0ea48bcc08a883a72385 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Wed, 20 Mar 2019 11:17:46 -0700 Subject: [PATCH 035/242] Fold ErrorDetails into grpc_impl from grpc --- BUILD | 1 + include/grpcpp/support/error_details.h | 20 ++++----- include/grpcpp/support/error_details_impl.h | 48 +++++++++++++++++++++ src/cpp/util/error_details.cc | 30 +++++++------ 4 files changed, 74 insertions(+), 25 deletions(-) create mode 100644 include/grpcpp/support/error_details_impl.h diff --git a/BUILD b/BUILD index 9e052dcf0c2..992c27fe75c 100644 --- a/BUILD +++ b/BUILD @@ -395,6 +395,7 @@ grpc_cc_library( hdrs = [ "include/grpc++/support/error_details.h", "include/grpcpp/support/error_details.h", + "include/grpcpp/support/error_details_impl.h", ], language = "c++", standalone = True, diff --git a/include/grpcpp/support/error_details.h b/include/grpcpp/support/error_details.h index 84931d98f18..07bc750db5c 100644 --- a/include/grpcpp/support/error_details.h +++ b/include/grpcpp/support/error_details.h @@ -19,7 +19,7 @@ #ifndef GRPCPP_SUPPORT_ERROR_DETAILS_H #define GRPCPP_SUPPORT_ERROR_DETAILS_H -#include +#include namespace google { namespace rpc { @@ -29,17 +29,15 @@ class Status; namespace grpc { -/// Map a \a grpc::Status to a \a google::rpc::Status. -/// The given \a to object will be cleared. -/// On success, returns status with OK. -/// Returns status with \a INVALID_ARGUMENT, if failed to deserialize. -/// Returns status with \a FAILED_PRECONDITION, if \a to is nullptr. -Status ExtractErrorDetails(const Status& from, ::google::rpc::Status* to); +static inline Status ExtractErrorDetails(const Status& from, + ::google::rpc::Status* to) { + return ::grpc_impl::ExtractErrorDetails(from, to); +} -/// Map \a google::rpc::Status to a \a grpc::Status. -/// Returns OK on success. -/// Returns status with \a FAILED_PRECONDITION if \a to is nullptr. -Status SetErrorDetails(const ::google::rpc::Status& from, Status* to); +static inline Status SetErrorDetails(const ::google::rpc::Status& from, + Status* to) { + return ::grpc_impl::SetErrorDetails(from, to); +} } // namespace grpc diff --git a/include/grpcpp/support/error_details_impl.h b/include/grpcpp/support/error_details_impl.h new file mode 100644 index 00000000000..daa630c1c3e --- /dev/null +++ b/include/grpcpp/support/error_details_impl.h @@ -0,0 +1,48 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_SUPPORT_ERROR_DETAILS__IMPL_H +#define GRPCPP_SUPPORT_ERROR_DETAILS_IMPL_H + +#include + +namespace google { +namespace rpc { +class Status; +} // namespace rpc +} // namespace google + +namespace grpc_impl { + +/// Map a \a grpc::Status to a \a google::rpc::Status. +/// The given \a to object will be cleared. +/// On success, returns status with OK. +/// Returns status with \a INVALID_ARGUMENT, if failed to deserialize. +/// Returns status with \a FAILED_PRECONDITION, if \a to is nullptr. +grpc::Status ExtractErrorDetails(const grpc::Status& from, + ::google::rpc::Status* to); + +/// Map \a google::rpc::Status to a \a grpc::Status. +/// Returns OK on success. +/// Returns status with \a FAILED_PRECONDITION if \a to is nullptr. +grpc::Status SetErrorDetails(const ::google::rpc::Status& from, + grpc::Status* to); + +} // namespace grpc_impl + +#endif // GRPCPP_SUPPORT_ERROR_DETAILS_IMPL_H diff --git a/src/cpp/util/error_details.cc b/src/cpp/util/error_details.cc index 42c887aed73..a1aafcbdc6e 100644 --- a/src/cpp/util/error_details.cc +++ b/src/cpp/util/error_details.cc @@ -20,29 +20,31 @@ #include "src/proto/grpc/status/status.pb.h" -namespace grpc { +namespace grpc_impl { -Status ExtractErrorDetails(const Status& from, ::google::rpc::Status* to) { +grpc::Status ExtractErrorDetails(const grpc::Status& from, + ::google::rpc::Status* to) { if (to == nullptr) { - return Status(StatusCode::FAILED_PRECONDITION, ""); + return grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, ""); } if (!to->ParseFromString(from.error_details())) { - return Status(StatusCode::INVALID_ARGUMENT, ""); + return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, ""); } - return Status::OK; + return grpc::Status::OK; } -Status SetErrorDetails(const ::google::rpc::Status& from, Status* to) { +grpc::Status SetErrorDetails(const ::google::rpc::Status& from, + grpc::Status* to) { if (to == nullptr) { - return Status(StatusCode::FAILED_PRECONDITION, ""); + return grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, ""); } - StatusCode code = StatusCode::UNKNOWN; - if (from.code() >= StatusCode::OK && - from.code() <= StatusCode::UNAUTHENTICATED) { - code = static_cast(from.code()); + grpc::StatusCode code = grpc::StatusCode::UNKNOWN; + if (from.code() >= grpc::StatusCode::OK && + from.code() <= grpc::StatusCode::UNAUTHENTICATED) { + code = static_cast(from.code()); } - *to = Status(code, from.message(), from.SerializeAsString()); - return Status::OK; + *to = grpc::Status(code, from.message(), from.SerializeAsString()); + return grpc::Status::OK; } -} // namespace grpc +} // namespace grpc_impl From 04af168cf852236f71d08f34d45442725567b9c6 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Wed, 20 Mar 2019 13:05:36 -0700 Subject: [PATCH 036/242] Move Server into grpc_impl from grpc --- BUILD | 1 + .../impl/codegen/async_generic_service.h | 10 +- include/grpcpp/impl/codegen/async_stream.h | 2 +- .../grpcpp/impl/codegen/completion_queue.h | 9 +- include/grpcpp/impl/codegen/server_context.h | 7 +- include/grpcpp/impl/codegen/service_type.h | 7 +- include/grpcpp/impl/server_initializer.h | 5 +- include/grpcpp/security/server_credentials.h | 7 +- include/grpcpp/server.h | 325 +-- include/grpcpp/server_builder.h | 7 +- include/grpcpp/server_impl.h | 353 +++ src/cpp/server/server_cc.cc | 2110 +++++++++-------- test/cpp/util/metrics_server.h | 2 + 13 files changed, 1452 insertions(+), 1393 deletions(-) create mode 100644 include/grpcpp/server_impl.h diff --git a/BUILD b/BUILD index 9e052dcf0c2..ee6e4fce32d 100644 --- a/BUILD +++ b/BUILD @@ -246,6 +246,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/security/credentials.h", "include/grpcpp/security/server_credentials.h", "include/grpcpp/server.h", + "include/grpcpp/server_impl.h", "include/grpcpp/server_builder.h", "include/grpcpp/server_context.h", "include/grpcpp/server_posix.h", diff --git a/include/grpcpp/impl/codegen/async_generic_service.h b/include/grpcpp/impl/codegen/async_generic_service.h index 46489b135d7..4e680bb1c76 100644 --- a/include/grpcpp/impl/codegen/async_generic_service.h +++ b/include/grpcpp/impl/codegen/async_generic_service.h @@ -39,7 +39,7 @@ class GenericServerContext final : public ServerContext { const grpc::string& host() const { return host_; } private: - friend class Server; + friend class grpc_impl::Server; friend class ServerInterface; void Clear() { @@ -79,8 +79,8 @@ class AsyncGenericService final { ServerCompletionQueue* notification_cq, void* tag); private: - friend class Server; - Server* server_; + friend class grpc_impl::Server; + grpc_impl::Server* server_; }; namespace experimental { @@ -117,14 +117,14 @@ class CallbackGenericService { } private: - friend class ::grpc::Server; + friend class ::grpc_impl::Server; internal::CallbackBidiHandler* Handler() { return new internal::CallbackBidiHandler( [this] { return CreateReactor(); }); } - Server* server_{nullptr}; + grpc_impl::Server* server_{nullptr}; }; } // namespace experimental } // namespace grpc diff --git a/include/grpcpp/impl/codegen/async_stream.h b/include/grpcpp/impl/codegen/async_stream.h index bfb2df4f232..e12923ea02c 100644 --- a/include/grpcpp/impl/codegen/async_stream.h +++ b/include/grpcpp/impl/codegen/async_stream.h @@ -1099,7 +1099,7 @@ class ServerAsyncReaderWriter final } private: - friend class ::grpc::Server; + friend class ::grpc_impl::Server; void BindCall(::grpc::internal::Call* call) override { call_ = *call; } diff --git a/include/grpcpp/impl/codegen/completion_queue.h b/include/grpcpp/impl/codegen/completion_queue.h index 4812f0253d4..559b7b7fe47 100644 --- a/include/grpcpp/impl/codegen/completion_queue.h +++ b/include/grpcpp/impl/codegen/completion_queue.h @@ -41,6 +41,10 @@ struct grpc_completion_queue; +namespace grpc_impl { + +class Server; +} // namespace grpc_impl namespace grpc { template @@ -62,7 +66,6 @@ class Channel; class ChannelInterface; class ClientContext; class CompletionQueue; -class Server; class ServerBuilder; class ServerContext; class ServerInterface; @@ -271,7 +274,7 @@ class CompletionQueue : private GrpcLibraryCodegen { friend class ::grpc::internal::TemplatedBidiStreamingHandler; template friend class ::grpc::internal::ErrorMethodHandler; - friend class ::grpc::Server; + friend class ::grpc_impl::Server; friend class ::grpc::ServerContext; friend class ::grpc::ServerInterface; template @@ -406,7 +409,7 @@ class ServerCompletionQueue : public CompletionQueue { grpc_cq_polling_type polling_type_; friend class ServerBuilder; - friend class Server; + friend class grpc_impl::Server; }; } // namespace grpc diff --git a/include/grpcpp/impl/codegen/server_context.h b/include/grpcpp/impl/codegen/server_context.h index 591a9ff9549..c2959d95de7 100644 --- a/include/grpcpp/impl/codegen/server_context.h +++ b/include/grpcpp/impl/codegen/server_context.h @@ -41,11 +41,14 @@ struct grpc_metadata; struct grpc_call; struct census_context; +namespace grpc_impl { + +class Server; +} // namespace grpc_impl namespace grpc { class ClientContext; class GenericServerContext; class CompletionQueue; -class Server; class ServerInterface; template class ServerAsyncReader; @@ -269,7 +272,7 @@ class ServerContext { friend class ::grpc::testing::InteropServerContextInspector; friend class ::grpc::testing::ServerContextTestSpouse; friend class ::grpc::ServerInterface; - friend class ::grpc::Server; + friend class ::grpc_impl::Server; template friend class ::grpc::ServerAsyncReader; template diff --git a/include/grpcpp/impl/codegen/service_type.h b/include/grpcpp/impl/codegen/service_type.h index 332a04c294f..7ac482c19d7 100644 --- a/include/grpcpp/impl/codegen/service_type.h +++ b/include/grpcpp/impl/codegen/service_type.h @@ -26,10 +26,13 @@ #include #include +namespace grpc_impl { + +class Server; +} // namespace grpc_impl namespace grpc { class CompletionQueue; -class Server; class ServerInterface; class ServerCompletionQueue; class ServerContext; @@ -228,7 +231,7 @@ class Service { } private: - friend class Server; + friend class grpc_impl::Server; friend class ServerInterface; ServerInterface* server_; std::vector> methods_; diff --git a/include/grpcpp/impl/server_initializer.h b/include/grpcpp/impl/server_initializer.h index f949fabfe6f..bd18ee04927 100644 --- a/include/grpcpp/impl/server_initializer.h +++ b/include/grpcpp/impl/server_initializer.h @@ -24,9 +24,12 @@ #include -namespace grpc { +namespace grpc_impl { class Server; +} // namespace grpc_impl +namespace grpc { + class Service; class ServerInitializer { diff --git a/include/grpcpp/security/server_credentials.h b/include/grpcpp/security/server_credentials.h index bd00a0a1737..a519caf9913 100644 --- a/include/grpcpp/security/server_credentials.h +++ b/include/grpcpp/security/server_credentials.h @@ -28,8 +28,11 @@ struct grpc_server; -namespace grpc { +namespace grpc_impl { + class Server; +} // namespace grpc_impl +namespace grpc { /// Wrapper around \a grpc_server_credentials, a way to authenticate a server. class ServerCredentials { @@ -42,7 +45,7 @@ class ServerCredentials { const std::shared_ptr& processor) = 0; private: - friend class ::grpc::Server; + friend class ::grpc_impl::Server; /// Tries to bind \a server to the given \a addr (eg, localhost:1234, /// 192.168.1.1:31416, [::1]:27182, etc.) diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index f5c99f22df2..3de2aba0b59 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,330 +19,11 @@ #ifndef GRPCPP_SERVER_H #define GRPCPP_SERVER_H -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct grpc_server; +#include namespace grpc { -class AsyncGenericService; -class HealthCheckServiceInterface; -class ServerContext; -class ServerInitializer; - -/// Represents a gRPC server. -/// -/// Use a \a grpc::ServerBuilder to create, configure, and start -/// \a Server instances. -class Server : public ServerInterface, private GrpcLibraryCodegen { - public: - ~Server(); - - /// Block until the server shuts down. - /// - /// \warning The server must be either shutting down or some other thread must - /// call \a Shutdown for this function to ever return. - void Wait() override; - - /// Global callbacks are a set of hooks that are called when server - /// events occur. \a SetGlobalCallbacks method is used to register - /// the hooks with gRPC. Note that - /// the \a GlobalCallbacks instance will be shared among all - /// \a Server instances in an application and can be set exactly - /// once per application. - class GlobalCallbacks { - public: - virtual ~GlobalCallbacks() {} - /// Called before server is created. - virtual void UpdateArguments(ChannelArguments* args) {} - /// Called before application callback for each synchronous server request - virtual void PreSynchronousRequest(ServerContext* context) = 0; - /// Called after application callback for each synchronous server request - virtual void PostSynchronousRequest(ServerContext* context) = 0; - /// Called before server is started. - virtual void PreServerStart(Server* server) {} - /// Called after a server port is added. - virtual void AddPort(Server* server, const grpc::string& addr, - ServerCredentials* creds, int port) {} - }; - /// Set the global callback object. Can only be called once per application. - /// Does not take ownership of callbacks, and expects the pointed to object - /// to be alive until all server objects in the process have been destroyed. - /// The same \a GlobalCallbacks object will be used throughout the - /// application and is shared among all \a Server objects. - static void SetGlobalCallbacks(GlobalCallbacks* callbacks); - - /// Returns a \em raw pointer to the underlying \a grpc_server instance. - /// EXPERIMENTAL: for internal/test use only - grpc_server* c_server(); - - /// Returns the health check service. - HealthCheckServiceInterface* GetHealthCheckService() const { - return health_check_service_.get(); - } - - /// Establish a channel for in-process communication - std::shared_ptr InProcessChannel(const ChannelArguments& args); - - /// NOTE: class experimental_type is not part of the public API of this class. - /// TODO(yashykt): Integrate into public API when this is no longer - /// experimental. - class experimental_type { - public: - explicit experimental_type(Server* server) : server_(server) {} - - /// Establish a channel for in-process communication with client - /// interceptors - std::shared_ptr InProcessChannelWithInterceptors( - const ChannelArguments& args, - std::vector< - std::unique_ptr> - interceptor_creators); - - private: - Server* server_; - }; - - /// NOTE: The function experimental() is not stable public API. It is a view - /// to the experimental components of this class. It may be changed or removed - /// at any time. - experimental_type experimental() { return experimental_type(this); } - - protected: - /// Register a service. This call does not take ownership of the service. - /// The service must exist for the lifetime of the Server instance. - bool RegisterService(const grpc::string* host, Service* service) override; - - /// Try binding the server to the given \a addr endpoint - /// (port, and optionally including IP address to bind to). - /// - /// It can be invoked multiple times. Should be used before - /// starting the server. - /// - /// \param addr The address to try to bind to the server (eg, localhost:1234, - /// 192.168.1.1:31416, [::1]:27182, etc.). - /// \param creds The credentials associated with the server. - /// - /// \return bound port number on success, 0 on failure. - /// - /// \warning It is an error to call this method on an already started server. - int AddListeningPort(const grpc::string& addr, - ServerCredentials* creds) override; - - /// NOTE: This is *NOT* a public API. The server constructors are supposed to - /// be used by \a ServerBuilder class only. The constructor will be made - /// 'private' very soon. - /// - /// Server constructors. To be used by \a ServerBuilder only. - /// - /// \param max_message_size Maximum message length that the channel can - /// receive. - /// - /// \param args The channel args - /// - /// \param sync_server_cqs The completion queues to use if the server is a - /// synchronous server (or a hybrid server). The server polls for new RPCs on - /// these queues - /// - /// \param min_pollers The minimum number of polling threads per server - /// completion queue (in param sync_server_cqs) to use for listening to - /// incoming requests (used only in case of sync server) - /// - /// \param max_pollers The maximum number of polling threads per server - /// completion queue (in param sync_server_cqs) to use for listening to - /// incoming requests (used only in case of sync server) - /// - /// \param sync_cq_timeout_msec The timeout to use when calling AsyncNext() on - /// server completion queues passed via sync_server_cqs param. - Server(int max_message_size, ChannelArguments* args, - std::shared_ptr>> - sync_server_cqs, - int min_pollers, int max_pollers, int sync_cq_timeout_msec, - grpc_resource_quota* server_rq = nullptr, - std::vector< - std::unique_ptr> - interceptor_creators = std::vector>()); - - /// Start the server. - /// - /// \param cqs Completion queues for handling asynchronous services. The - /// caller is required to keep all completion queues live until the server is - /// destroyed. - /// \param num_cqs How many completion queues does \a cqs hold. - void Start(ServerCompletionQueue** cqs, size_t num_cqs) override; - - grpc_server* server() override { return server_; } - - private: - std::vector>* - interceptor_creators() override { - return &interceptor_creators_; - } - - friend class AsyncGenericService; - friend class ServerBuilder; - friend class ServerInitializer; - - class SyncRequest; - class CallbackRequestBase; - template - class CallbackRequest; - class UnimplementedAsyncRequest; - class UnimplementedAsyncResponse; - - /// SyncRequestThreadManager is an implementation of ThreadManager. This class - /// is responsible for polling for incoming RPCs and calling the RPC handlers. - /// This is only used in case of a Sync server (i.e a server exposing a sync - /// interface) - class SyncRequestThreadManager; - - /// Register a generic service. This call does not take ownership of the - /// service. The service must exist for the lifetime of the Server instance. - void RegisterAsyncGenericService(AsyncGenericService* service) override; - - /// NOTE: class experimental_registration_type is not part of the public API - /// of this class - /// TODO(vjpai): Move these contents to the public API of Server when - /// they are no longer experimental - class experimental_registration_type final - : public experimental_registration_interface { - public: - explicit experimental_registration_type(Server* server) : server_(server) {} - void RegisterCallbackGenericService( - experimental::CallbackGenericService* service) override { - server_->RegisterCallbackGenericService(service); - } - - private: - Server* server_; - }; - - /// TODO(vjpai): Mark this override when experimental type above is deleted - void RegisterCallbackGenericService( - experimental::CallbackGenericService* service); - - /// NOTE: The function experimental_registration() is not stable public API. - /// It is a view to the experimental components of this class. It may be - /// changed or removed at any time. - experimental_registration_interface* experimental_registration() override { - return &experimental_registration_; - } - - void PerformOpsOnCall(internal::CallOpSetInterface* ops, - internal::Call* call) override; - - void ShutdownInternal(gpr_timespec deadline) override; - - int max_receive_message_size() const override { - return max_receive_message_size_; - } - - CompletionQueue* CallbackCQ() override; - - ServerInitializer* initializer(); - - // A vector of interceptor factory objects. - // This should be destroyed after health_check_service_ and this requirement - // is satisfied by declaring interceptor_creators_ before - // health_check_service_. (C++ mandates that member objects be destroyed in - // the reverse order of initialization.) - std::vector> - interceptor_creators_; - - const int max_receive_message_size_; - - /// The following completion queues are ONLY used in case of Sync API - /// i.e. if the server has any services with sync methods. The server uses - /// these completion queues to poll for new RPCs - std::shared_ptr>> - sync_server_cqs_; - - /// List of \a ThreadManager instances (one for each cq in - /// the \a sync_server_cqs) - std::vector> sync_req_mgrs_; - - // Outstanding unmatched callback requests, indexed by method. - // NOTE: Using a gpr_atm rather than atomic_int because atomic_int isn't - // copyable or movable and thus will cause compilation errors. We - // actually only want to extend the vector before the threaded use - // starts, but this is still a limitation. - std::vector callback_unmatched_reqs_count_; - - // List of callback requests to start when server actually starts. - std::list callback_reqs_to_start_; - - // For registering experimental callback generic service; remove when that - // method longer experimental - experimental_registration_type experimental_registration_{this}; - - // Server status - std::mutex mu_; - bool started_; - bool shutdown_; - bool shutdown_notified_; // Was notify called on the shutdown_cv_ - - std::condition_variable shutdown_cv_; - - // It is ok (but not required) to nest callback_reqs_mu_ under mu_ . - // Incrementing callback_reqs_outstanding_ is ok without a lock but it must be - // decremented under the lock in case it is the last request and enables the - // server shutdown. The increment is performance-critical since it happens - // during periods of increasing load; the decrement happens only when memory - // is maxed out, during server shutdown, or (possibly in a future version) - // during decreasing load, so it is less performance-critical. - std::mutex callback_reqs_mu_; - std::condition_variable callback_reqs_done_cv_; - std::atomic_int callback_reqs_outstanding_{0}; - - std::shared_ptr global_callbacks_; - - std::vector services_; - bool has_async_generic_service_{false}; - bool has_callback_generic_service_{false}; - - // Pointer to the wrapped grpc_server. - grpc_server* server_; - - std::unique_ptr server_initializer_; - - std::unique_ptr health_check_service_; - bool health_check_service_disabled_; - - // When appropriate, use a default callback generic service to handle - // unimplemented methods - std::unique_ptr unimplemented_service_; - - // A special handler for resource exhausted in sync case - std::unique_ptr resource_exhausted_handler_; - - // Handler for callback generic service, if any - std::unique_ptr generic_handler_; - - // callback_cq_ references the callbackable completion queue associated - // with this server (if any). It is set on the first call to CallbackCQ(). - // It is _not owned_ by the server; ownership belongs with its internal - // shutdown callback tag (invoked when the CQ is fully shutdown). - // It is protected by mu_ - CompletionQueue* callback_cq_ = nullptr; -}; +typedef ::grpc_impl::Server Server; } // namespace grpc diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h index 498e5b7bb31..aaa8197e966 100644 --- a/include/grpcpp/server_builder.h +++ b/include/grpcpp/server_builder.h @@ -35,12 +35,15 @@ struct grpc_resource_quota; +namespace grpc_impl { + +class Server; +} // namespace grpc_impl namespace grpc { class AsyncGenericService; class ResourceQuota; class CompletionQueue; -class Server; class ServerCompletionQueue; class ServerCredentials; class Service; @@ -70,7 +73,7 @@ class ServerBuilder { /// traffic (via AddListeningPort) /// 3. [for async api only] completion queues have been added via /// AddCompletionQueue - virtual std::unique_ptr BuildAndStart(); + virtual std::unique_ptr BuildAndStart(); /// Register a service. This call does not take ownership of the service. /// The service must exist for the lifetime of the \a Server instance returned diff --git a/include/grpcpp/server_impl.h b/include/grpcpp/server_impl.h new file mode 100644 index 00000000000..d27723a01fe --- /dev/null +++ b/include/grpcpp/server_impl.h @@ -0,0 +1,353 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_SERVER_IMPL_H +#define GRPCPP_SERVER_IMPL_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct grpc_server; + +namespace grpc { + +class AsyncGenericService; +class HealthCheckServiceInterface; +class ServerContext; +class ServerInitializer; + +} // namespace grpc + +namespace grpc_impl { + +/// Represents a gRPC server. +/// +/// Use a \a grpc::ServerBuilder to create, configure, and start +/// \a Server instances. +class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen { + public: + ~Server(); + + /// Block until the server shuts down. + /// + /// \warning The server must be either shutting down or some other thread must + /// call \a Shutdown for this function to ever return. + void Wait() override; + + /// Global callbacks are a set of hooks that are called when server + /// events occur. \a SetGlobalCallbacks method is used to register + /// the hooks with gRPC. Note that + /// the \a GlobalCallbacks instance will be shared among all + /// \a Server instances in an application and can be set exactly + /// once per application. + class GlobalCallbacks { + public: + virtual ~GlobalCallbacks() {} + /// Called before server is created. + virtual void UpdateArguments(grpc::ChannelArguments* args) {} + /// Called before application callback for each synchronous server request + virtual void PreSynchronousRequest(grpc::ServerContext* context) = 0; + /// Called after application callback for each synchronous server request + virtual void PostSynchronousRequest(grpc::ServerContext* context) = 0; + /// Called before server is started. + virtual void PreServerStart(Server* server) {} + /// Called after a server port is added. + virtual void AddPort(Server* server, const grpc::string& addr, + grpc::ServerCredentials* creds, int port) {} + }; + /// Set the global callback object. Can only be called once per application. + /// Does not take ownership of callbacks, and expects the pointed to object + /// to be alive until all server objects in the process have been destroyed. + /// The same \a GlobalCallbacks object will be used throughout the + /// application and is shared among all \a Server objects. + static void SetGlobalCallbacks(GlobalCallbacks* callbacks); + + /// Returns a \em raw pointer to the underlying \a grpc_server instance. + /// EXPERIMENTAL: for internal/test use only + grpc_server* c_server(); + + /// Returns the health check service. + grpc::HealthCheckServiceInterface* GetHealthCheckService() const { + return health_check_service_.get(); + } + + /// Establish a channel for in-process communication + std::shared_ptr InProcessChannel(const grpc::ChannelArguments& args); + + /// NOTE: class experimental_type is not part of the public API of this class. + /// TODO(yashykt): Integrate into public API when this is no longer + /// experimental. + class experimental_type { + public: + explicit experimental_type(Server* server) : server_(server) {} + + /// Establish a channel for in-process communication with client + /// interceptors + std::shared_ptr InProcessChannelWithInterceptors( + const grpc::ChannelArguments& args, + std::vector< + std::unique_ptr> + interceptor_creators); + + private: + Server* server_; + }; + + /// NOTE: The function experimental() is not stable public API. It is a view + /// to the experimental components of this class. It may be changed or removed + /// at any time. + experimental_type experimental() { return experimental_type(this); } + + protected: + /// Register a service. This call does not take ownership of the service. + /// The service must exist for the lifetime of the Server instance. + bool RegisterService(const grpc::string* host, grpc::Service* service) override; + + /// Try binding the server to the given \a addr endpoint + /// (port, and optionally including IP address to bind to). + /// + /// It can be invoked multiple times. Should be used before + /// starting the server. + /// + /// \param addr The address to try to bind to the server (eg, localhost:1234, + /// 192.168.1.1:31416, [::1]:27182, etc.). + /// \param creds The credentials associated with the server. + /// + /// \return bound port number on success, 0 on failure. + /// + /// \warning It is an error to call this method on an already started server. + int AddListeningPort(const grpc::string& addr, + grpc::ServerCredentials* creds) override; + + /// NOTE: This is *NOT* a public API. The server constructors are supposed to + /// be used by \a ServerBuilder class only. The constructor will be made + /// 'private' very soon. + /// + /// Server constructors. To be used by \a ServerBuilder only. + /// + /// \param max_message_size Maximum message length that the channel can + /// receive. + /// + /// \param args The channel args + /// + /// \param sync_server_cqs The completion queues to use if the server is a + /// synchronous server (or a hybrid server). The server polls for new RPCs on + /// these queues + /// + /// \param min_pollers The minimum number of polling threads per server + /// completion queue (in param sync_server_cqs) to use for listening to + /// incoming requests (used only in case of sync server) + /// + /// \param max_pollers The maximum number of polling threads per server + /// completion queue (in param sync_server_cqs) to use for listening to + /// incoming requests (used only in case of sync server) + /// + /// \param sync_cq_timeout_msec The timeout to use when calling AsyncNext() on + /// server completion queues passed via sync_server_cqs param. + Server(int max_message_size, grpc::ChannelArguments* args, + std::shared_ptr>> + sync_server_cqs, + int min_pollers, int max_pollers, int sync_cq_timeout_msec, + grpc_resource_quota* server_rq = nullptr, + std::vector< + std::unique_ptr> + interceptor_creators = std::vector>()); + + /// Start the server. + /// + /// \param cqs Completion queues for handling asynchronous services. The + /// caller is required to keep all completion queues live until the server is + /// destroyed. + /// \param num_cqs How many completion queues does \a cqs hold. + void Start(grpc::ServerCompletionQueue** cqs, size_t num_cqs) override; + + grpc_server* server() override { return server_; } + + private: + std::vector>* + interceptor_creators() override { + return &interceptor_creators_; + } + + friend class grpc::AsyncGenericService; + friend class grpc::ServerBuilder; + friend class grpc::ServerInitializer; + + class SyncRequest; + class CallbackRequestBase; + template + class CallbackRequest; + class UnimplementedAsyncRequest; + class UnimplementedAsyncResponse; + + /// SyncRequestThreadManager is an implementation of ThreadManager. This class + /// is responsible for polling for incoming RPCs and calling the RPC handlers. + /// This is only used in case of a Sync server (i.e a server exposing a sync + /// interface) + class SyncRequestThreadManager; + + /// Register a generic service. This call does not take ownership of the + /// service. The service must exist for the lifetime of the Server instance. + void RegisterAsyncGenericService(grpc::AsyncGenericService* service) override; + + /// NOTE: class experimental_registration_type is not part of the public API + /// of this class + /// TODO(vjpai): Move these contents to the public API of Server when + /// they are no longer experimental + class experimental_registration_type final + : public experimental_registration_interface { + public: + explicit experimental_registration_type(Server* server) : server_(server) {} + void RegisterCallbackGenericService( + grpc::experimental::CallbackGenericService* service) override { + server_->RegisterCallbackGenericService(service); + } + + private: + Server* server_; + }; + + /// TODO(vjpai): Mark this override when experimental type above is deleted + void RegisterCallbackGenericService( + grpc::experimental::CallbackGenericService* service); + + /// NOTE: The function experimental_registration() is not stable public API. + /// It is a view to the experimental components of this class. It may be + /// changed or removed at any time. + experimental_registration_interface* experimental_registration() override { + return &experimental_registration_; + } + + void PerformOpsOnCall(grpc::internal::CallOpSetInterface* ops, + grpc::internal::Call* call) override; + + void ShutdownInternal(gpr_timespec deadline) override; + + int max_receive_message_size() const override { + return max_receive_message_size_; + } + + grpc::CompletionQueue* CallbackCQ() override; + + grpc::ServerInitializer* initializer(); + + // A vector of interceptor factory objects. + // This should be destroyed after health_check_service_ and this requirement + // is satisfied by declaring interceptor_creators_ before + // health_check_service_. (C++ mandates that member objects be destroyed in + // the reverse order of initialization.) + std::vector> + interceptor_creators_; + + const int max_receive_message_size_; + + /// The following completion queues are ONLY used in case of Sync API + /// i.e. if the server has any services with sync methods. The server uses + /// these completion queues to poll for new RPCs + std::shared_ptr>> + sync_server_cqs_; + + /// List of \a ThreadManager instances (one for each cq in + /// the \a sync_server_cqs) + std::vector> sync_req_mgrs_; + + // Outstanding unmatched callback requests, indexed by method. + // NOTE: Using a gpr_atm rather than atomic_int because atomic_int isn't + // copyable or movable and thus will cause compilation errors. We + // actually only want to extend the vector before the threaded use + // starts, but this is still a limitation. + std::vector callback_unmatched_reqs_count_; + + // List of callback requests to start when server actually starts. + std::list callback_reqs_to_start_; + + // For registering experimental callback generic service; remove when that + // method longer experimental + experimental_registration_type experimental_registration_{this}; + + // Server status + std::mutex mu_; + bool started_; + bool shutdown_; + bool shutdown_notified_; // Was notify called on the shutdown_cv_ + + std::condition_variable shutdown_cv_; + + // It is ok (but not required) to nest callback_reqs_mu_ under mu_ . + // Incrementing callback_reqs_outstanding_ is ok without a lock but it must be + // decremented under the lock in case it is the last request and enables the + // server shutdown. The increment is performance-critical since it happens + // during periods of increasing load; the decrement happens only when memory + // is maxed out, during server shutdown, or (possibly in a future version) + // during decreasing load, so it is less performance-critical. + std::mutex callback_reqs_mu_; + std::condition_variable callback_reqs_done_cv_; + std::atomic_int callback_reqs_outstanding_{0}; + + std::shared_ptr global_callbacks_; + + std::vector services_; + bool has_async_generic_service_{false}; + bool has_callback_generic_service_{false}; + + // Pointer to the wrapped grpc_server. + grpc_server* server_; + + std::unique_ptr server_initializer_; + + std::unique_ptr health_check_service_; + bool health_check_service_disabled_; + + // When appropriate, use a default callback generic service to handle + // unimplemented methods + std::unique_ptr unimplemented_service_; + + // A special handler for resource exhausted in sync case + std::unique_ptr resource_exhausted_handler_; + + // Handler for callback generic service, if any + std::unique_ptr generic_handler_; + + // callback_cq_ references the callbackable completion queue associated + // with this server (if any). It is set on the first call to CallbackCQ(). + // It is _not owned_ by the server; ownership belongs with its internal + // shutdown callback tag (invoked when the CQ is fully shutdown). + // It is protected by mu_ + grpc::CompletionQueue* callback_cq_ = nullptr; +}; + +} // namespace grpc_impl + +#endif // GRPCPP_SERVER_IMPL_H diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 26e84f1aed4..74d89ff18fc 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -106,1029 +106,6 @@ class UnimplementedAsyncRequestContext { } // namespace -/// Use private inheritance rather than composition only to establish order -/// of construction, since the public base class should be constructed after the -/// elements belonging to the private base class are constructed. This is not -/// possible using true composition. -class Server::UnimplementedAsyncRequest final - : private UnimplementedAsyncRequestContext, - public GenericAsyncRequest { - public: - UnimplementedAsyncRequest(Server* server, ServerCompletionQueue* cq) - : GenericAsyncRequest(server, &server_context_, &generic_stream_, cq, cq, - nullptr, false), - server_(server), - cq_(cq) {} - - bool FinalizeResult(void** tag, bool* status) override; - - ServerContext* context() { return &server_context_; } - GenericServerAsyncReaderWriter* stream() { return &generic_stream_; } - - private: - Server* const server_; - ServerCompletionQueue* const cq_; -}; - -/// UnimplementedAsyncResponse should not post user-visible completions to the -/// C++ completion queue, but is generated as a CQ event by the core -class Server::UnimplementedAsyncResponse final - : public internal::CallOpSet { - public: - UnimplementedAsyncResponse(UnimplementedAsyncRequest* request); - ~UnimplementedAsyncResponse() { delete request_; } - - bool FinalizeResult(void** tag, bool* status) override { - if (internal::CallOpSet< - internal::CallOpSendInitialMetadata, - internal::CallOpServerSendStatus>::FinalizeResult(tag, status)) { - delete this; - } else { - // The tag was swallowed due to interception. We will see it again. - } - return false; - } - - private: - UnimplementedAsyncRequest* const request_; -}; - -class Server::SyncRequest final : public internal::CompletionQueueTag { - public: - SyncRequest(internal::RpcServiceMethod* method, void* method_tag) - : method_(method), - method_tag_(method_tag), - in_flight_(false), - has_request_payload_( - method->method_type() == internal::RpcMethod::NORMAL_RPC || - method->method_type() == internal::RpcMethod::SERVER_STREAMING), - call_details_(nullptr), - cq_(nullptr) { - grpc_metadata_array_init(&request_metadata_); - } - - ~SyncRequest() { - if (call_details_) { - delete call_details_; - } - grpc_metadata_array_destroy(&request_metadata_); - } - - void SetupRequest() { cq_ = grpc_completion_queue_create_for_pluck(nullptr); } - - void TeardownRequest() { - grpc_completion_queue_destroy(cq_); - cq_ = nullptr; - } - - void Request(grpc_server* server, grpc_completion_queue* notify_cq) { - GPR_ASSERT(cq_ && !in_flight_); - in_flight_ = true; - if (method_tag_) { - if (grpc_server_request_registered_call( - server, method_tag_, &call_, &deadline_, &request_metadata_, - has_request_payload_ ? &request_payload_ : nullptr, cq_, - notify_cq, this) != GRPC_CALL_OK) { - TeardownRequest(); - return; - } - } else { - if (!call_details_) { - call_details_ = new grpc_call_details; - grpc_call_details_init(call_details_); - } - if (grpc_server_request_call(server, &call_, call_details_, - &request_metadata_, cq_, notify_cq, - this) != GRPC_CALL_OK) { - TeardownRequest(); - return; - } - } - } - - void PostShutdownCleanup() { - if (call_) { - grpc_call_unref(call_); - call_ = nullptr; - } - if (cq_) { - grpc_completion_queue_destroy(cq_); - cq_ = nullptr; - } - } - - bool FinalizeResult(void** tag, bool* status) override { - if (!*status) { - grpc_completion_queue_destroy(cq_); - cq_ = nullptr; - } - if (call_details_) { - deadline_ = call_details_->deadline; - grpc_call_details_destroy(call_details_); - grpc_call_details_init(call_details_); - } - return true; - } - - // The CallData class represents a call that is "active" as opposed - // to just being requested. It wraps and takes ownership of the cq from - // the call request - class CallData final { - public: - explicit CallData(Server* server, SyncRequest* mrd) - : cq_(mrd->cq_), - ctx_(mrd->deadline_, &mrd->request_metadata_), - has_request_payload_(mrd->has_request_payload_), - request_payload_(has_request_payload_ ? mrd->request_payload_ - : nullptr), - request_(nullptr), - method_(mrd->method_), - call_( - mrd->call_, server, &cq_, server->max_receive_message_size(), - ctx_.set_server_rpc_info(method_->name(), method_->method_type(), - server->interceptor_creators_)), - server_(server), - global_callbacks_(nullptr), - resources_(false) { - ctx_.set_call(mrd->call_); - ctx_.cq_ = &cq_; - GPR_ASSERT(mrd->in_flight_); - mrd->in_flight_ = false; - mrd->request_metadata_.count = 0; - } - - ~CallData() { - if (has_request_payload_ && request_payload_) { - grpc_byte_buffer_destroy(request_payload_); - } - } - - void Run(const std::shared_ptr& global_callbacks, - bool resources) { - global_callbacks_ = global_callbacks; - resources_ = resources; - - interceptor_methods_.SetCall(&call_); - interceptor_methods_.SetReverse(); - // Set interception point for RECV INITIAL METADATA - interceptor_methods_.AddInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA); - interceptor_methods_.SetRecvInitialMetadata(&ctx_.client_metadata_); - - if (has_request_payload_) { - // Set interception point for RECV MESSAGE - auto* handler = resources_ ? method_->handler() - : server_->resource_exhausted_handler_.get(); - request_ = handler->Deserialize(call_.call(), request_payload_, - &request_status_); - - request_payload_ = nullptr; - interceptor_methods_.AddInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_MESSAGE); - interceptor_methods_.SetRecvMessage(request_, nullptr); - } - - if (interceptor_methods_.RunInterceptors( - [this]() { ContinueRunAfterInterception(); })) { - ContinueRunAfterInterception(); - } else { - // There were interceptors to be run, so ContinueRunAfterInterception - // will be run when interceptors are done. - } - } - - void ContinueRunAfterInterception() { - { - ctx_.BeginCompletionOp(&call_, nullptr, nullptr); - global_callbacks_->PreSynchronousRequest(&ctx_); - auto* handler = resources_ ? method_->handler() - : server_->resource_exhausted_handler_.get(); - handler->RunHandler(internal::MethodHandler::HandlerParameter( - &call_, &ctx_, request_, request_status_, nullptr)); - request_ = nullptr; - global_callbacks_->PostSynchronousRequest(&ctx_); - - cq_.Shutdown(); - - internal::CompletionQueueTag* op_tag = ctx_.GetCompletionOpTag(); - cq_.TryPluck(op_tag, gpr_inf_future(GPR_CLOCK_REALTIME)); - - /* Ensure the cq_ is shutdown */ - DummyTag ignored_tag; - GPR_ASSERT(cq_.Pluck(&ignored_tag) == false); - } - delete this; - } - - private: - CompletionQueue cq_; - ServerContext ctx_; - const bool has_request_payload_; - grpc_byte_buffer* request_payload_; - void* request_; - Status request_status_; - internal::RpcServiceMethod* const method_; - internal::Call call_; - Server* server_; - std::shared_ptr global_callbacks_; - bool resources_; - internal::InterceptorBatchMethodsImpl interceptor_methods_; - }; - - private: - internal::RpcServiceMethod* const method_; - void* const method_tag_; - bool in_flight_; - const bool has_request_payload_; - grpc_call* call_; - grpc_call_details* call_details_; - gpr_timespec deadline_; - grpc_metadata_array request_metadata_; - grpc_byte_buffer* request_payload_; - grpc_completion_queue* cq_; -}; - -class Server::CallbackRequestBase : public internal::CompletionQueueTag { - public: - virtual ~CallbackRequestBase() {} - virtual bool Request() = 0; -}; - -template -class Server::CallbackRequest final : public Server::CallbackRequestBase { - public: - static_assert(std::is_base_of::value, - "ServerContextType must be derived from ServerContext"); - - // The constructor needs to know the server for this callback request and its - // index in the server's request count array to allow for proper dynamic - // requesting of incoming RPCs. For codegen services, the values of method and - // method_tag represent the defined characteristics of the method being - // requested. For generic services, method and method_tag are nullptr since - // these services don't have pre-defined methods or method registration tags. - CallbackRequest(Server* server, size_t method_idx, - internal::RpcServiceMethod* method, void* method_tag) - : server_(server), - method_index_(method_idx), - method_(method), - method_tag_(method_tag), - has_request_payload_( - method_ != nullptr && - (method->method_type() == internal::RpcMethod::NORMAL_RPC || - method->method_type() == internal::RpcMethod::SERVER_STREAMING)), - cq_(server->CallbackCQ()), - tag_(this) { - server_->callback_reqs_outstanding_++; - Setup(); - } - - ~CallbackRequest() { - Clear(); - - // The counter of outstanding requests must be decremented - // under a lock in case it causes the server shutdown. - std::lock_guard l(server_->callback_reqs_mu_); - if (--server_->callback_reqs_outstanding_ == 0) { - server_->callback_reqs_done_cv_.notify_one(); - } - } - - bool Request() override { - if (method_tag_) { - if (GRPC_CALL_OK != - grpc_server_request_registered_call( - server_->c_server(), method_tag_, &call_, &deadline_, - &request_metadata_, - has_request_payload_ ? &request_payload_ : nullptr, cq_->cq(), - cq_->cq(), static_cast(&tag_))) { - return false; - } - } else { - if (!call_details_) { - call_details_ = new grpc_call_details; - grpc_call_details_init(call_details_); - } - if (grpc_server_request_call(server_->c_server(), &call_, call_details_, - &request_metadata_, cq_->cq(), cq_->cq(), - static_cast(&tag_)) != GRPC_CALL_OK) { - return false; - } - } - return true; - } - - // Needs specialization to account for different processing of metadata - // in generic API - bool FinalizeResult(void** tag, bool* status) override; - - private: - // method_name needs to be specialized between named method and generic - const char* method_name() const; - - class CallbackCallTag : public grpc_experimental_completion_queue_functor { - public: - CallbackCallTag(Server::CallbackRequest* req) - : req_(req) { - functor_run = &CallbackCallTag::StaticRun; - } - - // force_run can not be performed on a tag if operations using this tag - // have been sent to PerformOpsOnCall. It is intended for error conditions - // that are detected before the operations are internally processed. - void force_run(bool ok) { Run(ok); } - - private: - Server::CallbackRequest* req_; - internal::Call* call_; - - static void StaticRun(grpc_experimental_completion_queue_functor* cb, - int ok) { - static_cast(cb)->Run(static_cast(ok)); - } - void Run(bool ok) { - void* ignored = req_; - bool new_ok = ok; - GPR_ASSERT(!req_->FinalizeResult(&ignored, &new_ok)); - GPR_ASSERT(ignored == req_); - - int count = - static_cast(gpr_atm_no_barrier_fetch_add( - &req_->server_ - ->callback_unmatched_reqs_count_[req_->method_index_], - -1)) - - 1; - if (!ok) { - // The call has been shutdown. - // Delete its contents to free up the request. - delete req_; - return; - } - - // If this was the last request in the list or it is below the soft - // minimum and there are spare requests available, set up a new one. - if (count == 0 || (count < SOFT_MINIMUM_SPARE_CALLBACK_REQS_PER_METHOD && - req_->server_->callback_reqs_outstanding_ < - SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING)) { - auto* new_req = new CallbackRequest( - req_->server_, req_->method_index_, req_->method_, - req_->method_tag_); - if (!new_req->Request()) { - // The server must have just decided to shutdown. - gpr_atm_no_barrier_fetch_add( - &new_req->server_ - ->callback_unmatched_reqs_count_[new_req->method_index_], - -1); - delete new_req; - } - } - - // Bind the call, deadline, and metadata from what we got - req_->ctx_.set_call(req_->call_); - req_->ctx_.cq_ = req_->cq_; - req_->ctx_.BindDeadlineAndMetadata(req_->deadline_, - &req_->request_metadata_); - req_->request_metadata_.count = 0; - - // Create a C++ Call to control the underlying core call - call_ = new (grpc_call_arena_alloc(req_->call_, sizeof(internal::Call))) - internal::Call(req_->call_, req_->server_, req_->cq_, - req_->server_->max_receive_message_size(), - req_->ctx_.set_server_rpc_info( - req_->method_name(), - (req_->method_ != nullptr) - ? req_->method_->method_type() - : internal::RpcMethod::BIDI_STREAMING, - req_->server_->interceptor_creators_)); - - req_->interceptor_methods_.SetCall(call_); - req_->interceptor_methods_.SetReverse(); - // Set interception point for RECV INITIAL METADATA - req_->interceptor_methods_.AddInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA); - req_->interceptor_methods_.SetRecvInitialMetadata( - &req_->ctx_.client_metadata_); - - if (req_->has_request_payload_) { - // Set interception point for RECV MESSAGE - req_->request_ = req_->method_->handler()->Deserialize( - req_->call_, req_->request_payload_, &req_->request_status_); - req_->request_payload_ = nullptr; - req_->interceptor_methods_.AddInterceptionHookPoint( - experimental::InterceptionHookPoints::POST_RECV_MESSAGE); - req_->interceptor_methods_.SetRecvMessage(req_->request_, nullptr); - } - - if (req_->interceptor_methods_.RunInterceptors( - [this] { ContinueRunAfterInterception(); })) { - ContinueRunAfterInterception(); - } else { - // There were interceptors to be run, so ContinueRunAfterInterception - // will be run when interceptors are done. - } - } - void ContinueRunAfterInterception() { - auto* handler = (req_->method_ != nullptr) - ? req_->method_->handler() - : req_->server_->generic_handler_.get(); - handler->RunHandler(internal::MethodHandler::HandlerParameter( - call_, &req_->ctx_, req_->request_, req_->request_status_, [this] { - // Recycle this request if there aren't too many outstanding. - // Note that we don't have to worry about a case where there - // are no requests waiting to match for this method since that - // is already taken care of when binding a request to a call. - // TODO(vjpai): Also don't recycle this request if the dynamic - // load no longer justifies it. Consider measuring - // dynamic load and setting a target accordingly. - if (req_->server_->callback_reqs_outstanding_ < - SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING) { - req_->Clear(); - req_->Setup(); - } else { - // We can free up this request because there are too many - delete req_; - return; - } - if (!req_->Request()) { - // The server must have just decided to shutdown. - delete req_; - } - })); - } - }; - - void Clear() { - if (call_details_) { - delete call_details_; - call_details_ = nullptr; - } - grpc_metadata_array_destroy(&request_metadata_); - if (has_request_payload_ && request_payload_) { - grpc_byte_buffer_destroy(request_payload_); - } - ctx_.Clear(); - interceptor_methods_.ClearState(); - } - - void Setup() { - gpr_atm_no_barrier_fetch_add( - &server_->callback_unmatched_reqs_count_[method_index_], 1); - grpc_metadata_array_init(&request_metadata_); - ctx_.Setup(gpr_inf_future(GPR_CLOCK_REALTIME)); - request_payload_ = nullptr; - request_ = nullptr; - request_status_ = Status(); - } - - Server* const server_; - const size_t method_index_; - internal::RpcServiceMethod* const method_; - void* const method_tag_; - const bool has_request_payload_; - grpc_byte_buffer* request_payload_; - void* request_; - Status request_status_; - grpc_call_details* call_details_ = nullptr; - grpc_call* call_; - gpr_timespec deadline_; - grpc_metadata_array request_metadata_; - CompletionQueue* cq_; - CallbackCallTag tag_; - ServerContextType ctx_; - internal::InterceptorBatchMethodsImpl interceptor_methods_; -}; - -template <> -bool Server::CallbackRequest::FinalizeResult(void** tag, - bool* status) { - return false; -} - -template <> -bool Server::CallbackRequest::FinalizeResult( - void** tag, bool* status) { - if (*status) { - // TODO(yangg) remove the copy here - ctx_.method_ = StringFromCopiedSlice(call_details_->method); - ctx_.host_ = StringFromCopiedSlice(call_details_->host); - } - grpc_slice_unref(call_details_->method); - grpc_slice_unref(call_details_->host); - return false; -} - -template <> -const char* Server::CallbackRequest::method_name() const { - return method_->name(); -} - -template <> -const char* Server::CallbackRequest::method_name() const { - return ctx_.method().c_str(); -} - -// Implementation of ThreadManager. Each instance of SyncRequestThreadManager -// manages a pool of threads that poll for incoming Sync RPCs and call the -// appropriate RPC handlers -class Server::SyncRequestThreadManager : public ThreadManager { - public: - SyncRequestThreadManager(Server* server, CompletionQueue* server_cq, - std::shared_ptr global_callbacks, - grpc_resource_quota* rq, int min_pollers, - int max_pollers, int cq_timeout_msec) - : ThreadManager("SyncServer", rq, min_pollers, max_pollers), - server_(server), - server_cq_(server_cq), - cq_timeout_msec_(cq_timeout_msec), - global_callbacks_(std::move(global_callbacks)) {} - - WorkStatus PollForWork(void** tag, bool* ok) override { - *tag = nullptr; - // TODO(ctiller): workaround for GPR_TIMESPAN based deadlines not working - // right now - gpr_timespec deadline = - gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_millis(cq_timeout_msec_, GPR_TIMESPAN)); - - switch (server_cq_->AsyncNext(tag, ok, deadline)) { - case CompletionQueue::TIMEOUT: - return TIMEOUT; - case CompletionQueue::SHUTDOWN: - return SHUTDOWN; - case CompletionQueue::GOT_EVENT: - return WORK_FOUND; - } - - GPR_UNREACHABLE_CODE(return TIMEOUT); - } - - void DoWork(void* tag, bool ok, bool resources) override { - SyncRequest* sync_req = static_cast(tag); - - if (!sync_req) { - // No tag. Nothing to work on. This is an unlikley scenario and possibly a - // bug in RPC Manager implementation. - gpr_log(GPR_ERROR, "Sync server. DoWork() was called with NULL tag"); - return; - } - - if (ok) { - // Calldata takes ownership of the completion queue and interceptors - // inside sync_req - auto* cd = new SyncRequest::CallData(server_, sync_req); - // Prepare for the next request - if (!IsShutdown()) { - sync_req->SetupRequest(); // Create new completion queue for sync_req - sync_req->Request(server_->c_server(), server_cq_->cq()); - } - - GPR_TIMER_SCOPE("cd.Run()", 0); - cd->Run(global_callbacks_, resources); - } - // TODO (sreek) If ok is false here (which it isn't in case of - // grpc_request_registered_call), we should still re-queue the request - // object - } - - void AddSyncMethod(internal::RpcServiceMethod* method, void* tag) { - sync_requests_.emplace_back(new SyncRequest(method, tag)); - } - - void AddUnknownSyncMethod() { - if (!sync_requests_.empty()) { - unknown_method_.reset(new internal::RpcServiceMethod( - "unknown", internal::RpcMethod::BIDI_STREAMING, - new internal::UnknownMethodHandler)); - sync_requests_.emplace_back( - new SyncRequest(unknown_method_.get(), nullptr)); - } - } - - void Shutdown() override { - ThreadManager::Shutdown(); - server_cq_->Shutdown(); - } - - void Wait() override { - ThreadManager::Wait(); - // Drain any pending items from the queue - void* tag; - bool ok; - while (server_cq_->Next(&tag, &ok)) { - if (ok) { - // If a request was pulled off the queue, it means that the thread - // handling the request added it to the completion queue after shutdown - // was called - because the thread had already started and checked the - // shutdown flag before shutdown was called. In this case, we simply - // clean it up here, *after* calling wait on all the worker threads, at - // which point we are certain no in-flight requests will add more to the - // queue. This fixes an intermittent memory leak on shutdown. - SyncRequest* sync_req = static_cast(tag); - sync_req->PostShutdownCleanup(); - } - } - } - - void Start() { - if (!sync_requests_.empty()) { - for (auto m = sync_requests_.begin(); m != sync_requests_.end(); m++) { - (*m)->SetupRequest(); - (*m)->Request(server_->c_server(), server_cq_->cq()); - } - - Initialize(); // ThreadManager's Initialize() - } - } - - private: - Server* server_; - CompletionQueue* server_cq_; - int cq_timeout_msec_; - std::vector> sync_requests_; - std::unique_ptr unknown_method_; - std::shared_ptr global_callbacks_; -}; - -static internal::GrpcLibraryInitializer g_gli_initializer; -Server::Server( - int max_receive_message_size, ChannelArguments* args, - std::shared_ptr>> - sync_server_cqs, - int min_pollers, int max_pollers, int sync_cq_timeout_msec, - grpc_resource_quota* server_rq, - std::vector< - std::unique_ptr> - interceptor_creators) - : interceptor_creators_(std::move(interceptor_creators)), - max_receive_message_size_(max_receive_message_size), - sync_server_cqs_(std::move(sync_server_cqs)), - started_(false), - shutdown_(false), - shutdown_notified_(false), - server_(nullptr), - server_initializer_(new ServerInitializer(this)), - health_check_service_disabled_(false) { - g_gli_initializer.summon(); - gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks); - global_callbacks_ = g_callbacks; - global_callbacks_->UpdateArguments(args); - - if (sync_server_cqs_ != nullptr) { - bool default_rq_created = false; - if (server_rq == nullptr) { - server_rq = grpc_resource_quota_create("SyncServer-default-rq"); - grpc_resource_quota_set_max_threads(server_rq, - DEFAULT_MAX_SYNC_SERVER_THREADS); - default_rq_created = true; - } - - for (const auto& it : *sync_server_cqs_) { - sync_req_mgrs_.emplace_back(new SyncRequestThreadManager( - this, it.get(), global_callbacks_, server_rq, min_pollers, - max_pollers, sync_cq_timeout_msec)); - } - - if (default_rq_created) { - grpc_resource_quota_unref(server_rq); - } - } - - grpc_channel_args channel_args; - args->SetChannelArgs(&channel_args); - - for (size_t i = 0; i < channel_args.num_args; i++) { - if (0 == - strcmp(channel_args.args[i].key, kHealthCheckServiceInterfaceArg)) { - if (channel_args.args[i].value.pointer.p == nullptr) { - health_check_service_disabled_ = true; - } else { - health_check_service_.reset(static_cast( - channel_args.args[i].value.pointer.p)); - } - break; - } - } - - server_ = grpc_server_create(&channel_args, nullptr); -} - -Server::~Server() { - { - std::unique_lock lock(mu_); - if (callback_cq_ != nullptr) { - callback_cq_->Shutdown(); - } - if (started_ && !shutdown_) { - lock.unlock(); - Shutdown(); - } else if (!started_) { - // Shutdown the completion queues - for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { - (*it)->Shutdown(); - } - } - } - - grpc_server_destroy(server_); - for (auto& per_method_count : callback_unmatched_reqs_count_) { - // There should be no more unmatched callbacks for any method - // as each request is failed by Shutdown. Check that this actually - // happened - GPR_ASSERT(static_cast(gpr_atm_no_barrier_load(&per_method_count)) == - 0); - } -} - -void Server::SetGlobalCallbacks(GlobalCallbacks* callbacks) { - GPR_ASSERT(!g_callbacks); - GPR_ASSERT(callbacks); - g_callbacks.reset(callbacks); -} - -grpc_server* Server::c_server() { return server_; } - -std::shared_ptr Server::InProcessChannel( - const ChannelArguments& args) { - grpc_channel_args channel_args = args.c_channel_args(); - return CreateChannelInternal( - "inproc", grpc_inproc_channel_create(server_, &channel_args, nullptr), - std::vector< - std::unique_ptr>()); -} - -std::shared_ptr -Server::experimental_type::InProcessChannelWithInterceptors( - const ChannelArguments& args, - std::vector< - std::unique_ptr> - interceptor_creators) { - grpc_channel_args channel_args = args.c_channel_args(); - return CreateChannelInternal( - "inproc", - grpc_inproc_channel_create(server_->server_, &channel_args, nullptr), - std::move(interceptor_creators)); -} - -static grpc_server_register_method_payload_handling PayloadHandlingForMethod( - internal::RpcServiceMethod* method) { - switch (method->method_type()) { - case internal::RpcMethod::NORMAL_RPC: - case internal::RpcMethod::SERVER_STREAMING: - return GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER; - case internal::RpcMethod::CLIENT_STREAMING: - case internal::RpcMethod::BIDI_STREAMING: - return GRPC_SRM_PAYLOAD_NONE; - } - GPR_UNREACHABLE_CODE(return GRPC_SRM_PAYLOAD_NONE;); -} - -bool Server::RegisterService(const grpc::string* host, Service* service) { - bool has_async_methods = service->has_async_methods(); - if (has_async_methods) { - GPR_ASSERT(service->server_ == nullptr && - "Can only register an asynchronous service against one server."); - service->server_ = this; - } - - const char* method_name = nullptr; - - for (auto it = service->methods_.begin(); it != service->methods_.end(); - ++it) { - if (it->get() == nullptr) { // Handled by generic service if any. - continue; - } - - internal::RpcServiceMethod* method = it->get(); - void* method_registration_tag = grpc_server_register_method( - server_, method->name(), host ? host->c_str() : nullptr, - PayloadHandlingForMethod(method), 0); - if (method_registration_tag == nullptr) { - gpr_log(GPR_DEBUG, "Attempt to register %s multiple times", - method->name()); - return false; - } - - if (method->handler() == nullptr) { // Async method without handler - method->set_server_tag(method_registration_tag); - } else if (method->api_type() == - internal::RpcServiceMethod::ApiType::SYNC) { - for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { - (*it)->AddSyncMethod(method, method_registration_tag); - } - } else { - // a callback method. Register at least some callback requests - callback_unmatched_reqs_count_.push_back(0); - auto method_index = callback_unmatched_reqs_count_.size() - 1; - // TODO(vjpai): Register these dynamically based on need - for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) { - callback_reqs_to_start_.push_back(new CallbackRequest( - this, method_index, method, method_registration_tag)); - } - // Enqueue it so that it will be Request'ed later after all request - // matchers are created at core server startup - } - - method_name = method->name(); - } - - // Parse service name. - if (method_name != nullptr) { - std::stringstream ss(method_name); - grpc::string service_name; - if (std::getline(ss, service_name, '/') && - std::getline(ss, service_name, '/')) { - services_.push_back(service_name); - } - } - return true; -} - -void Server::RegisterAsyncGenericService(AsyncGenericService* service) { - GPR_ASSERT(service->server_ == nullptr && - "Can only register an async generic service against one server."); - service->server_ = this; - has_async_generic_service_ = true; -} - -void Server::RegisterCallbackGenericService( - experimental::CallbackGenericService* service) { - GPR_ASSERT( - service->server_ == nullptr && - "Can only register a callback generic service against one server."); - service->server_ = this; - has_callback_generic_service_ = true; - generic_handler_.reset(service->Handler()); - - callback_unmatched_reqs_count_.push_back(0); - auto method_index = callback_unmatched_reqs_count_.size() - 1; - // TODO(vjpai): Register these dynamically based on need - for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) { - callback_reqs_to_start_.push_back(new CallbackRequest( - this, method_index, nullptr, nullptr)); - } -} - -int Server::AddListeningPort(const grpc::string& addr, - ServerCredentials* creds) { - GPR_ASSERT(!started_); - int port = creds->AddPortToServer(addr, server_); - global_callbacks_->AddPort(this, addr, creds, port); - return port; -} - -void Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) { - GPR_ASSERT(!started_); - global_callbacks_->PreServerStart(this); - started_ = true; - - // Only create default health check service when user did not provide an - // explicit one. - ServerCompletionQueue* health_check_cq = nullptr; - DefaultHealthCheckService::HealthCheckServiceImpl* - default_health_check_service_impl = nullptr; - if (health_check_service_ == nullptr && !health_check_service_disabled_ && - DefaultHealthCheckServiceEnabled()) { - auto* default_hc_service = new DefaultHealthCheckService; - health_check_service_.reset(default_hc_service); - // We create a non-polling CQ to avoid impacting application - // performance. This ensures that we don't introduce thread hops - // for application requests that wind up on this CQ, which is polled - // in its own thread. - health_check_cq = - new ServerCompletionQueue(GRPC_CQ_NEXT, GRPC_CQ_NON_POLLING, nullptr); - grpc_server_register_completion_queue(server_, health_check_cq->cq(), - nullptr); - default_health_check_service_impl = - default_hc_service->GetHealthCheckService( - std::unique_ptr(health_check_cq)); - RegisterService(nullptr, default_health_check_service_impl); - } - - // If this server uses callback methods, then create a callback generic - // service to handle any unimplemented methods using the default reactor - // creator - if (!callback_reqs_to_start_.empty() && !has_callback_generic_service_) { - unimplemented_service_.reset(new experimental::CallbackGenericService); - RegisterCallbackGenericService(unimplemented_service_.get()); - } - - grpc_server_start(server_); - - if (!has_async_generic_service_ && !has_callback_generic_service_) { - for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { - (*it)->AddUnknownSyncMethod(); - } - - for (size_t i = 0; i < num_cqs; i++) { - if (cqs[i]->IsFrequentlyPolled()) { - new UnimplementedAsyncRequest(this, cqs[i]); - } - } - if (health_check_cq != nullptr) { - new UnimplementedAsyncRequest(this, health_check_cq); - } - } - - // If this server has any support for synchronous methods (has any sync - // server CQs), make sure that we have a ResourceExhausted handler - // to deal with the case of thread exhaustion - if (sync_server_cqs_ != nullptr && !sync_server_cqs_->empty()) { - resource_exhausted_handler_.reset(new internal::ResourceExhaustedHandler); - } - - for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { - (*it)->Start(); - } - - for (auto* cbreq : callback_reqs_to_start_) { - GPR_ASSERT(cbreq->Request()); - } - callback_reqs_to_start_.clear(); - - if (default_health_check_service_impl != nullptr) { - default_health_check_service_impl->StartServingThread(); - } -} - -void Server::ShutdownInternal(gpr_timespec deadline) { - std::unique_lock lock(mu_); - if (shutdown_) { - return; - } - - shutdown_ = true; - - /// The completion queue to use for server shutdown completion notification - CompletionQueue shutdown_cq; - ShutdownTag shutdown_tag; // Dummy shutdown tag - grpc_server_shutdown_and_notify(server_, shutdown_cq.cq(), &shutdown_tag); - - shutdown_cq.Shutdown(); - - void* tag; - bool ok; - CompletionQueue::NextStatus status = - shutdown_cq.AsyncNext(&tag, &ok, deadline); - - // If this timed out, it means we are done with the grace period for a clean - // shutdown. We should force a shutdown now by cancelling all inflight calls - if (status == CompletionQueue::NextStatus::TIMEOUT) { - grpc_server_cancel_all_calls(server_); - } - // Else in case of SHUTDOWN or GOT_EVENT, it means that the server has - // successfully shutdown - - // Shutdown all ThreadManagers. This will try to gracefully stop all the - // threads in the ThreadManagers (once they process any inflight requests) - for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { - (*it)->Shutdown(); // ThreadManager's Shutdown() - } - - // Wait for threads in all ThreadManagers to terminate - for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { - (*it)->Wait(); - } - - // Wait for all outstanding callback requests to complete - // (whether waiting for a match or already active). - // We know that no new requests will be created after this point - // because they are only created at server startup time or when - // we have a successful match on a request. During the shutdown phase, - // requests that have not yet matched will be failed rather than - // allowed to succeed, which will cause the server to delete the - // request and decrement the count. Possibly a request will match before - // the shutdown but then find that shutdown has already started by the - // time it tries to register a new request. In that case, the registration - // will report a failure, indicating a shutdown and again we won't end - // up incrementing the counter. - { - std::unique_lock cblock(callback_reqs_mu_); - callback_reqs_done_cv_.wait( - cblock, [this] { return callback_reqs_outstanding_ == 0; }); - } - - // Drain the shutdown queue (if the previous call to AsyncNext() timed out - // and we didn't remove the tag from the queue yet) - while (shutdown_cq.Next(&tag, &ok)) { - // Nothing to be done here. Just ignore ok and tag values - } - - shutdown_notified_ = true; - shutdown_cv_.notify_all(); -} - -void Server::Wait() { - std::unique_lock lock(mu_); - while (started_ && !shutdown_notified_) { - shutdown_cv_.wait(lock); - } -} - -void Server::PerformOpsOnCall(internal::CallOpSetInterface* ops, - internal::Call* call) { - ops->FillOps(call); -} - ServerInterface::BaseAsyncRequest::BaseAsyncRequest( ServerInterface* server, ServerContext* context, internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, @@ -1272,32 +249,6 @@ bool ServerInterface::GenericAsyncRequest::FinalizeResult(void** tag, return BaseAsyncRequest::FinalizeResult(tag, status); } -bool Server::UnimplementedAsyncRequest::FinalizeResult(void** tag, - bool* status) { - if (GenericAsyncRequest::FinalizeResult(tag, status)) { - // We either had no interceptors run or we are done intercepting - if (*status) { - new UnimplementedAsyncRequest(server_, cq_); - new UnimplementedAsyncResponse(this); - } else { - delete this; - } - } else { - // The tag was swallowed due to interception. We will see it again. - } - return false; -} - -Server::UnimplementedAsyncResponse::UnimplementedAsyncResponse( - UnimplementedAsyncRequest* request) - : request_(request) { - Status status(StatusCode::UNIMPLEMENTED, ""); - internal::UnknownMethodHandler::FillOps(request_->context(), this); - request_->stream()->call_.PerformOps(this); -} - -ServerInitializer* Server::initializer() { return server_initializer_.get(); } - namespace { class ShutdownCallback : public grpc_experimental_completion_queue_functor { public: @@ -1319,13 +270,1066 @@ class ShutdownCallback : public grpc_experimental_completion_queue_functor { }; } // namespace -CompletionQueue* Server::CallbackCQ() { +} // namespace grpc + +namespace grpc_impl { + +/// Use private inheritance rather than composition only to establish order +/// of construction, since the public base class should be constructed after the +/// elements belonging to the private base class are constructed. This is not +/// possible using true composition. +class Server::UnimplementedAsyncRequest final + : private grpc::UnimplementedAsyncRequestContext, + public GenericAsyncRequest { + public: + UnimplementedAsyncRequest(Server* server, grpc::ServerCompletionQueue* cq) + : GenericAsyncRequest(server, &server_context_, &generic_stream_, cq, cq, + nullptr, false), + server_(server), + cq_(cq) {} + + bool FinalizeResult(void** tag, bool* status) override; + + grpc::ServerContext* context() { return &server_context_; } + grpc::GenericServerAsyncReaderWriter* stream() { return &generic_stream_; } + + private: + Server* const server_; + grpc::ServerCompletionQueue* const cq_; +}; + +/// UnimplementedAsyncResponse should not post user-visible completions to the +/// C++ completion queue, but is generated as a CQ event by the core +class Server::UnimplementedAsyncResponse final + : public grpc::internal::CallOpSet { + public: + UnimplementedAsyncResponse(UnimplementedAsyncRequest* request); + ~UnimplementedAsyncResponse() { delete request_; } + + bool FinalizeResult(void** tag, bool* status) override { + if (grpc::internal::CallOpSet< + grpc::internal::CallOpSendInitialMetadata, + grpc::internal::CallOpServerSendStatus>::FinalizeResult(tag, status)) { + delete this; + } else { + // The tag was swallowed due to interception. We will see it again. + } + return false; + } + + private: + UnimplementedAsyncRequest* const request_; +}; + +class Server::SyncRequest final : public grpc::internal::CompletionQueueTag { + public: + SyncRequest(grpc::internal::RpcServiceMethod* method, void* method_tag) + : method_(method), + method_tag_(method_tag), + in_flight_(false), + has_request_payload_( + method->method_type() == grpc::internal::RpcMethod::NORMAL_RPC || + method->method_type() == grpc::internal::RpcMethod::SERVER_STREAMING), + call_details_(nullptr), + cq_(nullptr) { + grpc_metadata_array_init(&request_metadata_); + } + + ~SyncRequest() { + if (call_details_) { + delete call_details_; + } + grpc_metadata_array_destroy(&request_metadata_); + } + + void SetupRequest() { cq_ = grpc_completion_queue_create_for_pluck(nullptr); } + + void TeardownRequest() { + grpc_completion_queue_destroy(cq_); + cq_ = nullptr; + } + + void Request(grpc_server* server, grpc_completion_queue* notify_cq) { + GPR_ASSERT(cq_ && !in_flight_); + in_flight_ = true; + if (method_tag_) { + if (grpc_server_request_registered_call( + server, method_tag_, &call_, &deadline_, &request_metadata_, + has_request_payload_ ? &request_payload_ : nullptr, cq_, + notify_cq, this) != GRPC_CALL_OK) { + TeardownRequest(); + return; + } + } else { + if (!call_details_) { + call_details_ = new grpc_call_details; + grpc_call_details_init(call_details_); + } + if (grpc_server_request_call(server, &call_, call_details_, + &request_metadata_, cq_, notify_cq, + this) != GRPC_CALL_OK) { + TeardownRequest(); + return; + } + } + } + + void PostShutdownCleanup() { + if (call_) { + grpc_call_unref(call_); + call_ = nullptr; + } + if (cq_) { + grpc_completion_queue_destroy(cq_); + cq_ = nullptr; + } + } + + bool FinalizeResult(void** tag, bool* status) override { + if (!*status) { + grpc_completion_queue_destroy(cq_); + cq_ = nullptr; + } + if (call_details_) { + deadline_ = call_details_->deadline; + grpc_call_details_destroy(call_details_); + grpc_call_details_init(call_details_); + } + return true; + } + + // The CallData class represents a call that is "active" as opposed + // to just being requested. It wraps and takes ownership of the cq from + // the call request + class CallData final { + public: + explicit CallData(Server* server, SyncRequest* mrd) + : cq_(mrd->cq_), + ctx_(mrd->deadline_, &mrd->request_metadata_), + has_request_payload_(mrd->has_request_payload_), + request_payload_(has_request_payload_ ? mrd->request_payload_ + : nullptr), + request_(nullptr), + method_(mrd->method_), + call_( + mrd->call_, server, &cq_, server->max_receive_message_size(), + ctx_.set_server_rpc_info(method_->name(), method_->method_type(), + server->interceptor_creators_)), + server_(server), + global_callbacks_(nullptr), + resources_(false) { + ctx_.set_call(mrd->call_); + ctx_.cq_ = &cq_; + GPR_ASSERT(mrd->in_flight_); + mrd->in_flight_ = false; + mrd->request_metadata_.count = 0; + } + + ~CallData() { + if (has_request_payload_ && request_payload_) { + grpc_byte_buffer_destroy(request_payload_); + } + } + + void Run(const std::shared_ptr& global_callbacks, + bool resources) { + global_callbacks_ = global_callbacks; + resources_ = resources; + + interceptor_methods_.SetCall(&call_); + interceptor_methods_.SetReverse(); + // Set interception point for RECV INITIAL METADATA + interceptor_methods_.AddInterceptionHookPoint( + grpc::experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA); + interceptor_methods_.SetRecvInitialMetadata(&ctx_.client_metadata_); + + if (has_request_payload_) { + // Set interception point for RECV MESSAGE + auto* handler = resources_ ? method_->handler() + : server_->resource_exhausted_handler_.get(); + request_ = handler->Deserialize(call_.call(), request_payload_, + &request_status_); + + request_payload_ = nullptr; + interceptor_methods_.AddInterceptionHookPoint( + grpc::experimental::InterceptionHookPoints::POST_RECV_MESSAGE); + interceptor_methods_.SetRecvMessage(request_, nullptr); + } + + if (interceptor_methods_.RunInterceptors( + [this]() { ContinueRunAfterInterception(); })) { + ContinueRunAfterInterception(); + } else { + // There were interceptors to be run, so ContinueRunAfterInterception + // will be run when interceptors are done. + } + } + + void ContinueRunAfterInterception() { + { + ctx_.BeginCompletionOp(&call_, nullptr, nullptr); + global_callbacks_->PreSynchronousRequest(&ctx_); + auto* handler = resources_ ? method_->handler() + : server_->resource_exhausted_handler_.get(); + handler->RunHandler(grpc::internal::MethodHandler::HandlerParameter( + &call_, &ctx_, request_, request_status_, nullptr)); + request_ = nullptr; + global_callbacks_->PostSynchronousRequest(&ctx_); + + cq_.Shutdown(); + + grpc::internal::CompletionQueueTag* op_tag = ctx_.GetCompletionOpTag(); + cq_.TryPluck(op_tag, gpr_inf_future(GPR_CLOCK_REALTIME)); + + /* Ensure the cq_ is shutdown */ + grpc::DummyTag ignored_tag; + GPR_ASSERT(cq_.Pluck(&ignored_tag) == false); + } + delete this; + } + + private: + grpc::CompletionQueue cq_; + grpc::ServerContext ctx_; + const bool has_request_payload_; + grpc_byte_buffer* request_payload_; + void* request_; + grpc::Status request_status_; + grpc::internal::RpcServiceMethod* const method_; + grpc::internal::Call call_; + Server* server_; + std::shared_ptr global_callbacks_; + bool resources_; + grpc::internal::InterceptorBatchMethodsImpl interceptor_methods_; + }; + + private: + grpc::internal::RpcServiceMethod* const method_; + void* const method_tag_; + bool in_flight_; + const bool has_request_payload_; + grpc_call* call_; + grpc_call_details* call_details_; + gpr_timespec deadline_; + grpc_metadata_array request_metadata_; + grpc_byte_buffer* request_payload_; + grpc_completion_queue* cq_; +}; + +class Server::CallbackRequestBase : public grpc::internal::CompletionQueueTag { + public: + virtual ~CallbackRequestBase() {} + virtual bool Request() = 0; +}; + +template +class Server::CallbackRequest final : public Server::CallbackRequestBase { + public: + static_assert(std::is_base_of::value, + "ServerContextType must be derived from ServerContext"); + + // The constructor needs to know the server for this callback request and its + // index in the server's request count array to allow for proper dynamic + // requesting of incoming RPCs. For codegen services, the values of method and + // method_tag represent the defined characteristics of the method being + // requested. For generic services, method and method_tag are nullptr since + // these services don't have pre-defined methods or method registration tags. + CallbackRequest(Server* server, size_t method_idx, + grpc::internal::RpcServiceMethod* method, void* method_tag) + : server_(server), + method_index_(method_idx), + method_(method), + method_tag_(method_tag), + has_request_payload_( + method_ != nullptr && + (method->method_type() == grpc::internal::RpcMethod::NORMAL_RPC || + method->method_type() == grpc::internal::RpcMethod::SERVER_STREAMING)), + cq_(server->CallbackCQ()), + tag_(this) { + server_->callback_reqs_outstanding_++; + Setup(); + } + + ~CallbackRequest() { + Clear(); + + // The counter of outstanding requests must be decremented + // under a lock in case it causes the server shutdown. + std::lock_guard l(server_->callback_reqs_mu_); + if (--server_->callback_reqs_outstanding_ == 0) { + server_->callback_reqs_done_cv_.notify_one(); + } + } + + bool Request() override { + if (method_tag_) { + if (GRPC_CALL_OK != + grpc_server_request_registered_call( + server_->c_server(), method_tag_, &call_, &deadline_, + &request_metadata_, + has_request_payload_ ? &request_payload_ : nullptr, cq_->cq(), + cq_->cq(), static_cast(&tag_))) { + return false; + } + } else { + if (!call_details_) { + call_details_ = new grpc_call_details; + grpc_call_details_init(call_details_); + } + if (grpc_server_request_call(server_->c_server(), &call_, call_details_, + &request_metadata_, cq_->cq(), cq_->cq(), + static_cast(&tag_)) != GRPC_CALL_OK) { + return false; + } + } + return true; + } + + // Needs specialization to account for different processing of metadata + // in generic API + bool FinalizeResult(void** tag, bool* status) override; + + private: + // method_name needs to be specialized between named method and generic + const char* method_name() const; + + class CallbackCallTag : public grpc_experimental_completion_queue_functor { + public: + CallbackCallTag(Server::CallbackRequest* req) + : req_(req) { + functor_run = &CallbackCallTag::StaticRun; + } + + // force_run can not be performed on a tag if operations using this tag + // have been sent to PerformOpsOnCall. It is intended for error conditions + // that are detected before the operations are internally processed. + void force_run(bool ok) { Run(ok); } + + private: + Server::CallbackRequest* req_; + grpc::internal::Call* call_; + + static void StaticRun(grpc_experimental_completion_queue_functor* cb, + int ok) { + static_cast(cb)->Run(static_cast(ok)); + } + void Run(bool ok) { + void* ignored = req_; + bool new_ok = ok; + GPR_ASSERT(!req_->FinalizeResult(&ignored, &new_ok)); + GPR_ASSERT(ignored == req_); + + int count = + static_cast(gpr_atm_no_barrier_fetch_add( + &req_->server_ + ->callback_unmatched_reqs_count_[req_->method_index_], + -1)) - + 1; + if (!ok) { + // The call has been shutdown. + // Delete its contents to free up the request. + delete req_; + return; + } + + // If this was the last request in the list or it is below the soft + // minimum and there are spare requests available, set up a new one. + if (count == 0 || (count < SOFT_MINIMUM_SPARE_CALLBACK_REQS_PER_METHOD && + req_->server_->callback_reqs_outstanding_ < + SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING)) { + auto* new_req = new CallbackRequest( + req_->server_, req_->method_index_, req_->method_, + req_->method_tag_); + if (!new_req->Request()) { + // The server must have just decided to shutdown. + gpr_atm_no_barrier_fetch_add( + &new_req->server_ + ->callback_unmatched_reqs_count_[new_req->method_index_], + -1); + delete new_req; + } + } + + // Bind the call, deadline, and metadata from what we got + req_->ctx_.set_call(req_->call_); + req_->ctx_.cq_ = req_->cq_; + req_->ctx_.BindDeadlineAndMetadata(req_->deadline_, + &req_->request_metadata_); + req_->request_metadata_.count = 0; + + // Create a C++ Call to control the underlying core call + call_ = new (grpc_call_arena_alloc(req_->call_, sizeof(grpc::internal::Call))) + grpc::internal::Call(req_->call_, req_->server_, req_->cq_, + req_->server_->max_receive_message_size(), + req_->ctx_.set_server_rpc_info( + req_->method_name(), + (req_->method_ != nullptr) + ? req_->method_->method_type() + : grpc::internal::RpcMethod::BIDI_STREAMING, + req_->server_->interceptor_creators_)); + + req_->interceptor_methods_.SetCall(call_); + req_->interceptor_methods_.SetReverse(); + // Set interception point for RECV INITIAL METADATA + req_->interceptor_methods_.AddInterceptionHookPoint( + grpc::experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA); + req_->interceptor_methods_.SetRecvInitialMetadata( + &req_->ctx_.client_metadata_); + + if (req_->has_request_payload_) { + // Set interception point for RECV MESSAGE + req_->request_ = req_->method_->handler()->Deserialize( + req_->call_, req_->request_payload_, &req_->request_status_); + req_->request_payload_ = nullptr; + req_->interceptor_methods_.AddInterceptionHookPoint( + grpc::experimental::InterceptionHookPoints::POST_RECV_MESSAGE); + req_->interceptor_methods_.SetRecvMessage(req_->request_, nullptr); + } + + if (req_->interceptor_methods_.RunInterceptors( + [this] { ContinueRunAfterInterception(); })) { + ContinueRunAfterInterception(); + } else { + // There were interceptors to be run, so ContinueRunAfterInterception + // will be run when interceptors are done. + } + } + void ContinueRunAfterInterception() { + auto* handler = (req_->method_ != nullptr) + ? req_->method_->handler() + : req_->server_->generic_handler_.get(); + handler->RunHandler(grpc::internal::MethodHandler::HandlerParameter( + call_, &req_->ctx_, req_->request_, req_->request_status_, [this] { + // Recycle this request if there aren't too many outstanding. + // Note that we don't have to worry about a case where there + // are no requests waiting to match for this method since that + // is already taken care of when binding a request to a call. + // TODO(vjpai): Also don't recycle this request if the dynamic + // load no longer justifies it. Consider measuring + // dynamic load and setting a target accordingly. + if (req_->server_->callback_reqs_outstanding_ < + SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING) { + req_->Clear(); + req_->Setup(); + } else { + // We can free up this request because there are too many + delete req_; + return; + } + if (!req_->Request()) { + // The server must have just decided to shutdown. + delete req_; + } + })); + } + }; + + void Clear() { + if (call_details_) { + delete call_details_; + call_details_ = nullptr; + } + grpc_metadata_array_destroy(&request_metadata_); + if (has_request_payload_ && request_payload_) { + grpc_byte_buffer_destroy(request_payload_); + } + ctx_.Clear(); + interceptor_methods_.ClearState(); + } + + void Setup() { + gpr_atm_no_barrier_fetch_add( + &server_->callback_unmatched_reqs_count_[method_index_], 1); + grpc_metadata_array_init(&request_metadata_); + ctx_.Setup(gpr_inf_future(GPR_CLOCK_REALTIME)); + request_payload_ = nullptr; + request_ = nullptr; + request_status_ = grpc::Status(); + } + + Server* const server_; + const size_t method_index_; + grpc::internal::RpcServiceMethod* const method_; + void* const method_tag_; + const bool has_request_payload_; + grpc_byte_buffer* request_payload_; + void* request_; + grpc::Status request_status_; + grpc_call_details* call_details_ = nullptr; + grpc_call* call_; + gpr_timespec deadline_; + grpc_metadata_array request_metadata_; + grpc::CompletionQueue* cq_; + CallbackCallTag tag_; + ServerContextType ctx_; + grpc::internal::InterceptorBatchMethodsImpl interceptor_methods_; +}; + +template <> +bool Server::CallbackRequest::FinalizeResult(void** tag, + bool* status) { + return false; +} + +template <> +bool Server::CallbackRequest::FinalizeResult( + void** tag, bool* status) { + if (*status) { + // TODO(yangg) remove the copy here + ctx_.method_ = grpc::StringFromCopiedSlice(call_details_->method); + ctx_.host_ = grpc::StringFromCopiedSlice(call_details_->host); + } + grpc_slice_unref(call_details_->method); + grpc_slice_unref(call_details_->host); + return false; +} + +template <> +const char* Server::CallbackRequest::method_name() const { + return method_->name(); +} + +template <> +const char* Server::CallbackRequest::method_name() const { + return ctx_.method().c_str(); +} + +// Implementation of ThreadManager. Each instance of SyncRequestThreadManager +// manages a pool of threads that poll for incoming Sync RPCs and call the +// appropriate RPC handlers +class Server::SyncRequestThreadManager : public grpc::ThreadManager { + public: + SyncRequestThreadManager(Server* server, grpc::CompletionQueue* server_cq, + std::shared_ptr global_callbacks, + grpc_resource_quota* rq, int min_pollers, + int max_pollers, int cq_timeout_msec) + : ThreadManager("SyncServer", rq, min_pollers, max_pollers), + server_(server), + server_cq_(server_cq), + cq_timeout_msec_(cq_timeout_msec), + global_callbacks_(std::move(global_callbacks)) {} + + WorkStatus PollForWork(void** tag, bool* ok) override { + *tag = nullptr; + // TODO(ctiller): workaround for GPR_TIMESPAN based deadlines not working + // right now + gpr_timespec deadline = + gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_millis(cq_timeout_msec_, GPR_TIMESPAN)); + + switch (server_cq_->AsyncNext(tag, ok, deadline)) { + case grpc::CompletionQueue::TIMEOUT: + return TIMEOUT; + case grpc::CompletionQueue::SHUTDOWN: + return SHUTDOWN; + case grpc::CompletionQueue::GOT_EVENT: + return WORK_FOUND; + } + + GPR_UNREACHABLE_CODE(return TIMEOUT); + } + + void DoWork(void* tag, bool ok, bool resources) override { + SyncRequest* sync_req = static_cast(tag); + + if (!sync_req) { + // No tag. Nothing to work on. This is an unlikley scenario and possibly a + // bug in RPC Manager implementation. + gpr_log(GPR_ERROR, "Sync server. DoWork() was called with NULL tag"); + return; + } + + if (ok) { + // Calldata takes ownership of the completion queue and interceptors + // inside sync_req + auto* cd = new SyncRequest::CallData(server_, sync_req); + // Prepare for the next request + if (!IsShutdown()) { + sync_req->SetupRequest(); // Create new completion queue for sync_req + sync_req->Request(server_->c_server(), server_cq_->cq()); + } + + GPR_TIMER_SCOPE("cd.Run()", 0); + cd->Run(global_callbacks_, resources); + } + // TODO (sreek) If ok is false here (which it isn't in case of + // grpc_request_registered_call), we should still re-queue the request + // object + } + + void AddSyncMethod(grpc::internal::RpcServiceMethod* method, void* tag) { + sync_requests_.emplace_back(new SyncRequest(method, tag)); + } + + void AddUnknownSyncMethod() { + if (!sync_requests_.empty()) { + unknown_method_.reset(new grpc::internal::RpcServiceMethod( + "unknown", grpc::internal::RpcMethod::BIDI_STREAMING, + new grpc::internal::UnknownMethodHandler)); + sync_requests_.emplace_back( + new SyncRequest(unknown_method_.get(), nullptr)); + } + } + + void Shutdown() override { + ThreadManager::Shutdown(); + server_cq_->Shutdown(); + } + + void Wait() override { + ThreadManager::Wait(); + // Drain any pending items from the queue + void* tag; + bool ok; + while (server_cq_->Next(&tag, &ok)) { + if (ok) { + // If a request was pulled off the queue, it means that the thread + // handling the request added it to the completion queue after shutdown + // was called - because the thread had already started and checked the + // shutdown flag before shutdown was called. In this case, we simply + // clean it up here, *after* calling wait on all the worker threads, at + // which point we are certain no in-flight requests will add more to the + // queue. This fixes an intermittent memory leak on shutdown. + SyncRequest* sync_req = static_cast(tag); + sync_req->PostShutdownCleanup(); + } + } + } + + void Start() { + if (!sync_requests_.empty()) { + for (auto m = sync_requests_.begin(); m != sync_requests_.end(); m++) { + (*m)->SetupRequest(); + (*m)->Request(server_->c_server(), server_cq_->cq()); + } + + Initialize(); // ThreadManager's Initialize() + } + } + + private: + Server* server_; + grpc::CompletionQueue* server_cq_; + int cq_timeout_msec_; + std::vector> sync_requests_; + std::unique_ptr unknown_method_; + std::shared_ptr global_callbacks_; +}; + +static grpc::internal::GrpcLibraryInitializer g_gli_initializer; +Server::Server( + int max_receive_message_size, grpc::ChannelArguments* args, + std::shared_ptr>> + sync_server_cqs, + int min_pollers, int max_pollers, int sync_cq_timeout_msec, + grpc_resource_quota* server_rq, + std::vector< + std::unique_ptr> + interceptor_creators) + : interceptor_creators_(std::move(interceptor_creators)), + max_receive_message_size_(max_receive_message_size), + sync_server_cqs_(std::move(sync_server_cqs)), + started_(false), + shutdown_(false), + shutdown_notified_(false), + server_(nullptr), + server_initializer_(new grpc::ServerInitializer(this)), + health_check_service_disabled_(false) { + g_gli_initializer.summon(); + gpr_once_init(&grpc::g_once_init_callbacks, grpc::InitGlobalCallbacks); + global_callbacks_ = grpc::g_callbacks; + global_callbacks_->UpdateArguments(args); + + if (sync_server_cqs_ != nullptr) { + bool default_rq_created = false; + if (server_rq == nullptr) { + server_rq = grpc_resource_quota_create("SyncServer-default-rq"); + grpc_resource_quota_set_max_threads(server_rq, + DEFAULT_MAX_SYNC_SERVER_THREADS); + default_rq_created = true; + } + + for (const auto& it : *sync_server_cqs_) { + sync_req_mgrs_.emplace_back(new SyncRequestThreadManager( + this, it.get(), global_callbacks_, server_rq, min_pollers, + max_pollers, sync_cq_timeout_msec)); + } + + if (default_rq_created) { + grpc_resource_quota_unref(server_rq); + } + } + + grpc_channel_args channel_args; + args->SetChannelArgs(&channel_args); + + for (size_t i = 0; i < channel_args.num_args; i++) { + if (0 == + strcmp(channel_args.args[i].key, grpc::kHealthCheckServiceInterfaceArg)) { + if (channel_args.args[i].value.pointer.p == nullptr) { + health_check_service_disabled_ = true; + } else { + health_check_service_.reset(static_cast( + channel_args.args[i].value.pointer.p)); + } + break; + } + } + + server_ = grpc_server_create(&channel_args, nullptr); +} + +Server::~Server() { + { + std::unique_lock lock(mu_); + if (callback_cq_ != nullptr) { + callback_cq_->Shutdown(); + } + if (started_ && !shutdown_) { + lock.unlock(); + Shutdown(); + } else if (!started_) { + // Shutdown the completion queues + for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { + (*it)->Shutdown(); + } + } + } + + grpc_server_destroy(server_); + for (auto& per_method_count : callback_unmatched_reqs_count_) { + // There should be no more unmatched callbacks for any method + // as each request is failed by Shutdown. Check that this actually + // happened + GPR_ASSERT(static_cast(gpr_atm_no_barrier_load(&per_method_count)) == + 0); + } +} + +void Server::SetGlobalCallbacks(GlobalCallbacks* callbacks) { + GPR_ASSERT(!grpc::g_callbacks); + GPR_ASSERT(callbacks); + grpc::g_callbacks.reset(callbacks); +} + +grpc_server* Server::c_server() { return server_; } + +std::shared_ptr Server::InProcessChannel( + const grpc::ChannelArguments& args) { + grpc_channel_args channel_args = args.c_channel_args(); + return grpc::CreateChannelInternal( + "inproc", grpc_inproc_channel_create(server_, &channel_args, nullptr), + std::vector< + std::unique_ptr>()); +} + +std::shared_ptr +Server::experimental_type::InProcessChannelWithInterceptors( + const grpc::ChannelArguments& args, + std::vector< + std::unique_ptr> + interceptor_creators) { + grpc_channel_args channel_args = args.c_channel_args(); + return grpc::CreateChannelInternal( + "inproc", + grpc_inproc_channel_create(server_->server_, &channel_args, nullptr), + std::move(interceptor_creators)); +} + +static grpc_server_register_method_payload_handling PayloadHandlingForMethod( + grpc::internal::RpcServiceMethod* method) { + switch (method->method_type()) { + case grpc::internal::RpcMethod::NORMAL_RPC: + case grpc::internal::RpcMethod::SERVER_STREAMING: + return GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER; + case grpc::internal::RpcMethod::CLIENT_STREAMING: + case grpc::internal::RpcMethod::BIDI_STREAMING: + return GRPC_SRM_PAYLOAD_NONE; + } + GPR_UNREACHABLE_CODE(return GRPC_SRM_PAYLOAD_NONE;); +} + +bool Server::RegisterService(const grpc::string* host, grpc::Service* service) { + bool has_async_methods = service->has_async_methods(); + if (has_async_methods) { + GPR_ASSERT(service->server_ == nullptr && + "Can only register an asynchronous service against one server."); + service->server_ = this; + } + + const char* method_name = nullptr; + + for (auto it = service->methods_.begin(); it != service->methods_.end(); + ++it) { + if (it->get() == nullptr) { // Handled by generic service if any. + continue; + } + + grpc::internal::RpcServiceMethod* method = it->get(); + void* method_registration_tag = grpc_server_register_method( + server_, method->name(), host ? host->c_str() : nullptr, + PayloadHandlingForMethod(method), 0); + if (method_registration_tag == nullptr) { + gpr_log(GPR_DEBUG, "Attempt to register %s multiple times", + method->name()); + return false; + } + + if (method->handler() == nullptr) { // Async method without handler + method->set_server_tag(method_registration_tag); + } else if (method->api_type() == + grpc::internal::RpcServiceMethod::ApiType::SYNC) { + for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { + (*it)->AddSyncMethod(method, method_registration_tag); + } + } else { + // a callback method. Register at least some callback requests + callback_unmatched_reqs_count_.push_back(0); + auto method_index = callback_unmatched_reqs_count_.size() - 1; + // TODO(vjpai): Register these dynamically based on need + for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) { + callback_reqs_to_start_.push_back(new CallbackRequest( + this, method_index, method, method_registration_tag)); + } + // Enqueue it so that it will be Request'ed later after all request + // matchers are created at core server startup + } + + method_name = method->name(); + } + + // Parse service name. + if (method_name != nullptr) { + std::stringstream ss(method_name); + grpc::string service_name; + if (std::getline(ss, service_name, '/') && + std::getline(ss, service_name, '/')) { + services_.push_back(service_name); + } + } + return true; +} + +void Server::RegisterAsyncGenericService(grpc::AsyncGenericService* service) { + GPR_ASSERT(service->server_ == nullptr && + "Can only register an async generic service against one server."); + service->server_ = this; + has_async_generic_service_ = true; +} + +void Server::RegisterCallbackGenericService( + grpc::experimental::CallbackGenericService* service) { + GPR_ASSERT( + service->server_ == nullptr && + "Can only register a callback generic service against one server."); + service->server_ = this; + has_callback_generic_service_ = true; + generic_handler_.reset(service->Handler()); + + callback_unmatched_reqs_count_.push_back(0); + auto method_index = callback_unmatched_reqs_count_.size() - 1; + // TODO(vjpai): Register these dynamically based on need + for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) { + callback_reqs_to_start_.push_back(new CallbackRequest( + this, method_index, nullptr, nullptr)); + } +} + +int Server::AddListeningPort(const grpc::string& addr, + grpc::ServerCredentials* creds) { + GPR_ASSERT(!started_); + int port = creds->AddPortToServer(addr, server_); + global_callbacks_->AddPort(this, addr, creds, port); + return port; +} + +void Server::Start(grpc::ServerCompletionQueue** cqs, size_t num_cqs) { + GPR_ASSERT(!started_); + global_callbacks_->PreServerStart(this); + started_ = true; + + // Only create default health check service when user did not provide an + // explicit one. + grpc::ServerCompletionQueue* health_check_cq = nullptr; + grpc::DefaultHealthCheckService::HealthCheckServiceImpl* + default_health_check_service_impl = nullptr; + if (health_check_service_ == nullptr && !health_check_service_disabled_ && + grpc::DefaultHealthCheckServiceEnabled()) { + auto* default_hc_service = new grpc::DefaultHealthCheckService; + health_check_service_.reset(default_hc_service); + // We create a non-polling CQ to avoid impacting application + // performance. This ensures that we don't introduce thread hops + // for application requests that wind up on this CQ, which is polled + // in its own thread. + health_check_cq = + new grpc::ServerCompletionQueue(GRPC_CQ_NEXT, GRPC_CQ_NON_POLLING, nullptr); + grpc_server_register_completion_queue(server_, health_check_cq->cq(), + nullptr); + default_health_check_service_impl = + default_hc_service->GetHealthCheckService( + std::unique_ptr(health_check_cq)); + RegisterService(nullptr, default_health_check_service_impl); + } + + // If this server uses callback methods, then create a callback generic + // service to handle any unimplemented methods using the default reactor + // creator + if (!callback_reqs_to_start_.empty() && !has_callback_generic_service_) { + unimplemented_service_.reset(new grpc::experimental::CallbackGenericService); + RegisterCallbackGenericService(unimplemented_service_.get()); + } + + grpc_server_start(server_); + + if (!has_async_generic_service_ && !has_callback_generic_service_) { + for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { + (*it)->AddUnknownSyncMethod(); + } + + for (size_t i = 0; i < num_cqs; i++) { + if (cqs[i]->IsFrequentlyPolled()) { + new UnimplementedAsyncRequest(this, cqs[i]); + } + } + if (health_check_cq != nullptr) { + new UnimplementedAsyncRequest(this, health_check_cq); + } + } + + // If this server has any support for synchronous methods (has any sync + // server CQs), make sure that we have a ResourceExhausted handler + // to deal with the case of thread exhaustion + if (sync_server_cqs_ != nullptr && !sync_server_cqs_->empty()) { + resource_exhausted_handler_.reset(new grpc::internal::ResourceExhaustedHandler); + } + + for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { + (*it)->Start(); + } + + for (auto* cbreq : callback_reqs_to_start_) { + GPR_ASSERT(cbreq->Request()); + } + callback_reqs_to_start_.clear(); + + if (default_health_check_service_impl != nullptr) { + default_health_check_service_impl->StartServingThread(); + } +} + +void Server::ShutdownInternal(gpr_timespec deadline) { + std::unique_lock lock(mu_); + if (shutdown_) { + return; + } + + shutdown_ = true; + + /// The completion queue to use for server shutdown completion notification + grpc::CompletionQueue shutdown_cq; + grpc::ShutdownTag shutdown_tag; // Dummy shutdown tag + grpc_server_shutdown_and_notify(server_, shutdown_cq.cq(), &shutdown_tag); + + shutdown_cq.Shutdown(); + + void* tag; + bool ok; + grpc::CompletionQueue::NextStatus status = + shutdown_cq.AsyncNext(&tag, &ok, deadline); + + // If this timed out, it means we are done with the grace period for a clean + // shutdown. We should force a shutdown now by cancelling all inflight calls + if (status == grpc::CompletionQueue::NextStatus::TIMEOUT) { + grpc_server_cancel_all_calls(server_); + } + // Else in case of SHUTDOWN or GOT_EVENT, it means that the server has + // successfully shutdown + + // Shutdown all ThreadManagers. This will try to gracefully stop all the + // threads in the ThreadManagers (once they process any inflight requests) + for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { + (*it)->Shutdown(); // ThreadManager's Shutdown() + } + + // Wait for threads in all ThreadManagers to terminate + for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { + (*it)->Wait(); + } + + // Wait for all outstanding callback requests to complete + // (whether waiting for a match or already active). + // We know that no new requests will be created after this point + // because they are only created at server startup time or when + // we have a successful match on a request. During the shutdown phase, + // requests that have not yet matched will be failed rather than + // allowed to succeed, which will cause the server to delete the + // request and decrement the count. Possibly a request will match before + // the shutdown but then find that shutdown has already started by the + // time it tries to register a new request. In that case, the registration + // will report a failure, indicating a shutdown and again we won't end + // up incrementing the counter. + { + std::unique_lock cblock(callback_reqs_mu_); + callback_reqs_done_cv_.wait( + cblock, [this] { return callback_reqs_outstanding_ == 0; }); + } + + // Drain the shutdown queue (if the previous call to AsyncNext() timed out + // and we didn't remove the tag from the queue yet) + while (shutdown_cq.Next(&tag, &ok)) { + // Nothing to be done here. Just ignore ok and tag values + } + + shutdown_notified_ = true; + shutdown_cv_.notify_all(); +} + +void Server::Wait() { + std::unique_lock lock(mu_); + while (started_ && !shutdown_notified_) { + shutdown_cv_.wait(lock); + } +} + +void Server::PerformOpsOnCall(grpc::internal::CallOpSetInterface* ops, + grpc::internal::Call* call) { + ops->FillOps(call); +} + +bool Server::UnimplementedAsyncRequest::FinalizeResult(void** tag, + bool* status) { + if (GenericAsyncRequest::FinalizeResult(tag, status)) { + // We either had no interceptors run or we are done intercepting + if (*status) { + new UnimplementedAsyncRequest(server_, cq_); + new UnimplementedAsyncResponse(this); + } else { + delete this; + } + } else { + // The tag was swallowed due to interception. We will see it again. + } + return false; +} + +Server::UnimplementedAsyncResponse::UnimplementedAsyncResponse( + UnimplementedAsyncRequest* request) + : request_(request) { + grpc::Status status(grpc::StatusCode::UNIMPLEMENTED, ""); + grpc::internal::UnknownMethodHandler::FillOps(request_->context(), this); + request_->stream()->call_.PerformOps(this); +} + +grpc::ServerInitializer* Server::initializer() { return server_initializer_.get(); } + +grpc::CompletionQueue* Server::CallbackCQ() { // TODO(vjpai): Consider using a single global CQ for the default CQ // if there is no explicit per-server CQ registered std::lock_guard l(mu_); if (callback_cq_ == nullptr) { - auto* shutdown_callback = new ShutdownCallback; - callback_cq_ = new CompletionQueue(grpc_completion_queue_attributes{ + auto* shutdown_callback = new grpc::ShutdownCallback; + callback_cq_ = new grpc::CompletionQueue(grpc_completion_queue_attributes{ GRPC_CQ_CURRENT_VERSION, GRPC_CQ_CALLBACK, GRPC_CQ_DEFAULT_POLLING, shutdown_callback}); @@ -1335,4 +1339,4 @@ CompletionQueue* Server::CallbackCQ() { return callback_cq_; } -} // namespace grpc +} // namespace grpc_impl diff --git a/test/cpp/util/metrics_server.h b/test/cpp/util/metrics_server.h index 2d6ddf08043..08f6034c28e 100644 --- a/test/cpp/util/metrics_server.h +++ b/test/cpp/util/metrics_server.h @@ -21,6 +21,8 @@ #include #include +#include + #include "src/proto/grpc/testing/metrics.grpc.pb.h" #include "src/proto/grpc/testing/metrics.pb.h" From 3f3f1772221302d708ecf79ea641c2ea24ecbb6d Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Wed, 20 Mar 2019 16:08:53 -0700 Subject: [PATCH 037/242] Fix route guide example --- examples/cpp/route_guide/route_guide_server.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/cpp/route_guide/route_guide_server.cc b/examples/cpp/route_guide/route_guide_server.cc index 5867c167128..7217bb2f8ac 100644 --- a/examples/cpp/route_guide/route_guide_server.cc +++ b/examples/cpp/route_guide/route_guide_server.cc @@ -147,24 +147,25 @@ class RouteGuideImpl final : public RouteGuide::Service { Status RouteChat(ServerContext* context, ServerReaderWriter* stream) override { - std::vector received_notes; RouteNote note; while (stream->Read(¬e)) { - for (const RouteNote& n : received_notes) { + std::unique_lock lock(mu_); + for (const RouteNote& n : received_notes_) { if (n.location().latitude() == note.location().latitude() && n.location().longitude() == note.location().longitude()) { stream->Write(n); } } - received_notes.push_back(note); + received_notes_.push_back(note); } return Status::OK; } private: - std::vector feature_list_; + std::mutex mu_; + std::vector received_notes_; }; void RunServer(const std::string& db_path) { From 303416080c447dae8729e1ffbe78a366f1f88a71 Mon Sep 17 00:00:00 2001 From: Thibaut Le Guilly Date: Tue, 9 Oct 2018 17:10:22 +0900 Subject: [PATCH 038/242] Provide access to verify_peer_callback from C# --- src/csharp/Grpc.Core/ChannelCredentials.cs | 69 +++++++++++++++++-- .../Internal/ChannelCredentialsSafeHandle.cs | 12 +++- .../Internal/NativeMethods.Generated.cs | 6 +- src/csharp/Grpc.Core/VerifyPeerContext.cs | 30 ++++++++ .../SslCredentialsTest.cs | 43 +++++++++++- src/csharp/ext/grpc_csharp_ext.c | 41 +++++++++-- .../Grpc.Core/Internal/native_methods.include | 2 +- 7 files changed, 184 insertions(+), 19 deletions(-) create mode 100644 src/csharp/Grpc.Core/VerifyPeerContext.cs diff --git a/src/csharp/Grpc.Core/ChannelCredentials.cs b/src/csharp/Grpc.Core/ChannelCredentials.cs index 3ce32f31b76..103a594bb06 100644 --- a/src/csharp/Grpc.Core/ChannelCredentials.cs +++ b/src/csharp/Grpc.Core/ChannelCredentials.cs @@ -18,9 +18,11 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; using System.Threading.Tasks; using Grpc.Core.Internal; +using Grpc.Core.Logging; using Grpc.Core.Utils; namespace Grpc.Core @@ -104,20 +106,36 @@ namespace Grpc.Core } } + /// + /// Callback invoked with the expected targetHost and the peer's certificate. + /// If false is returned by this callback then it is treated as a + /// verification failure. Invocation of the callback is blocking, so any + /// implementation should be light-weight. + /// + /// The associated with the callback + /// true if verification succeeded, false otherwise. + /// Note: experimental API that can change or be removed without any prior notice. + public delegate bool VerifyPeerCallback(VerifyPeerContext context); + /// /// Client-side SSL credentials. /// public sealed class SslCredentials : ChannelCredentials { + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); + readonly string rootCertificates; readonly KeyCertificatePair keyCertificatePair; + readonly VerifyPeerCallback verifyPeerCallback; + readonly VerifyPeerCallbackInternal verifyPeerCallbackInternal; + readonly GCHandle gcHandle; /// /// Creates client-side SSL credentials loaded from /// disk file pointed to by the GRPC_DEFAULT_SSL_ROOTS_FILE_PATH environment variable. /// If that fails, gets the roots certificates from a well known place on disk. /// - public SslCredentials() : this(null, null) + public SslCredentials() : this(null, null, null) { } @@ -125,19 +143,37 @@ namespace Grpc.Core /// Creates client-side SSL credentials from /// a string containing PEM encoded root certificates. /// - public SslCredentials(string rootCertificates) : this(rootCertificates, null) + public SslCredentials(string rootCertificates) : this(rootCertificates, null, null) { } - + /// /// Creates client-side SSL credentials. /// /// string containing PEM encoded server root certificates. /// a key certificate pair. - public SslCredentials(string rootCertificates, KeyCertificatePair keyCertificatePair) + public SslCredentials(string rootCertificates, KeyCertificatePair keyCertificatePair) : + this(rootCertificates, keyCertificatePair, null) + { + } + + /// + /// Creates client-side SSL credentials. + /// + /// string containing PEM encoded server root certificates. + /// a key certificate pair. + /// a callback to verify peer's target name and certificate. + /// Note: experimental API that can change or be removed without any prior notice. + public SslCredentials(string rootCertificates, KeyCertificatePair keyCertificatePair, VerifyPeerCallback verifyPeerCallback) { this.rootCertificates = rootCertificates; this.keyCertificatePair = keyCertificatePair; + if (verifyPeerCallback != null) + { + this.verifyPeerCallback = verifyPeerCallback; + this.verifyPeerCallbackInternal = this.VerifyPeerCallbackHandler; + gcHandle = GCHandle.Alloc(verifyPeerCallbackInternal); + } } /// @@ -171,7 +207,30 @@ namespace Grpc.Core internal override ChannelCredentialsSafeHandle CreateNativeCredentials() { - return ChannelCredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair); + return ChannelCredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair, this.verifyPeerCallbackInternal); + } + + private int VerifyPeerCallbackHandler(IntPtr host, IntPtr pem, IntPtr userData, bool isDestroy) + { + if (isDestroy) + { + this.gcHandle.Free(); + return 0; + } + + try + { + var context = new VerifyPeerContext(Marshal.PtrToStringAnsi(host), Marshal.PtrToStringAnsi(pem)); + + return this.verifyPeerCallback(context) ? 0 : 1; + } + catch (Exception e) + { + // eat the exception, we must not throw when inside callback from native code. + Logger.Error(e, "Exception occurred while invoking verify peer callback handler."); + // Return validation failure in case of exception. + return 1; + } } } diff --git a/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs index 11b5d2cc3f6..5e336673153 100644 --- a/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs @@ -20,6 +20,12 @@ using System.Threading.Tasks; namespace Grpc.Core.Internal { + internal delegate int VerifyPeerCallbackInternal( + IntPtr targetHost, + IntPtr targetPem, + IntPtr userData, + bool isDestroy); + /// /// grpc_channel_credentials from grpc/grpc_security.h /// @@ -38,15 +44,15 @@ namespace Grpc.Core.Internal return creds; } - public static ChannelCredentialsSafeHandle CreateSslCredentials(string pemRootCerts, KeyCertificatePair keyCertPair) + public static ChannelCredentialsSafeHandle CreateSslCredentials(string pemRootCerts, KeyCertificatePair keyCertPair, VerifyPeerCallbackInternal verifyPeerCallback) { if (keyCertPair != null) { - return Native.grpcsharp_ssl_credentials_create(pemRootCerts, keyCertPair.CertificateChain, keyCertPair.PrivateKey); + return Native.grpcsharp_ssl_credentials_create(pemRootCerts, keyCertPair.CertificateChain, keyCertPair.PrivateKey, verifyPeerCallback); } else { - return Native.grpcsharp_ssl_credentials_create(pemRootCerts, null, null); + return Native.grpcsharp_ssl_credentials_create(pemRootCerts, null, null, verifyPeerCallback); } } diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs index b7b9a12d8a3..e09b9813f79 100644 --- a/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs +++ b/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs @@ -482,7 +482,7 @@ namespace Grpc.Core.Internal public delegate void grpcsharp_channel_args_set_integer_delegate(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); public delegate void grpcsharp_channel_args_destroy_delegate(IntPtr args); public delegate void grpcsharp_override_default_ssl_roots_delegate(string pemRootCerts); - public delegate ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create_delegate(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey); + public delegate ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create_delegate(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, VerifyPeerCallbackInternal verifyPeerCallback); public delegate ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create_delegate(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); public delegate void grpcsharp_channel_credentials_release_delegate(IntPtr credentials); public delegate ChannelSafeHandle grpcsharp_insecure_channel_create_delegate(string target, ChannelArgsSafeHandle channelArgs); @@ -676,7 +676,7 @@ namespace Grpc.Core.Internal public static extern void grpcsharp_override_default_ssl_roots(string pemRootCerts); [DllImport(ImportName)] - public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey); + public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, VerifyPeerCallbackInternal verifyPeerCallback); [DllImport(ImportName)] public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); @@ -972,7 +972,7 @@ namespace Grpc.Core.Internal public static extern void grpcsharp_override_default_ssl_roots(string pemRootCerts); [DllImport(ImportName)] - public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey); + public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, VerifyPeerCallbackInternal verifyPeerCallback); [DllImport(ImportName)] public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); diff --git a/src/csharp/Grpc.Core/VerifyPeerContext.cs b/src/csharp/Grpc.Core/VerifyPeerContext.cs new file mode 100644 index 00000000000..b48984b093c --- /dev/null +++ b/src/csharp/Grpc.Core/VerifyPeerContext.cs @@ -0,0 +1,30 @@ +namespace Grpc.Core +{ + /// + /// Verification context for VerifyPeerCallback. + /// Note: experimental API that can change or be removed without any prior notice. + /// + public class VerifyPeerContext + { + /// + /// Initializes a new instance of the class. + /// + /// string containing the host name of the peer. + /// string containing PEM encoded certificate of the peer. + internal VerifyPeerContext(string targetHost, string targetPem) + { + this.TargetHost = targetHost; + this.TargetPem = targetPem; + } + + /// + /// String containing the host name of the peer. + /// + public string TargetHost { get; } + + /// + /// string containing PEM encoded certificate of the peer. + /// + public string TargetPem { get; } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs index b3c47c2d8d3..818ac6d1adc 100644 --- a/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs +++ b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs @@ -44,17 +44,23 @@ namespace Grpc.IntegrationTesting string rootCert; KeyCertificatePair keyCertPair; + string certChain; + List options; + bool isHostEqual; + bool isPemEqual; public void InitClientAndServer(bool clientAddKeyCertPair, SslClientCertificateRequestType clientCertRequestType) { rootCert = File.ReadAllText(TestCredentials.ClientCertAuthorityPath); + certChain = File.ReadAllText(TestCredentials.ServerCertChainPath); + certChain = certChain.Replace("\r", string.Empty); keyCertPair = new KeyCertificatePair( - File.ReadAllText(TestCredentials.ServerCertChainPath), + certChain, File.ReadAllText(TestCredentials.ServerPrivateKeyPath)); var serverCredentials = new SslServerCredentials(new[] { keyCertPair }, rootCert, clientCertRequestType); - var clientCredentials = clientAddKeyCertPair ? new SslCredentials(rootCert, keyCertPair) : new SslCredentials(rootCert); + var clientCredentials = clientAddKeyCertPair ? new SslCredentials(rootCert, keyCertPair, context => this.VerifyPeerCallback(context, true)) : new SslCredentials(rootCert); // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) @@ -64,7 +70,7 @@ namespace Grpc.IntegrationTesting }; server.Start(); - var options = new List + options = new List { new ChannelOption(ChannelOptions.SslTargetNameOverride, TestCredentials.DefaultHostOverride) }; @@ -210,6 +216,37 @@ namespace Grpc.IntegrationTesting Assert.AreEqual(12345, response.AggregatedPayloadSize); } + [Test] + public void VerifyPeerCallbackTest() + { + InitClientAndServer(true, SslClientCertificateRequestType.RequestAndRequireAndVerify); + + // Force GC collection to verify that the VerifyPeerCallback is not collected. If + // it gets collected, this test will hang. + GC.Collect(); + + client.UnaryCall(new SimpleRequest { ResponseSize = 10 }); + Assert.IsTrue(isHostEqual); + Assert.IsTrue(isPemEqual); + } + + [Test] + public void VerifyPeerCallbackFailTest() + { + InitClientAndServer(true, SslClientCertificateRequestType.RequestAndRequireAndVerify); + var clientCredentials = new SslCredentials(rootCert, keyCertPair, context => this.VerifyPeerCallback(context, false)); + var failingChannel = new Channel(Host, server.Ports.Single().BoundPort, clientCredentials, options); + var failingClient = new TestService.TestServiceClient(failingChannel); + Assert.Throws(() => failingClient.UnaryCall(new SimpleRequest { ResponseSize = 10 })); + } + + private bool VerifyPeerCallback(VerifyPeerContext context, bool returnValue) + { + isHostEqual = TestCredentials.DefaultHostOverride == context.TargetHost; + isPemEqual = certChain == context.TargetPem; + return returnValue; + } + private class SslCredentialsTestServiceImpl : TestService.TestServiceBase { public override Task UnaryCall(SimpleRequest request, ServerCallContext context) diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index dc690a6a608..5f80d3417a5 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -927,20 +927,53 @@ grpcsharp_override_default_ssl_roots(const char* pem_root_certs) { grpc_set_ssl_roots_override_callback(override_ssl_roots_handler); } +typedef int(GPR_CALLTYPE* grpcsharp_verify_peer_func)(const char* target_host, + const char* target_pem, + void* userdata, + int32_t isDestroy); + +static void grpcsharp_verify_peer_destroy_handler(void* userdata) { + grpcsharp_verify_peer_func callback = + (grpcsharp_verify_peer_func)(intptr_t)userdata; + callback(NULL, NULL, NULL, 1); +} + +static int grpcsharp_verify_peer_handler(const char* target_host, + const char* target_pem, + void* userdata) { + grpcsharp_verify_peer_func callback = + (grpcsharp_verify_peer_func)(intptr_t)userdata; + return callback(target_host, target_pem, NULL, 0); +} + + GPR_EXPORT grpc_channel_credentials* GPR_CALLTYPE grpcsharp_ssl_credentials_create(const char* pem_root_certs, const char* key_cert_pair_cert_chain, - const char* key_cert_pair_private_key) { + const char* key_cert_pair_private_key, + grpcsharp_verify_peer_func verify_peer_func) { grpc_ssl_pem_key_cert_pair key_cert_pair; + verify_peer_options verify_options; + verify_peer_options* p_verify_options = NULL; + if (verify_peer_func != NULL) { + verify_options.verify_peer_callback_userdata = + (void*)(intptr_t)verify_peer_func; + verify_options.verify_peer_destruct = + grpcsharp_verify_peer_destroy_handler; + verify_options.verify_peer_callback = grpcsharp_verify_peer_handler; + p_verify_options = &verify_options; + } + if (key_cert_pair_cert_chain || key_cert_pair_private_key) { key_cert_pair.cert_chain = key_cert_pair_cert_chain; key_cert_pair.private_key = key_cert_pair_private_key; - return grpc_ssl_credentials_create(pem_root_certs, &key_cert_pair, NULL, - NULL); + return grpc_ssl_credentials_create(pem_root_certs, &key_cert_pair, + p_verify_options, NULL); } else { GPR_ASSERT(!key_cert_pair_cert_chain); GPR_ASSERT(!key_cert_pair_private_key); - return grpc_ssl_credentials_create(pem_root_certs, NULL, NULL, NULL); + return grpc_ssl_credentials_create(pem_root_certs, NULL, p_verify_options, + NULL); } } diff --git a/templates/src/csharp/Grpc.Core/Internal/native_methods.include b/templates/src/csharp/Grpc.Core/Internal/native_methods.include index b7a8e285488..4cb71730529 100644 --- a/templates/src/csharp/Grpc.Core/Internal/native_methods.include +++ b/templates/src/csharp/Grpc.Core/Internal/native_methods.include @@ -44,7 +44,7 @@ native_method_signatures = [ 'void grpcsharp_channel_args_set_integer(ChannelArgsSafeHandle args, UIntPtr index, string key, int value)', 'void grpcsharp_channel_args_destroy(IntPtr args)', 'void grpcsharp_override_default_ssl_roots(string pemRootCerts)', - 'ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey)', + 'ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, VerifyPeerCallbackInternal verifyPeerCallback)', 'ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds)', 'void grpcsharp_channel_credentials_release(IntPtr credentials)', 'ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs)', From 9a41671cb10e645dd490fdf3d3b7c7345e105d81 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Thu, 21 Mar 2019 14:22:06 -0700 Subject: [PATCH 039/242] Remove grpc:: from API to ensure general availability --- test/cpp/ext/filters/census/stats_plugin_end2end_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc b/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc index 1b40ca42254..0638c3343e6 100644 --- a/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc +++ b/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc @@ -59,7 +59,7 @@ class EchoServer final : public EchoTestService::Service { class StatsPluginEnd2EndTest : public ::testing::Test { protected: - static void SetUpTestCase() { grpc::RegisterOpenCensusPlugin(); } + static void SetUpTestCase() { RegisterOpenCensusPlugin(); } void SetUp() { // Set up a synchronous server on a different thread to avoid the asynch From 4260fe1147240cd8ceb6bc4a2c292f6a1e5e9c96 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Thu, 21 Mar 2019 17:51:28 -0700 Subject: [PATCH 040/242] More fixes --- src/cpp/ext/filters/census/grpc_plugin.h | 7 ++----- test/cpp/microbenchmarks/bm_opencensus_plugin.cc | 7 +++++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cpp/ext/filters/census/grpc_plugin.h b/src/cpp/ext/filters/census/grpc_plugin.h index 209fad139ce..993faae0a94 100644 --- a/src/cpp/ext/filters/census/grpc_plugin.h +++ b/src/cpp/ext/filters/census/grpc_plugin.h @@ -22,14 +22,11 @@ #include #include "absl/strings/string_view.h" -#include "include/grpcpp/opencensus_impl.h" +#include "include/grpcpp/opencensus.h" #include "opencensus/stats/stats.h" -namespace grpc_impl { - -class ServerContext; -} namespace grpc { +class ServerContext; // The tag keys set when recording RPC stats. ::opencensus::stats::TagKey ClientMethodTagKey(); diff --git a/test/cpp/microbenchmarks/bm_opencensus_plugin.cc b/test/cpp/microbenchmarks/bm_opencensus_plugin.cc index c3fa6f3031a..0b376c0a0c3 100644 --- a/test/cpp/microbenchmarks/bm_opencensus_plugin.cc +++ b/test/cpp/microbenchmarks/bm_opencensus_plugin.cc @@ -29,9 +29,12 @@ #include "src/proto/grpc/testing/echo.grpc.pb.h" #include "test/cpp/microbenchmarks/helpers.h" +using ::grpc::RegisterOpenCensusPlugin; +using ::grpc::RegisterOpenCensusViewsForExport; + absl::once_flag once; void RegisterOnce() { - absl::call_once(once, grpc::RegisterOpenCensusPlugin); + absl::call_once(once, RegisterOpenCensusPlugin); } class EchoServer final : public grpc::testing::EchoTestService::Service { @@ -102,7 +105,7 @@ static void BM_E2eLatencyCensusEnabled(benchmark::State& state) { RegisterOnce(); // This we can safely repeat, and doing so clears accumulated data to avoid // initialization costs varying between runs. - grpc::RegisterOpenCensusViewsForExport(); + RegisterOpenCensusViewsForExport(); EchoServerThread server; std::unique_ptr stub = From d93959853f45d7e0725030a3ca6bd9f341ba6255 Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Thu, 21 Mar 2019 18:00:48 -0700 Subject: [PATCH 041/242] Enabled Windows Bazel build for cpp tests --- bazel/BUILD | 13 ++++++++ bazel/grpc_build_system.bzl | 31 ++++++++++++++++--- test/core/bad_connection/BUILD | 1 + test/core/client_channel/BUILD | 1 + test/core/end2end/generate_tests.bzl | 23 +++++++++++--- test/core/iomgr/BUILD | 10 ++++++ test/cpp/common/BUILD | 1 + test/cpp/end2end/BUILD | 2 ++ test/cpp/interop/BUILD | 1 + test/cpp/microbenchmarks/BUILD | 18 +++++++++++ .../generate_resolver_component_tests.bzl | 5 ++- test/cpp/performance/BUILD | 1 + test/cpp/qps/qps_benchmark_script.bzl | 1 + test/cpp/server/BUILD | 3 ++ test/cpp/server/load_reporter/BUILD | 1 + .../cpp/thread_manager/thread_manager_test.cc | 3 +- tools/remote_build/README.md | 6 ++++ tools/remote_build/windows.bazelrc | 3 ++ 18 files changed, 113 insertions(+), 11 deletions(-) create mode 100644 tools/remote_build/windows.bazelrc diff --git a/bazel/BUILD b/bazel/BUILD index 32402892cc3..4b581709f20 100644 --- a/bazel/BUILD +++ b/bazel/BUILD @@ -29,3 +29,16 @@ cc_grpc_library( proto_only = True, deps = [], ) + +environment(name = "windows_msvc") + +environment(name = "non_windows_msvc") + +environment_group( + name = "os", + defaults = [":non_windows_msvc"], + environments = [ + ":non_windows_msvc", + ":windows_msvc", + ], +) diff --git a/bazel/grpc_build_system.bzl b/bazel/grpc_build_system.bzl index 2a09022c64c..a2f3c200fa7 100644 --- a/bazel/grpc_build_system.bzl +++ b/bazel/grpc_build_system.bzl @@ -28,6 +28,12 @@ load("//bazel:cc_grpc_library.bzl", "cc_grpc_library") # The set of pollers to test against if a test exercises polling POLLERS = ["epollex", "epoll1", "poll"] +def is_msvc(): + return select({ + "//:windows_msvc": True, + "//conditions:default": False, + }) + def if_not_windows(a): return select({ "//:windows": [], @@ -80,7 +86,8 @@ def grpc_cc_library( visibility = None, alwayslink = 0, data = [], - use_cfstream = False): + use_cfstream = False, + tags = []): copts = [] if use_cfstream: copts = if_mac(["-DGRPC_CFSTREAM"]) @@ -117,6 +124,7 @@ def grpc_cc_library( ], alwayslink = alwayslink, data = data, + tags = tags, ) def grpc_proto_plugin(name, srcs = [], deps = []): @@ -159,9 +167,23 @@ def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data "size": size, "timeout": timeout, "exec_compatible_with": exec_compatible_with, + "tags": tags, } if uses_polling: - native.cc_test(testonly = True, tags = ["manual"], **args) + native.cc_test( + testonly = True, + tags = (["manual"] if not is_msvc() else tags), + name = name, + srcs = srcs, + args = args["args"], + data = data, + deps = deps + _get_external_deps(external_deps), + copts = copts, + linkopts = if_not_windows(["-pthread"]), + size = size, + timeout = timeout, + exec_compatible_with = exec_compatible_with, + ) for poller in POLLERS: native.sh_test( name = name + "@poller=" + poller, @@ -175,13 +197,13 @@ def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data poller, "$(location %s)" % name, ] + args["args"], - tags = tags, + tags = tags if is_msvc() else tags + ["no_windows"], exec_compatible_with = exec_compatible_with, ) else: native.cc_test(**args) -def grpc_cc_binary(name, srcs = [], deps = [], external_deps = [], args = [], data = [], language = "C++", testonly = False, linkshared = False, linkopts = []): +def grpc_cc_binary(name, srcs = [], deps = [], external_deps = [], args = [], data = [], language = "C++", testonly = False, linkshared = False, linkopts = [], tags = []): copts = [] if language.upper() == "C": copts = ["-std=c99"] @@ -195,6 +217,7 @@ def grpc_cc_binary(name, srcs = [], deps = [], external_deps = [], args = [], da deps = deps + _get_external_deps(external_deps), copts = copts, linkopts = if_not_windows(["-pthread"]) + linkopts, + tags = tags, ) def grpc_generate_one_off_targets(): diff --git a/test/core/bad_connection/BUILD b/test/core/bad_connection/BUILD index 8ada933e796..82b38ccc469 100644 --- a/test/core/bad_connection/BUILD +++ b/test/core/bad_connection/BUILD @@ -29,4 +29,5 @@ grpc_cc_binary( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) diff --git a/test/core/client_channel/BUILD b/test/core/client_channel/BUILD index 57e5191af4c..68a71632daf 100644 --- a/test/core/client_channel/BUILD +++ b/test/core/client_channel/BUILD @@ -52,6 +52,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index 79c079bcc73..8020780a909 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -15,7 +15,7 @@ """Generates the appropriate build.json data for all the end2end tests.""" -load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library") +load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "is_msvc") POLLERS = ["epollex", "epoll1", "poll"] @@ -31,7 +31,8 @@ def _fixture_options( is_http2 = True, supports_proxy_auth = False, supports_write_buffering = True, - client_channel = True): + client_channel = True, + supports_msvc = True): return struct( fullstack = fullstack, includes_proxy = includes_proxy, @@ -44,6 +45,7 @@ def _fixture_options( supports_proxy_auth = supports_proxy_auth, supports_write_buffering = supports_write_buffering, client_channel = client_channel, + supports_msvc = supports_msvc, #_platforms=_platforms, ) @@ -120,10 +122,11 @@ END2END_NOSEC_FIXTURES = { client_channel = False, secure = False, _platforms = ["linux", "mac", "posix"], + supports_msvc = False, ), "h2_full": _fixture_options(secure = False), - "h2_full+pipe": _fixture_options(secure = False, _platforms = ["linux"]), - "h2_full+trace": _fixture_options(secure = False, tracing = True), + "h2_full+pipe": _fixture_options(secure = False, _platforms = ["linux"], supports_msvc = False), + "h2_full+trace": _fixture_options(secure = False, tracing = True, supports_msvc = False), "h2_full+workarounds": _fixture_options(secure = False), "h2_http_proxy": _fixture_options(secure = False, supports_proxy_auth = True), "h2_proxy": _fixture_options(secure = False, includes_proxy = True), @@ -152,6 +155,7 @@ END2END_NOSEC_FIXTURES = { dns_resolver = False, _platforms = ["linux", "mac", "posix"], secure = False, + supports_msvc = False, ), } @@ -453,6 +457,16 @@ def grpc_end2end_nosec_tests(): continue if topt.secure: continue + native.sh_test( + name = "%s_nosec_test@%s" % (f, t), + data = [":%s_nosec_test" % f], + srcs = ["end2end_test.sh"], + args = [ + "$(location %s_nosec_test)" % f, + t, + ], + tags = ["no_windows"], + ) for poller in POLLERS: native.sh_test( name = "%s_nosec_test@%s@poller=%s" % (f, t, poller), @@ -463,4 +477,5 @@ def grpc_end2end_nosec_tests(): t, poller, ], + tags = ["no_windows"], ) diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD index 5e4338aee37..1aefa0ab224 100644 --- a/test/core/iomgr/BUILD +++ b/test/core/iomgr/BUILD @@ -81,6 +81,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -92,6 +93,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -103,6 +105,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -139,6 +142,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -153,6 +157,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -214,6 +219,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -225,6 +231,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -237,6 +244,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -259,6 +267,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -303,4 +312,5 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) diff --git a/test/cpp/common/BUILD b/test/cpp/common/BUILD index 01699b26add..b67c1995ff7 100644 --- a/test/cpp/common/BUILD +++ b/test/cpp/common/BUILD @@ -28,6 +28,7 @@ grpc_cc_test( "//:grpc++_unsecure", "//test/core/util:grpc_test_util_unsecure", ], + tags = ["no_windows"], ) grpc_cc_test( diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD index 998ba8e1e4e..707a628148e 100644 --- a/test/cpp/end2end/BUILD +++ b/test/cpp/end2end/BUILD @@ -99,6 +99,7 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -633,6 +634,7 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], + tags = ["no_windows"], ) grpc_cc_test( diff --git a/test/cpp/interop/BUILD b/test/cpp/interop/BUILD index f36494d98db..6cf4719c17b 100644 --- a/test/cpp/interop/BUILD +++ b/test/cpp/interop/BUILD @@ -161,4 +161,5 @@ grpc_cc_test( "//test/cpp/util:test_config", "//test/cpp/util:test_util", ], + tags = ["no_windows"], ) diff --git a/test/cpp/microbenchmarks/BUILD b/test/cpp/microbenchmarks/BUILD index 70b4000780c..6e844a6dc62 100644 --- a/test/cpp/microbenchmarks/BUILD +++ b/test/cpp/microbenchmarks/BUILD @@ -45,6 +45,7 @@ grpc_cc_library( "//test/core/util:grpc_test_util_unsecure", "//test/cpp/util:test_config", ], + tags = ["no_windows"], ) grpc_cc_binary( @@ -52,6 +53,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_closure.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -59,6 +61,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_alarm.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -66,6 +69,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_arena.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -73,6 +77,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_byte_buffer.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -80,6 +85,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_channel.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -87,6 +93,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_call_create.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -94,6 +101,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_cq.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -101,6 +109,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_cq_multiple_threads.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -108,6 +117,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_error.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_library( @@ -117,6 +127,7 @@ grpc_cc_library( "fullstack_streaming_ping_pong.h", ], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -126,6 +137,7 @@ grpc_cc_binary( "bm_fullstack_streaming_ping_pong.cc", ], deps = [":fullstack_streaming_ping_pong_h"], + tags = ["no_windows"], ) grpc_cc_library( @@ -144,6 +156,7 @@ grpc_cc_binary( "bm_fullstack_streaming_pump.cc", ], deps = [":fullstack_streaming_pump_h"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -151,6 +164,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_fullstack_trickle.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_library( @@ -169,6 +183,7 @@ grpc_cc_binary( "bm_fullstack_unary_ping_pong.cc", ], deps = [":fullstack_unary_ping_pong_h"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -176,6 +191,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_metadata.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -183,6 +199,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_chttp2_hpack.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -202,4 +219,5 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_timer.cc"], deps = [":helpers"], + tags = ["no_windows"], ) diff --git a/test/cpp/naming/generate_resolver_component_tests.bzl b/test/cpp/naming/generate_resolver_component_tests.bzl index f36021560c1..589176762e6 100755 --- a/test/cpp/naming/generate_resolver_component_tests.bzl +++ b/test/cpp/naming/generate_resolver_component_tests.bzl @@ -33,6 +33,7 @@ def generate_resolver_component_tests(): "//:gpr", "//test/cpp/util:test_config", ], + tags = ["no_windows"], ) # meant to be invoked only through the top-level shell script driver grpc_cc_binary( @@ -52,6 +53,7 @@ def generate_resolver_component_tests(): "//:gpr", "//test/cpp/util:test_config", ], + tags = ["no_windows"], ) grpc_cc_test( name = "resolver_component_tests_runner_invoker%s" % unsecure_build_config_suffix, @@ -77,5 +79,6 @@ def generate_resolver_component_tests(): args = [ "--test_bin_name=resolver_component_test%s" % unsecure_build_config_suffix, "--running_under_bazel=true", - ] + ], + tags = ["no_windows"], ) diff --git a/test/cpp/performance/BUILD b/test/cpp/performance/BUILD index 4fe95d5905e..6068c33f95f 100644 --- a/test/cpp/performance/BUILD +++ b/test/cpp/performance/BUILD @@ -31,4 +31,5 @@ grpc_cc_test( "//src/proto/grpc/testing:echo_proto", "//test/core/util:grpc_test_util_base", ], + tags = ["no_windows"], ) diff --git a/test/cpp/qps/qps_benchmark_script.bzl b/test/cpp/qps/qps_benchmark_script.bzl index 855caa0d37c..b4767ec8e09 100644 --- a/test/cpp/qps/qps_benchmark_script.bzl +++ b/test/cpp/qps/qps_benchmark_script.bzl @@ -75,5 +75,6 @@ def json_run_localhost_batch(): ], tags = [ "json_run_localhost", + "no_windows", ], ) diff --git a/test/cpp/server/BUILD b/test/cpp/server/BUILD index 050b83f5c4f..a4811031691 100644 --- a/test/cpp/server/BUILD +++ b/test/cpp/server/BUILD @@ -29,6 +29,7 @@ grpc_cc_test( "//src/proto/grpc/testing:echo_proto", "//test/core/util:grpc_test_util_unsecure", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -42,6 +43,7 @@ grpc_cc_test( "//src/proto/grpc/testing:echo_proto", "//test/core/util:grpc_test_util_unsecure", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -55,4 +57,5 @@ grpc_cc_test( "//src/proto/grpc/testing:echo_proto", "//test/core/util:grpc_test_util_unsecure", ], + tags = ["no_windows"], ) diff --git a/test/cpp/server/load_reporter/BUILD b/test/cpp/server/load_reporter/BUILD index 8d876c56d29..db5c93263ad 100644 --- a/test/cpp/server/load_reporter/BUILD +++ b/test/cpp/server/load_reporter/BUILD @@ -45,6 +45,7 @@ grpc_cc_test( "//:lb_server_load_reporting_filter", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( diff --git a/test/cpp/thread_manager/thread_manager_test.cc b/test/cpp/thread_manager/thread_manager_test.cc index 99de5a3e010..ee7252bf78d 100644 --- a/test/cpp/thread_manager/thread_manager_test.cc +++ b/test/cpp/thread_manager/thread_manager_test.cc @@ -21,13 +21,12 @@ #include #include -#include #include #include #include -#include "src/cpp/thread_manager/thread_manager.h" #include "test/cpp/util/test_config.h" +#include "src/cpp/thread_manager/thread_manager.h" namespace grpc { diff --git a/tools/remote_build/README.md b/tools/remote_build/README.md index 19739e9ee12..8a236973946 100644 --- a/tools/remote_build/README.md +++ b/tools/remote_build/README.md @@ -29,5 +29,11 @@ Sanitizer runs (asan, msan, tsan, ubsan): bazel --bazelrc=tools/remote_build/manual.bazelrc test --config=asan //test/... ``` +Run on Windows MSVC: +``` +# local manual run only for C++ targets (RBE to be supported) +bazel --bazelrc=tools/remote_build/windows.bazelrc test //test/cpp/... +``` + Available command line options can be found in [Bazel command line reference](https://docs.bazel.build/versions/master/command-line-reference.html) diff --git a/tools/remote_build/windows.bazelrc b/tools/remote_build/windows.bazelrc new file mode 100644 index 00000000000..70575372d02 --- /dev/null +++ b/tools/remote_build/windows.bazelrc @@ -0,0 +1,3 @@ +# TODO(yfen): Merge with rbe_common.bazelrc and enable Windows RBE +build --test_tag_filters=-no_windows +build --build_tag_filters=-no_windows From ecfc107f32d659e6a90b280b8dcce31586410536 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Thu, 21 Mar 2019 18:40:00 -0700 Subject: [PATCH 042/242] Make more changes to remove grpc qualifier from tests --- include/grpcpp/security/server_credentials.h | 27 ++++++++++++++++- .../grpcpp/security/server_credentials_impl.h | 29 ++----------------- src/cpp/server/secure_server_credentials.cc | 2 +- test/cpp/util/grpc_tool_test.cc | 2 +- test/cpp/util/test_credentials_provider.cc | 3 +- 5 files changed, 32 insertions(+), 31 deletions(-) diff --git a/include/grpcpp/security/server_credentials.h b/include/grpcpp/security/server_credentials.h index f1318b6fb0d..484671ea63d 100644 --- a/include/grpcpp/security/server_credentials.h +++ b/include/grpcpp/security/server_credentials.h @@ -24,7 +24,32 @@ namespace grpc { typedef ::grpc_impl::ServerCredentials ServerCredentials; -typedef ::grpc_impl::SslServerCredentialsOptions SslServerCredentialsOptions; + +/// Options to create ServerCredentials with SSL +struct SslServerCredentialsOptions { + /// \warning Deprecated + SslServerCredentialsOptions() + : force_client_auth(false), + client_certificate_request(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE) {} + SslServerCredentialsOptions( + grpc_ssl_client_certificate_request_type request_type) + : force_client_auth(false), client_certificate_request(request_type) {} + + struct PemKeyCertPair { + grpc::string private_key; + grpc::string cert_chain; + }; + grpc::string pem_root_certs; + std::vector pem_key_cert_pairs; + /// \warning Deprecated + bool force_client_auth; + + /// If both \a force_client_auth and \a client_certificate_request + /// fields are set, \a force_client_auth takes effect, i.e. + /// \a REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY + /// will be enforced. + grpc_ssl_client_certificate_request_type client_certificate_request; +}; static inline std::shared_ptr SslServerCredentials( const SslServerCredentialsOptions& options) { diff --git a/include/grpcpp/security/server_credentials_impl.h b/include/grpcpp/security/server_credentials_impl.h index f78de305f26..dbd194e402a 100644 --- a/include/grpcpp/security/server_credentials_impl.h +++ b/include/grpcpp/security/server_credentials_impl.h @@ -31,6 +31,7 @@ struct grpc_server; namespace grpc { class Server; +struct SslServerCredentialsOptions; } // namespace grpc namespace grpc_impl { @@ -56,35 +57,9 @@ class ServerCredentials { grpc_server* server) = 0; }; -/// Options to create ServerCredentials with SSL -struct SslServerCredentialsOptions { - /// \warning Deprecated - SslServerCredentialsOptions() - : force_client_auth(false), - client_certificate_request(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE) {} - SslServerCredentialsOptions( - grpc_ssl_client_certificate_request_type request_type) - : force_client_auth(false), client_certificate_request(request_type) {} - - struct PemKeyCertPair { - grpc::string private_key; - grpc::string cert_chain; - }; - grpc::string pem_root_certs; - std::vector pem_key_cert_pairs; - /// \warning Deprecated - bool force_client_auth; - - /// If both \a force_client_auth and \a client_certificate_request - /// fields are set, \a force_client_auth takes effect, i.e. - /// \a REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY - /// will be enforced. - grpc_ssl_client_certificate_request_type client_certificate_request; -}; - /// Builds SSL ServerCredentials given SSL specific options std::shared_ptr SslServerCredentials( - const SslServerCredentialsOptions& options); + const grpc::SslServerCredentialsOptions& options); /// Builds insecure server credentials. std::shared_ptr InsecureServerCredentials(); diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc index fc23ba25d6f..f2219fb2972 100644 --- a/src/cpp/server/secure_server_credentials.cc +++ b/src/cpp/server/secure_server_credentials.cc @@ -111,7 +111,7 @@ void SecureServerCredentials::SetAuthMetadataProcessor( } std::shared_ptr SslServerCredentials( - const SslServerCredentialsOptions& options) { + const grpc::SslServerCredentialsOptions& options) { std::vector pem_key_cert_pairs; for (auto key_cert_pair = options.pem_key_cert_pairs.begin(); key_cert_pair != options.pem_key_cert_pairs.end(); key_cert_pair++) { diff --git a/test/cpp/util/grpc_tool_test.cc b/test/cpp/util/grpc_tool_test.cc index 5707e6b85fa..57cdbeb7b76 100644 --- a/test/cpp/util/grpc_tool_test.cc +++ b/test/cpp/util/grpc_tool_test.cc @@ -246,7 +246,7 @@ class GrpcToolTest : public ::testing::Test { SslServerCredentialsOptions ssl_opts; ssl_opts.pem_root_certs = ""; ssl_opts.pem_key_cert_pairs.push_back(pkcp); - creds = grpc::SslServerCredentials(ssl_opts); + creds = SslServerCredentials(ssl_opts); } else { creds = InsecureServerCredentials(); } diff --git a/test/cpp/util/test_credentials_provider.cc b/test/cpp/util/test_credentials_provider.cc index f08b0c2294b..49688e5cf9b 100644 --- a/test/cpp/util/test_credentials_provider.cc +++ b/test/cpp/util/test_credentials_provider.cc @@ -24,6 +24,7 @@ #include #include +#include #include "test/core/end2end/data/ssl_test_data.h" @@ -91,7 +92,7 @@ class DefaultCredentialsProvider : public CredentialsProvider { SslServerCredentialsOptions ssl_opts; ssl_opts.pem_root_certs = ""; ssl_opts.pem_key_cert_pairs.push_back(pkcp); - return grpc::SslServerCredentials(ssl_opts); + return SslServerCredentials(ssl_opts); } else { std::unique_lock lock(mu_); auto it(std::find(added_secure_type_names_.begin(), From f26ef91c98c6f3c917b3eaec0f388b2c13c85c77 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 22 Mar 2019 08:26:10 -0700 Subject: [PATCH 043/242] Convert external connectivity watcher to C++. --- .../filters/client_channel/client_channel.cc | 320 ++++++++++-------- 1 file changed, 180 insertions(+), 140 deletions(-) diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 891df3baf6b..b6a9e83d33b 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -50,6 +50,7 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/manual_constructor.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/polling_entity.h" @@ -91,7 +92,53 @@ grpc_core::TraceFlag grpc_client_channel_routing_trace( * CHANNEL-WIDE FUNCTIONS */ -struct external_connectivity_watcher; +// Forward declaration. +typedef struct client_channel_channel_data channel_data; + +namespace grpc_core { +namespace { + +class ExternalConnectivityWatcher { + public: + class WatcherList { + public: + WatcherList() { gpr_mu_init(&mu_); } + ~WatcherList() { gpr_mu_destroy(&mu_); } + + int size() const; + ExternalConnectivityWatcher* Lookup(grpc_closure* on_complete) const; + void Append(ExternalConnectivityWatcher* watcher); + void Remove(ExternalConnectivityWatcher* watcher); + + private: + // head_ is guarded by its own mutex, since the size of the list needs + // to be grabbed immediately without polling on a CQ. + mutable gpr_mu mu_; + ExternalConnectivityWatcher* head_ = nullptr; + }; + + ExternalConnectivityWatcher(channel_data* chand, grpc_polling_entity pollent, + grpc_connectivity_state* state, + grpc_closure* on_complete, + grpc_closure* watcher_timer_init); + + ~ExternalConnectivityWatcher(); + + private: + static void OnExternalWatchCompleteLocked(void* arg, grpc_error* error); + static void WatchConnectivityStateLocked(void* arg, grpc_error* ignored); + + channel_data* chand_; + grpc_polling_entity pollent_; + grpc_connectivity_state* state_; + grpc_closure* on_complete_; + grpc_closure* watcher_timer_init_; + grpc_closure my_closure_; + ExternalConnectivityWatcher* next_ = nullptr; +}; + +} // namespace +} // namespace grpc_core struct QueuedPick { LoadBalancingPolicy::PickArgs pick; @@ -99,7 +146,7 @@ struct QueuedPick { QueuedPick* next = nullptr; }; -typedef struct client_channel_channel_data { +struct client_channel_channel_data { bool deadline_checking_enabled; bool enable_retries; size_t per_rpc_retry_buffer_size; @@ -139,11 +186,10 @@ typedef struct client_channel_channel_data { grpc_connectivity_state_tracker state_tracker; grpc_error* disconnect_error; - /* external_connectivity_watcher_list head is guarded by its own mutex, since - * counts need to be grabbed immediately without polling on a cq */ - gpr_mu external_connectivity_watcher_list_mu; - struct external_connectivity_watcher* external_connectivity_watcher_list_head; -} channel_data; + grpc_core::ManualConstructor< + grpc_core::ExternalConnectivityWatcher::WatcherList> + external_connectivity_watcher_list; +}; // Forward declarations. static void start_pick_locked(void* arg, grpc_error* ignored); @@ -191,6 +237,124 @@ static void set_connectivity_state_and_picker_locked( namespace grpc_core { namespace { +// +// ExternalConnectivityWatcher::WatcherList +// + +int ExternalConnectivityWatcher::WatcherList::size() const { + MutexLock lock(&mu_); + int count = 0; + for (ExternalConnectivityWatcher* w = head_; w != nullptr; w = w->next_) { + ++count; + } + return count; +} + +ExternalConnectivityWatcher* ExternalConnectivityWatcher::WatcherList::Lookup( + grpc_closure* on_complete) const { + MutexLock lock(&mu_); + ExternalConnectivityWatcher* w = head_; + while (w != nullptr && w->on_complete_ != on_complete) { + w = w->next_; + } + return w; +} + +void ExternalConnectivityWatcher::WatcherList::Append( + ExternalConnectivityWatcher* watcher) { + GPR_ASSERT(!Lookup(watcher->on_complete_)); + MutexLock lock(&mu_); + GPR_ASSERT(watcher->next_ == nullptr); + watcher->next_ = head_; + head_ = watcher; +} + +void ExternalConnectivityWatcher::WatcherList::Remove( + ExternalConnectivityWatcher* watcher) { + MutexLock lock(&mu_); + if (watcher == head_) { + head_ = watcher->next_; + return; + } + for (ExternalConnectivityWatcher* w = head_; w != nullptr; w = w->next_) { + if (w->next_ == watcher) { + w->next_ = w->next_->next_; + return; + } + } + GPR_UNREACHABLE_CODE(return ); +} + +// +// ExternalConnectivityWatcher +// + +ExternalConnectivityWatcher::ExternalConnectivityWatcher( + channel_data* chand, grpc_polling_entity pollent, + grpc_connectivity_state* state, grpc_closure* on_complete, + grpc_closure* watcher_timer_init) + : chand_(chand), + pollent_(pollent), + state_(state), + on_complete_(on_complete), + watcher_timer_init_(watcher_timer_init) { + grpc_polling_entity_add_to_pollset_set(&pollent_, chand_->interested_parties); + GRPC_CHANNEL_STACK_REF(chand_->owning_stack, "ExternalConnectivityWatcher"); + GRPC_CLOSURE_SCHED( + GRPC_CLOSURE_INIT(&my_closure_, WatchConnectivityStateLocked, this, + grpc_combiner_scheduler(chand_->combiner)), + GRPC_ERROR_NONE); +} + +ExternalConnectivityWatcher::~ExternalConnectivityWatcher() { + grpc_polling_entity_del_from_pollset_set(&pollent_, + chand_->interested_parties); + GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack, "ExternalConnectivityWatcher"); +} + +void ExternalConnectivityWatcher::OnExternalWatchCompleteLocked( + void* arg, grpc_error* error) { + ExternalConnectivityWatcher* self = + static_cast(arg); + grpc_closure* on_complete = self->on_complete_; + self->chand_->external_connectivity_watcher_list->Remove(self); + Delete(self); + GRPC_CLOSURE_SCHED(on_complete, GRPC_ERROR_REF(error)); +} + +void ExternalConnectivityWatcher::WatchConnectivityStateLocked( + void* arg, grpc_error* ignored) { + ExternalConnectivityWatcher* self = + static_cast(arg); + if (self->state_ == nullptr) { + // Handle cancellation. + GPR_ASSERT(self->watcher_timer_init_ == nullptr); + ExternalConnectivityWatcher* found = + self->chand_->external_connectivity_watcher_list->Lookup( + self->on_complete_); + if (found != nullptr) { + GPR_ASSERT(found->on_complete_ == self->on_complete_); + grpc_connectivity_state_notify_on_state_change( + &found->chand_->state_tracker, nullptr, &found->my_closure_); + } + Delete(self); + return; + } + // New watcher. + self->chand_->external_connectivity_watcher_list->Append(self); + // This assumes that the closure is scheduled on the ExecCtx scheduler + // and that GRPC_CLOSURE_RUN would run the closure immediately. + GRPC_CLOSURE_RUN(self->watcher_timer_init_, GRPC_ERROR_NONE); + GRPC_CLOSURE_INIT(&self->my_closure_, OnExternalWatchCompleteLocked, self, + grpc_combiner_scheduler(self->chand_->combiner)); + grpc_connectivity_state_notify_on_state_change( + &self->chand_->state_tracker, self->state_, &self->my_closure_); +} + +// +// ClientChannelControlHelper +// + class ClientChannelControlHelper : public LoadBalancingPolicy::ChannelControlHelper { public: @@ -402,12 +566,7 @@ static grpc_error* cc_init_channel_elem(grpc_channel_element* elem, "client_channel"); chand->disconnect_error = GRPC_ERROR_NONE; gpr_mu_init(&chand->info_mu); - gpr_mu_init(&chand->external_connectivity_watcher_list_mu); - - gpr_mu_lock(&chand->external_connectivity_watcher_list_mu); - chand->external_connectivity_watcher_list_head = nullptr; - gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu); - + chand->external_connectivity_watcher_list.Init(); chand->owning_stack = args->channel_stack; chand->deadline_checking_enabled = grpc_deadline_checking_enabled(args->channel_args); @@ -515,7 +674,7 @@ static void cc_destroy_channel_elem(grpc_channel_element* elem) { GRPC_ERROR_UNREF(chand->disconnect_error); grpc_connectivity_state_destroy(&chand->state_tracker); gpr_mu_destroy(&chand->info_mu); - gpr_mu_destroy(&chand->external_connectivity_watcher_list_mu); + chand->external_connectivity_watcher_list.Destroy(); } /************************************************************************* @@ -2875,6 +3034,10 @@ const grpc_channel_filter grpc_client_channel_filter = { "client-channel", }; +// +// functions exported to the rest of core +// + void grpc_client_channel_set_channelz_node( grpc_channel_element* elem, grpc_core::channelz::ClientChannelNode* node) { channel_data* chand = static_cast(elem->channel_data); @@ -2914,120 +3077,10 @@ grpc_connectivity_state grpc_client_channel_check_connectivity_state( return out; } -typedef struct external_connectivity_watcher { - channel_data* chand; - grpc_polling_entity pollent; - grpc_closure* on_complete; - grpc_closure* watcher_timer_init; - grpc_connectivity_state* state; - grpc_closure my_closure; - struct external_connectivity_watcher* next; -} external_connectivity_watcher; - -static external_connectivity_watcher* lookup_external_connectivity_watcher( - channel_data* chand, grpc_closure* on_complete) { - gpr_mu_lock(&chand->external_connectivity_watcher_list_mu); - external_connectivity_watcher* w = - chand->external_connectivity_watcher_list_head; - while (w != nullptr && w->on_complete != on_complete) { - w = w->next; - } - gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu); - return w; -} - -static void external_connectivity_watcher_list_append( - channel_data* chand, external_connectivity_watcher* w) { - GPR_ASSERT(!lookup_external_connectivity_watcher(chand, w->on_complete)); - - gpr_mu_lock(&w->chand->external_connectivity_watcher_list_mu); - GPR_ASSERT(!w->next); - w->next = chand->external_connectivity_watcher_list_head; - chand->external_connectivity_watcher_list_head = w; - gpr_mu_unlock(&w->chand->external_connectivity_watcher_list_mu); -} - -static void external_connectivity_watcher_list_remove( - channel_data* chand, external_connectivity_watcher* to_remove) { - GPR_ASSERT( - lookup_external_connectivity_watcher(chand, to_remove->on_complete)); - gpr_mu_lock(&chand->external_connectivity_watcher_list_mu); - if (to_remove == chand->external_connectivity_watcher_list_head) { - chand->external_connectivity_watcher_list_head = to_remove->next; - gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu); - return; - } - external_connectivity_watcher* w = - chand->external_connectivity_watcher_list_head; - while (w != nullptr) { - if (w->next == to_remove) { - w->next = w->next->next; - gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu); - return; - } - w = w->next; - } - GPR_UNREACHABLE_CODE(return ); -} - int grpc_client_channel_num_external_connectivity_watchers( grpc_channel_element* elem) { channel_data* chand = static_cast(elem->channel_data); - int count = 0; - - gpr_mu_lock(&chand->external_connectivity_watcher_list_mu); - external_connectivity_watcher* w = - chand->external_connectivity_watcher_list_head; - while (w != nullptr) { - count++; - w = w->next; - } - gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu); - - return count; -} - -static void on_external_watch_complete_locked(void* arg, grpc_error* error) { - external_connectivity_watcher* w = - static_cast(arg); - grpc_closure* follow_up = w->on_complete; - grpc_polling_entity_del_from_pollset_set(&w->pollent, - w->chand->interested_parties); - GRPC_CHANNEL_STACK_UNREF(w->chand->owning_stack, - "external_connectivity_watcher"); - external_connectivity_watcher_list_remove(w->chand, w); - gpr_free(w); - GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error)); -} - -static void watch_connectivity_state_locked(void* arg, - grpc_error* error_ignored) { - external_connectivity_watcher* w = - static_cast(arg); - external_connectivity_watcher* found = nullptr; - if (w->state != nullptr) { - external_connectivity_watcher_list_append(w->chand, w); - // An assumption is being made that the closure is scheduled on the exec ctx - // scheduler and that GRPC_CLOSURE_RUN would run the closure immediately. - GRPC_CLOSURE_RUN(w->watcher_timer_init, GRPC_ERROR_NONE); - GRPC_CLOSURE_INIT(&w->my_closure, on_external_watch_complete_locked, w, - grpc_combiner_scheduler(w->chand->combiner)); - grpc_connectivity_state_notify_on_state_change(&w->chand->state_tracker, - w->state, &w->my_closure); - } else { - GPR_ASSERT(w->watcher_timer_init == nullptr); - found = lookup_external_connectivity_watcher(w->chand, w->on_complete); - if (found) { - GPR_ASSERT(found->on_complete == w->on_complete); - grpc_connectivity_state_notify_on_state_change( - &found->chand->state_tracker, nullptr, &found->my_closure); - } - grpc_polling_entity_del_from_pollset_set(&w->pollent, - w->chand->interested_parties); - GRPC_CHANNEL_STACK_UNREF(w->chand->owning_stack, - "external_connectivity_watcher"); - gpr_free(w); - } + return chand->external_connectivity_watcher_list->size(); } void grpc_client_channel_watch_connectivity_state( @@ -3035,21 +3088,8 @@ void grpc_client_channel_watch_connectivity_state( grpc_connectivity_state* state, grpc_closure* closure, grpc_closure* watcher_timer_init) { channel_data* chand = static_cast(elem->channel_data); - external_connectivity_watcher* w = - static_cast(gpr_zalloc(sizeof(*w))); - w->chand = chand; - w->pollent = pollent; - w->on_complete = closure; - w->state = state; - w->watcher_timer_init = watcher_timer_init; - grpc_polling_entity_add_to_pollset_set(&w->pollent, - chand->interested_parties); - GRPC_CHANNEL_STACK_REF(w->chand->owning_stack, - "external_connectivity_watcher"); - GRPC_CLOSURE_SCHED( - GRPC_CLOSURE_INIT(&w->my_closure, watch_connectivity_state_locked, w, - grpc_combiner_scheduler(chand->combiner)), - GRPC_ERROR_NONE); + grpc_core::New( + chand, pollent, state, closure, watcher_timer_init); } grpc_core::RefCountedPtr From 61431be32b89b6b1857b525b01b66e6aaede7018 Mon Sep 17 00:00:00 2001 From: billfeng327 Date: Fri, 22 Mar 2019 10:22:59 -0700 Subject: [PATCH 044/242] skipping upb on windows --- BUILD | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/BUILD b/BUILD index 9e052dcf0c2..41ab64193ae 100644 --- a/BUILD +++ b/BUILD @@ -2334,7 +2334,8 @@ grpc_cc_library( ":google_api_upb", ":proto_gen_validate_upb", ":envoy_type_upb", - ] + ], + tags = ["no_windows"], ) grpc_cc_library( @@ -2354,7 +2355,8 @@ grpc_cc_library( deps = [ ":google_api_upb", ":proto_gen_validate_upb" - ] + ], + tags = ["no_windows"], ) grpc_cc_library( @@ -2373,7 +2375,8 @@ grpc_cc_library( ], deps = [ ":google_api_upb", - ] + ], + tags = ["no_windows"], ) grpc_cc_library( @@ -2404,6 +2407,7 @@ grpc_cc_library( external_deps = [ "upb_lib", ], + tags = ["no_windows"], ) grpc_generate_one_off_targets() From 1a09899d3e5c8f7e489a25d92ff0e5f6ae00ec81 Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Fri, 22 Mar 2019 11:18:39 -0700 Subject: [PATCH 045/242] reverted change on thread manager test --- test/cpp/thread_manager/thread_manager_test.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/cpp/thread_manager/thread_manager_test.cc b/test/cpp/thread_manager/thread_manager_test.cc index ee7252bf78d..99de5a3e010 100644 --- a/test/cpp/thread_manager/thread_manager_test.cc +++ b/test/cpp/thread_manager/thread_manager_test.cc @@ -21,12 +21,13 @@ #include #include +#include #include #include #include -#include "test/cpp/util/test_config.h" #include "src/cpp/thread_manager/thread_manager.h" +#include "test/cpp/util/test_config.h" namespace grpc { From d7e5cb70febcdc3f0ec267e2d5b01dc3e152c1d6 Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Fri, 22 Mar 2019 11:27:24 -0700 Subject: [PATCH 046/242] flipped logic for is_msvc() --- bazel/grpc_build_system.bzl | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/bazel/grpc_build_system.bzl b/bazel/grpc_build_system.bzl index a2f3c200fa7..ca87428f375 100644 --- a/bazel/grpc_build_system.bzl +++ b/bazel/grpc_build_system.bzl @@ -167,22 +167,12 @@ def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data "size": size, "timeout": timeout, "exec_compatible_with": exec_compatible_with, - "tags": tags, } if uses_polling: native.cc_test( testonly = True, - tags = (["manual"] if not is_msvc() else tags), - name = name, - srcs = srcs, - args = args["args"], - data = data, - deps = deps + _get_external_deps(external_deps), - copts = copts, - linkopts = if_not_windows(["-pthread"]), - size = size, - timeout = timeout, - exec_compatible_with = exec_compatible_with, + tags = (["manual"] if is_msvc() else tags), + **args ) for poller in POLLERS: native.sh_test( @@ -197,11 +187,11 @@ def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data poller, "$(location %s)" % name, ] + args["args"], - tags = tags if is_msvc() else tags + ["no_windows"], + tags = (tags + ["no_windows"]) if is_msvc() else tags, exec_compatible_with = exec_compatible_with, ) else: - native.cc_test(**args) + native.cc_test(tags = tags, **args) def grpc_cc_binary(name, srcs = [], deps = [], external_deps = [], args = [], data = [], language = "C++", testonly = False, linkshared = False, linkopts = [], tags = []): copts = [] From d16597ab73708b683d6d3b37f0213d343678865b Mon Sep 17 00:00:00 2001 From: billfeng327 Date: Fri, 22 Mar 2019 14:33:37 -0700 Subject: [PATCH 047/242] corrected Bazel target generation logic for Windows --- bazel/grpc_build_system.bzl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bazel/grpc_build_system.bzl b/bazel/grpc_build_system.bzl index ca87428f375..c5eb9ec8bf3 100644 --- a/bazel/grpc_build_system.bzl +++ b/bazel/grpc_build_system.bzl @@ -169,9 +169,11 @@ def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data "exec_compatible_with": exec_compatible_with, } if uses_polling: + # Only run targets with pollers for non-MSVC + # Only run targets without pollers for MSVC native.cc_test( testonly = True, - tags = (["manual"] if is_msvc() else tags), + tags = tags if is_msvc() else ["manual"], **args ) for poller in POLLERS: From be014d005d01575fabd2cb0b580633253025e26f Mon Sep 17 00:00:00 2001 From: Doug Fawley Date: Fri, 22 Mar 2019 14:43:50 -0700 Subject: [PATCH 048/242] Misconfigured non-gRPC, HTTP/2 clients can sometimes connect to gRPC servers. Today, these clients will receive an HTTP status 200 (OK) with a trailer that gRPC clients would be able to interpret as an error, but non-gRPC clients would interpret as a success. In Go and Java, this will have a grpc-status of UNKNOWN due to an unexpected content-type header. In C, the content-type header is currently ignored, but a grpc-status of UNAVAILABLE will be returned if a handler for that method is not registered (which is likely in this scenario). This change updates the gRPC HTTP/2 spec to recommend returning HTTP status 400 (Bad Request) to interoperate better with non-gRPC clients. Note that we should not do any enforcement on user-agent, as the spec specifically says "the protocol does not require a user-agent to function". --- doc/PROTOCOL-HTTP2.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/PROTOCOL-HTTP2.md b/doc/PROTOCOL-HTTP2.md index a354dad8636..6b4d85db30a 100644 --- a/doc/PROTOCOL-HTTP2.md +++ b/doc/PROTOCOL-HTTP2.md @@ -61,6 +61,8 @@ the form shown above. If **Timeout** is omitted a server should assume an infinite timeout. Client implementations are free to send a default minimum timeout based on their deployment requirements. +If **Content-Type** does not begin with "application/grpc", gRPC servers SHOULD respond with HTTP status of 400 (Bad Request). This will prevent other HTTP/2 clients from interpreting a gRPC error response, which uses status 200 (OK), as successful. + **Custom-Metadata** is an arbitrary set of key-value pairs defined by the application layer. Header names starting with "grpc-" but not listed here are reserved for future GRPC use and should not be used by applications as **Custom-Metadata**. Note that HTTP2 does not allow arbitrary octet sequences for header values so binary header values must be encoded using Base64 as per https://tools.ietf.org/html/rfc4648#section-4. Implementations MUST accept padded and un-padded values and should emit un-padded values. Applications define binary headers by having their names end with "-bin". Runtime libraries use this suffix to detect binary headers and properly apply base64 encoding & decoding as headers are sent and received. @@ -255,5 +257,3 @@ to be used. * **Service-Name** → ?( {_proto package name_} "." ) {_service name_} * **Message-Type** → {_fully qualified proto message name_} * **Content-Type** → "application/grpc+proto" - - From f00508e9ce9411e8d02ed444b37ccb15a9a3e10c Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 25 Mar 2019 09:16:09 +1300 Subject: [PATCH 049/242] Add BindServiceAttribute --- src/compiler/csharp_generator.cc | 3 ++ .../Grpc.Core.Api/BindServiceAttribute.cs | 48 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 src/csharp/Grpc.Core.Api/BindServiceAttribute.cs diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index ac0af336f93..c0f6a21c3e0 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -382,6 +382,9 @@ void GenerateServerClass(Printer* out, const ServiceDescriptor* service) { "/// Base class for server-side implementations of " "$servicename$\n", "servicename", GetServiceClassName(service)); + out->Print( + "[grpc::BindService(typeof($classname$), nameof($classname$.BindService))]\n", + "classname", GetServiceClassName(service)); out->Print("public abstract partial class $name$\n", "name", GetServerClassName(service)); out->Print("{\n"); diff --git a/src/csharp/Grpc.Core.Api/BindServiceAttribute.cs b/src/csharp/Grpc.Core.Api/BindServiceAttribute.cs new file mode 100644 index 00000000000..e53f1878b18 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/BindServiceAttribute.cs @@ -0,0 +1,48 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +using System; + +namespace Grpc.Core +{ + /// + /// Defines the location of the service bind method for a gRPC service. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class BindServiceAttribute : Attribute + { + /// + /// Initializes a new instance of the class. + /// + /// The type the service bind method is defined on. + /// The name of the service bind method. + public BindServiceAttribute(Type bindType, string bindMethodName) + { + BindType = bindType; + BindMethodName = bindMethodName; + } + + /// + /// Gets the type the service bind method is defined on. + /// + public Type BindType { get; } + + /// + /// Gets the name of the service bind method. + /// + public string BindMethodName { get; } + } +} From 31ce7a32bb6ab98c4582db21671b7c335724cf29 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 25 Mar 2019 18:39:09 +1300 Subject: [PATCH 050/242] PR feedback --- src/compiler/csharp_generator.cc | 3 ++- src/csharp/Grpc.Core.Api/BindServiceAttribute.cs | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index c0f6a21c3e0..97098714590 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -383,7 +383,8 @@ void GenerateServerClass(Printer* out, const ServiceDescriptor* service) { "$servicename$\n", "servicename", GetServiceClassName(service)); out->Print( - "[grpc::BindService(typeof($classname$), nameof($classname$.BindService))]\n", + "[grpc::BindService(typeof($classname$), " + "nameof($classname$.BindService))]\n", "classname", GetServiceClassName(service)); out->Print("public abstract partial class $name$\n", "name", GetServerClassName(service)); diff --git a/src/csharp/Grpc.Core.Api/BindServiceAttribute.cs b/src/csharp/Grpc.Core.Api/BindServiceAttribute.cs index e53f1878b18..d4ac6a10570 100644 --- a/src/csharp/Grpc.Core.Api/BindServiceAttribute.cs +++ b/src/csharp/Grpc.Core.Api/BindServiceAttribute.cs @@ -19,7 +19,12 @@ using System; namespace Grpc.Core { /// - /// Defines the location of the service bind method for a gRPC service. + /// Specifies the location of the service bind method for a gRPC service. + /// The bind method is typically generated code and is used to register a service's + /// methods with the server on startup. + /// + /// The bind method signature takes a and an optional + /// instance of the service base class, e.g. static void BindService(ServiceBinderBase, GreeterService). /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] public class BindServiceAttribute : Attribute From aa61b5361bae4c67d68b3e334eb4c1532607901d Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 25 Mar 2019 12:10:18 -0400 Subject: [PATCH 051/242] dont use nameof --- src/compiler/csharp_generator.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index 97098714590..682ce59efbf 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -384,7 +384,7 @@ void GenerateServerClass(Printer* out, const ServiceDescriptor* service) { "servicename", GetServiceClassName(service)); out->Print( "[grpc::BindService(typeof($classname$), " - "nameof($classname$.BindService))]\n", + "\"BindService\")]\n", "classname", GetServiceClassName(service)); out->Print("public abstract partial class $name$\n", "name", GetServerClassName(service)); From 30cc99d42cedece1362e9b0c519aecda3116c984 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Mon, 25 Mar 2019 10:43:10 -0700 Subject: [PATCH 052/242] Add Python example for error handling --- examples/python/errors/README.md | 96 +++++++++++++ .../python/errors/error_handling_client.py | 50 +++++++ .../python/errors/error_handling_server.py | 81 +++++++++++ examples/python/errors/helloworld_pb2.py | 134 ++++++++++++++++++ examples/python/errors/helloworld_pb2_grpc.py | 46 ++++++ 5 files changed, 407 insertions(+) create mode 100644 examples/python/errors/README.md create mode 100644 examples/python/errors/error_handling_client.py create mode 100644 examples/python/errors/error_handling_server.py create mode 100644 examples/python/errors/helloworld_pb2.py create mode 100644 examples/python/errors/helloworld_pb2_grpc.py diff --git a/examples/python/errors/README.md b/examples/python/errors/README.md new file mode 100644 index 00000000000..226f0e4a281 --- /dev/null +++ b/examples/python/errors/README.md @@ -0,0 +1,96 @@ +# gRPC Python Error Handling Example + +The goal of this example is sending error status from server that is more complicated than a code and detail string. + +The definition for an RPC method in proto files contains request message and response message. There are many error states that can be shared across RPC methods (e.g. stack trace, insufficient quota). Using a different path to handle error will make the code more maintainable. + +Ideally, the final status of an RPC should be described in the trailing headers of HTTP2, and gRPC Python provides helper functions in `grpcio-status` package to assist the packing and unpacking of error status. + +### Definition of Status Proto + +```proto +// The `Status` type defines a logical error model that is suitable for different +// programming environments, including REST APIs and RPC APIs. It is used by +// [gRPC](https://github.com/grpc). The error model is designed to be: +// +// - Simple to use and understand for most users +// - Flexible enough to meet unexpected needs +// +// # Overview +// +// The `Status` message contains three pieces of data: error code, error message, +// and error details. The error code should be an enum value of +// [google.rpc.Code][google.rpc.Code], but it may accept additional error codes if needed. The +// error message should be a developer-facing English message that helps +// developers *understand* and *resolve* the error. If a localized user-facing +// error message is needed, put the localized message in the error details or +// localize it in the client. The optional error details may contain arbitrary +// information about the error. There is a predefined set of error detail types +// in the package `google.rpc` that can be used for common error conditions. +// +// # Language mapping +// +// The `Status` message is the logical representation of the error model, but it +// is not necessarily the actual wire format. When the `Status` message is +// exposed in different client libraries and different wire protocols, it can be +// mapped differently. For example, it will likely be mapped to some exceptions +// in Java, but more likely mapped to some error codes in C. +// +// # Other uses +// +// The error model and the `Status` message can be used in a variety of +// environments, either with or without APIs, to provide a +// consistent developer experience across different environments. +// +// Example uses of this error model include: +// +// - Partial errors. If a service needs to return partial errors to the client, +// it may embed the `Status` in the normal response to indicate the partial +// errors. +// +// - Workflow errors. A typical workflow has multiple steps. Each step may +// have a `Status` message for error reporting. +// +// - Batch operations. If a client uses batch request and batch response, the +// `Status` message should be used directly inside batch response, one for +// each error sub-response. +// +// - Asynchronous operations. If an API call embeds asynchronous operation +// results in its response, the status of those operations should be +// represented directly using the `Status` message. +// +// - Logging. If some API errors are stored in logs, the message `Status` could +// be used directly after any stripping needed for security/privacy reasons. +message Status { + // The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. + int32 code = 1; + + // A developer-facing error message, which should be in English. Any + // user-facing error message should be localized and sent in the + // [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client. + string message = 2; + + // A list of messages that carry the error details. There is a common set of + // message types for APIs to use. + repeated google.protobuf.Any details = 3; +} +``` + +### Usage of Well-Known-Proto `Any` + +Please check [ProtoBuf Document: Any](https://developers.google.com/protocol-buffers/docs/reference/python-generated#any) + +```Python +any_message.Pack(message) +any_message.Unpack(message) +assert any_message.Is(message.DESCRIPTOR) +``` + +### Common Protos + +These protos are defined by Google Cloud API. Most error cases are covered in `error_dettails.proto`, but you may provide any custom error detail proto you want. + +Please refer to: +* [code.proto](https://github.com/googleapis/api-common-protos/blob/master/google/rpc/code.proto). +* [status.proto](https://github.com/googleapis/api-common-protos/blob/master/google/rpc/status.proto). +* [error_details.proto](https://github.com/googleapis/api-common-protos/blob/master/google/rpc/error_details.proto). diff --git a/examples/python/errors/error_handling_client.py b/examples/python/errors/error_handling_client.py new file mode 100644 index 00000000000..22a865a89bf --- /dev/null +++ b/examples/python/errors/error_handling_client.py @@ -0,0 +1,50 @@ +# Copyright 2019 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""This example handles rich error status in client-side.""" + +from __future__ import print_function +import logging + +import grpc +from grpc_status import rpc_status +from google.rpc import error_details_pb2 + +import helloworld_pb2 +import helloworld_pb2_grpc + + +def run(): + # NOTE(gRPC Python Team): .close() is possible on a channel and should be + # used in circumstances in which the with statement does not fit the needs + # of the code. + with grpc.insecure_channel('localhost:50051') as channel: + stub = helloworld_pb2_grpc.GreeterStub(channel) + try: + response = stub.SayHello(helloworld_pb2.HelloRequest(name='Alice')) + print('Call success:', response.message) + except grpc.RpcError as rpc_error: + print('Call failure:', rpc_error) + status = rpc_status.from_call(rpc_error) + for detail in status.details: + if detail.Is(error_details_pb2.QuotaFailure.DESCRIPTOR): + info = error_details_pb2.QuotaFailure() + detail.Unpack(info) + print('Quota failure:', info) + else: + print('Unexpected failure:', detail) + + +if __name__ == '__main__': + logging.basicConfig() + run() diff --git a/examples/python/errors/error_handling_server.py b/examples/python/errors/error_handling_server.py new file mode 100644 index 00000000000..c782f7d1a2d --- /dev/null +++ b/examples/python/errors/error_handling_server.py @@ -0,0 +1,81 @@ +# Copyright 2019 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""This example sends out rich error status from server-side.""" + +from concurrent import futures +import time +import logging +import threading + +import grpc +from grpc_status import rpc_status + +from google.protobuf import any_pb2 +from google.rpc import code_pb2, status_pb2, error_details_pb2 + +import helloworld_pb2 +import helloworld_pb2_grpc + +_ONE_DAY_IN_SECONDS = 60 * 60 * 24 + + +def create_greet_limit_exceed_error_status(name): + detail = any_pb2.Any() + detail.Pack( + error_details_pb2.QuotaFailure( + violations=[ + error_details_pb2.QuotaFailure.Violation( + subject="name:%s" % name, + description="Limit one greeting per person", + ) + ],)) + return status_pb2.Status( + code=code_pb2.RESOURCE_EXHAUSTED, + message='Request limit exceeded.', + details=[detail], + ) + + +class LimitedGreeter(helloworld_pb2_grpc.GreeterServicer): + + def __init__(self): + self._lock = threading.RLock() + self._greeted = set() + + def SayHello(self, request, context): + with self._lock: + if request.name in self._greeted: + rich_status = create_greet_limit_exceed_error_status( + request.name) + context.abort_with_status(rpc_status.to_status(rich_status)) + else: + self._greeted.add(request.name) + return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name) + + +def serve(): + server = grpc.server(futures.ThreadPoolExecutor()) + helloworld_pb2_grpc.add_GreeterServicer_to_server(LimitedGreeter(), server) + server.add_insecure_port('[::]:50051') + server.start() + try: + while True: + time.sleep(_ONE_DAY_IN_SECONDS) + except KeyboardInterrupt: + server.stop(None) + + +if __name__ == '__main__': + logging.basicConfig() + serve() diff --git a/examples/python/errors/helloworld_pb2.py b/examples/python/errors/helloworld_pb2.py new file mode 100644 index 00000000000..e18ab9acc7a --- /dev/null +++ b/examples/python/errors/helloworld_pb2.py @@ -0,0 +1,134 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: helloworld.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import descriptor_pb2 +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='helloworld.proto', + package='helloworld', + syntax='proto3', + serialized_pb=_b('\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3') +) + + + + +_HELLOREQUEST = _descriptor.Descriptor( + name='HelloRequest', + full_name='helloworld.HelloRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='helloworld.HelloRequest.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=32, + serialized_end=60, +) + + +_HELLOREPLY = _descriptor.Descriptor( + name='HelloReply', + full_name='helloworld.HelloReply', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='message', full_name='helloworld.HelloReply.message', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=62, + serialized_end=91, +) + +DESCRIPTOR.message_types_by_name['HelloRequest'] = _HELLOREQUEST +DESCRIPTOR.message_types_by_name['HelloReply'] = _HELLOREPLY +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +HelloRequest = _reflection.GeneratedProtocolMessageType('HelloRequest', (_message.Message,), dict( + DESCRIPTOR = _HELLOREQUEST, + __module__ = 'helloworld_pb2' + # @@protoc_insertion_point(class_scope:helloworld.HelloRequest) + )) +_sym_db.RegisterMessage(HelloRequest) + +HelloReply = _reflection.GeneratedProtocolMessageType('HelloReply', (_message.Message,), dict( + DESCRIPTOR = _HELLOREPLY, + __module__ = 'helloworld_pb2' + # @@protoc_insertion_point(class_scope:helloworld.HelloReply) + )) +_sym_db.RegisterMessage(HelloReply) + + +DESCRIPTOR.has_options = True +DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW')) + +_GREETER = _descriptor.ServiceDescriptor( + name='Greeter', + full_name='helloworld.Greeter', + file=DESCRIPTOR, + index=0, + options=None, + serialized_start=93, + serialized_end=166, + methods=[ + _descriptor.MethodDescriptor( + name='SayHello', + full_name='helloworld.Greeter.SayHello', + index=0, + containing_service=None, + input_type=_HELLOREQUEST, + output_type=_HELLOREPLY, + options=None, + ), +]) +_sym_db.RegisterServiceDescriptor(_GREETER) + +DESCRIPTOR.services_by_name['Greeter'] = _GREETER + +# @@protoc_insertion_point(module_scope) diff --git a/examples/python/errors/helloworld_pb2_grpc.py b/examples/python/errors/helloworld_pb2_grpc.py new file mode 100644 index 00000000000..18e07d16797 --- /dev/null +++ b/examples/python/errors/helloworld_pb2_grpc.py @@ -0,0 +1,46 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +import grpc + +import helloworld_pb2 as helloworld__pb2 + + +class GreeterStub(object): + """The greeting service definition. + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.SayHello = channel.unary_unary( + '/helloworld.Greeter/SayHello', + request_serializer=helloworld__pb2.HelloRequest.SerializeToString, + response_deserializer=helloworld__pb2.HelloReply.FromString, + ) + + +class GreeterServicer(object): + """The greeting service definition. + """ + + def SayHello(self, request, context): + """Sends a greeting + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_GreeterServicer_to_server(servicer, server): + rpc_method_handlers = { + 'SayHello': grpc.unary_unary_rpc_method_handler( + servicer.SayHello, + request_deserializer=helloworld__pb2.HelloRequest.FromString, + response_serializer=helloworld__pb2.HelloReply.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'helloworld.Greeter', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) From 7a38ddfab4610526c5c58d83a37b0a0463ad65cb Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 25 Mar 2019 13:56:21 -0400 Subject: [PATCH 053/242] run src/csharp/generate_protos.sh --- src/csharp/Grpc.Examples/MathGrpc.cs | 1 + src/csharp/Grpc.HealthCheck/HealthGrpc.cs | 1 + src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs | 1 + src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs | 1 + src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs | 1 + .../Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs | 1 + src/csharp/Grpc.IntegrationTesting/TestGrpc.cs | 3 +++ src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs | 1 + src/csharp/Grpc.Reflection/ReflectionGrpc.cs | 1 + 9 files changed, 11 insertions(+) diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index ba6824dd8e2..8315b2be82e 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -67,6 +67,7 @@ namespace Math { } /// Base class for server-side implementations of Math + [grpc::BindService(typeof(Math), "BindService")] public abstract partial class MathBase { /// diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs index 3edec5a37f8..bc7ae6cedf1 100644 --- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs +++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs @@ -54,6 +54,7 @@ namespace Grpc.Health.V1 { } /// Base class for server-side implementations of Health + [grpc::BindService(typeof(Health), "BindService")] public abstract partial class HealthBase { /// diff --git a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs index 09691d28716..00821bb41bd 100644 --- a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs @@ -74,6 +74,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of BenchmarkService + [grpc::BindService(typeof(BenchmarkService), "BindService")] public abstract partial class BenchmarkServiceBase { /// diff --git a/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs index bfa3348f6a0..20f415f72de 100644 --- a/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs @@ -39,6 +39,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of EmptyService + [grpc::BindService(typeof(EmptyService), "BindService")] public abstract partial class EmptyServiceBase { } diff --git a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs index 27746c07641..6e59d1eb6c1 100644 --- a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs @@ -58,6 +58,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of MetricsService + [grpc::BindService(typeof(MetricsService), "BindService")] public abstract partial class MetricsServiceBase { /// diff --git a/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs index f92ae8e974b..b86dfbf7ec9 100644 --- a/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs @@ -46,6 +46,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of ReportQpsScenarioService + [grpc::BindService(typeof(ReportQpsScenarioService), "BindService")] public abstract partial class ReportQpsScenarioServiceBase { /// diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs index d47b5fe0d4b..c4aa5249ab9 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs @@ -105,6 +105,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of TestService + [grpc::BindService(typeof(TestService), "BindService")] public abstract partial class TestServiceBase { /// @@ -580,6 +581,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of UnimplementedService + [grpc::BindService(typeof(UnimplementedService), "BindService")] public abstract partial class UnimplementedServiceBase { /// @@ -719,6 +721,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of ReconnectService + [grpc::BindService(typeof(ReconnectService), "BindService")] public abstract partial class ReconnectServiceBase { public virtual global::System.Threading.Tasks.Task Start(global::Grpc.Testing.ReconnectParams request, grpc::ServerCallContext context) diff --git a/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs index f7dd2eecf2e..5c079a5ec43 100644 --- a/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs @@ -72,6 +72,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of WorkerService + [grpc::BindService(typeof(WorkerService), "BindService")] public abstract partial class WorkerServiceBase { /// diff --git a/src/csharp/Grpc.Reflection/ReflectionGrpc.cs b/src/csharp/Grpc.Reflection/ReflectionGrpc.cs index 500738205a7..768879bd2a1 100644 --- a/src/csharp/Grpc.Reflection/ReflectionGrpc.cs +++ b/src/csharp/Grpc.Reflection/ReflectionGrpc.cs @@ -46,6 +46,7 @@ namespace Grpc.Reflection.V1Alpha { } /// Base class for server-side implementations of ServerReflection + [grpc::BindService(typeof(ServerReflection), "BindService")] public abstract partial class ServerReflectionBase { /// From f527cfbbac29a88e5a3a89a49a0338f5e7e9e256 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Mon, 25 Mar 2019 12:24:11 -0700 Subject: [PATCH 054/242] Adopt review's advice * Add a unit test * Integrate with Bazel * Polish README.md --- examples/protos/BUILD.bazel | 25 ++++ examples/python/errors/BUILD.bazel | 54 +++++++ examples/python/errors/README.md | 29 ++-- .../{error_handling_client.py => client.py} | 40 +++--- examples/python/errors/helloworld_pb2.py | 134 ------------------ examples/python/errors/helloworld_pb2_grpc.py | 46 ------ .../{error_handling_server.py => server.py} | 21 ++- .../test/_error_handling_example_test.py | 54 +++++++ src/python/grpcio_tests/tests/BUILD.bazel | 1 + 9 files changed, 192 insertions(+), 212 deletions(-) create mode 100644 examples/protos/BUILD.bazel create mode 100644 examples/python/errors/BUILD.bazel rename examples/python/errors/{error_handling_client.py => client.py} (57%) delete mode 100644 examples/python/errors/helloworld_pb2.py delete mode 100644 examples/python/errors/helloworld_pb2_grpc.py rename examples/python/errors/{error_handling_server.py => server.py} (86%) create mode 100644 examples/python/errors/test/_error_handling_example_test.py diff --git a/examples/protos/BUILD.bazel b/examples/protos/BUILD.bazel new file mode 100644 index 00000000000..197274e034c --- /dev/null +++ b/examples/protos/BUILD.bazel @@ -0,0 +1,25 @@ +# Copyright 2019 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@grpc_python_dependencies//:requirements.bzl", "requirement") +load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_library") + +package(default_visibility = ["//visibility:public"]) + +py_proto_library( + name = "py_helloworld_proto", + protos = ["helloworld.proto",], + with_grpc = True, + deps = [requirement('protobuf'),], +) diff --git a/examples/python/errors/BUILD.bazel b/examples/python/errors/BUILD.bazel new file mode 100644 index 00000000000..a2c3534f9bd --- /dev/null +++ b/examples/python/errors/BUILD.bazel @@ -0,0 +1,54 @@ +# Copyright 2019 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@grpc_python_dependencies//:requirements.bzl", "requirement") +load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_library") + +py_library( + name = "client", + testonly = 1, + srcs = ["client.py"], + deps = [ + "//src/python/grpcio/grpc:grpcio", + "//src/python/grpcio_status/grpc_status:grpc_status", + "//examples/protos:py_helloworld_proto", + requirement('googleapis-common-protos'), + ], +) + +py_library( + name = "server", + testonly = 1, + srcs = ["server.py"], + deps = [ + "//src/python/grpcio/grpc:grpcio", + "//src/python/grpcio_status/grpc_status:grpc_status", + "//examples/protos:py_helloworld_proto", + ] + select({ + "//conditions:default": [requirement("futures")], + "//:python3": [], + }), +) + +py_test( + name = "test/_error_handling_example_test", + srcs = ["test/_error_handling_example_test.py"], + data = [ + ":client", + ":server", + "//src/python/grpcio_tests/tests:bazel_namespace_package_hack", + ], + size = "small", + imports = ["../../../src/python/grpcio_status",], +) diff --git a/examples/python/errors/README.md b/examples/python/errors/README.md index 226f0e4a281..3c53690b99c 100644 --- a/examples/python/errors/README.md +++ b/examples/python/errors/README.md @@ -6,8 +6,27 @@ The definition for an RPC method in proto files contains request message and res Ideally, the final status of an RPC should be described in the trailing headers of HTTP2, and gRPC Python provides helper functions in `grpcio-status` package to assist the packing and unpacking of error status. + +### Requirement +``` +grpcio>=1.18.0 +grpcio-status>=1.18.0 +googleapis-common-protos>=1.5.5 +``` + + +### Error Detail Proto + +You may provide any custom proto message as error detail in your implementation. Here are protos are defined by Google Cloud Library Team: + +* [code.proto](https://github.com/googleapis/api-common-protos/blob/master/google/rpc/code.proto) contains definition of RPC error codes. +* [error_details.proto](https://github.com/googleapis/api-common-protos/blob/master/google/rpc/error_details.proto) contains definitions of common error details. + + ### Definition of Status Proto +Here is the definition of Status proto. For full text, please see [status.proto](https://github.com/googleapis/api-common-protos/blob/master/google/rpc/status.proto). + ```proto // The `Status` type defines a logical error model that is suitable for different // programming environments, including REST APIs and RPC APIs. It is used by @@ -76,6 +95,7 @@ message Status { } ``` + ### Usage of Well-Known-Proto `Any` Please check [ProtoBuf Document: Any](https://developers.google.com/protocol-buffers/docs/reference/python-generated#any) @@ -85,12 +105,3 @@ any_message.Pack(message) any_message.Unpack(message) assert any_message.Is(message.DESCRIPTOR) ``` - -### Common Protos - -These protos are defined by Google Cloud API. Most error cases are covered in `error_dettails.proto`, but you may provide any custom error detail proto you want. - -Please refer to: -* [code.proto](https://github.com/googleapis/api-common-protos/blob/master/google/rpc/code.proto). -* [status.proto](https://github.com/googleapis/api-common-protos/blob/master/google/rpc/status.proto). -* [error_details.proto](https://github.com/googleapis/api-common-protos/blob/master/google/rpc/error_details.proto). diff --git a/examples/python/errors/error_handling_client.py b/examples/python/errors/client.py similarity index 57% rename from examples/python/errors/error_handling_client.py rename to examples/python/errors/client.py index 22a865a89bf..a79b8fce1bd 100644 --- a/examples/python/errors/error_handling_client.py +++ b/examples/python/errors/client.py @@ -20,31 +20,37 @@ import grpc from grpc_status import rpc_status from google.rpc import error_details_pb2 -import helloworld_pb2 -import helloworld_pb2_grpc +from examples.protos import helloworld_pb2 +from examples.protos import helloworld_pb2_grpc + +_LOGGER = logging.getLogger(__name__) -def run(): +def process(stub): + try: + response = stub.SayHello(helloworld_pb2.HelloRequest(name='Alice')) + _LOGGER.info('Call success: %s', response.message) + except grpc.RpcError as rpc_error: + _LOGGER.error('Call failure: %s', rpc_error) + status = rpc_status.from_call(rpc_error) + for detail in status.details: + if detail.Is(error_details_pb2.QuotaFailure.DESCRIPTOR): + info = error_details_pb2.QuotaFailure() + detail.Unpack(info) + _LOGGER.error('Quota failure: %s', info) + else: + raise RuntimeError('Unexpected failure: %s' % detail) + + +def main(): # NOTE(gRPC Python Team): .close() is possible on a channel and should be # used in circumstances in which the with statement does not fit the needs # of the code. with grpc.insecure_channel('localhost:50051') as channel: stub = helloworld_pb2_grpc.GreeterStub(channel) - try: - response = stub.SayHello(helloworld_pb2.HelloRequest(name='Alice')) - print('Call success:', response.message) - except grpc.RpcError as rpc_error: - print('Call failure:', rpc_error) - status = rpc_status.from_call(rpc_error) - for detail in status.details: - if detail.Is(error_details_pb2.QuotaFailure.DESCRIPTOR): - info = error_details_pb2.QuotaFailure() - detail.Unpack(info) - print('Quota failure:', info) - else: - print('Unexpected failure:', detail) + process(stub) if __name__ == '__main__': logging.basicConfig() - run() + main() diff --git a/examples/python/errors/helloworld_pb2.py b/examples/python/errors/helloworld_pb2.py deleted file mode 100644 index e18ab9acc7a..00000000000 --- a/examples/python/errors/helloworld_pb2.py +++ /dev/null @@ -1,134 +0,0 @@ -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: helloworld.proto - -import sys -_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database -from google.protobuf import descriptor_pb2 -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - - - -DESCRIPTOR = _descriptor.FileDescriptor( - name='helloworld.proto', - package='helloworld', - syntax='proto3', - serialized_pb=_b('\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3') -) - - - - -_HELLOREQUEST = _descriptor.Descriptor( - name='HelloRequest', - full_name='helloworld.HelloRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='name', full_name='helloworld.HelloRequest.name', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=32, - serialized_end=60, -) - - -_HELLOREPLY = _descriptor.Descriptor( - name='HelloReply', - full_name='helloworld.HelloReply', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='message', full_name='helloworld.HelloReply.message', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=62, - serialized_end=91, -) - -DESCRIPTOR.message_types_by_name['HelloRequest'] = _HELLOREQUEST -DESCRIPTOR.message_types_by_name['HelloReply'] = _HELLOREPLY -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -HelloRequest = _reflection.GeneratedProtocolMessageType('HelloRequest', (_message.Message,), dict( - DESCRIPTOR = _HELLOREQUEST, - __module__ = 'helloworld_pb2' - # @@protoc_insertion_point(class_scope:helloworld.HelloRequest) - )) -_sym_db.RegisterMessage(HelloRequest) - -HelloReply = _reflection.GeneratedProtocolMessageType('HelloReply', (_message.Message,), dict( - DESCRIPTOR = _HELLOREPLY, - __module__ = 'helloworld_pb2' - # @@protoc_insertion_point(class_scope:helloworld.HelloReply) - )) -_sym_db.RegisterMessage(HelloReply) - - -DESCRIPTOR.has_options = True -DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW')) - -_GREETER = _descriptor.ServiceDescriptor( - name='Greeter', - full_name='helloworld.Greeter', - file=DESCRIPTOR, - index=0, - options=None, - serialized_start=93, - serialized_end=166, - methods=[ - _descriptor.MethodDescriptor( - name='SayHello', - full_name='helloworld.Greeter.SayHello', - index=0, - containing_service=None, - input_type=_HELLOREQUEST, - output_type=_HELLOREPLY, - options=None, - ), -]) -_sym_db.RegisterServiceDescriptor(_GREETER) - -DESCRIPTOR.services_by_name['Greeter'] = _GREETER - -# @@protoc_insertion_point(module_scope) diff --git a/examples/python/errors/helloworld_pb2_grpc.py b/examples/python/errors/helloworld_pb2_grpc.py deleted file mode 100644 index 18e07d16797..00000000000 --- a/examples/python/errors/helloworld_pb2_grpc.py +++ /dev/null @@ -1,46 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -import grpc - -import helloworld_pb2 as helloworld__pb2 - - -class GreeterStub(object): - """The greeting service definition. - """ - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.SayHello = channel.unary_unary( - '/helloworld.Greeter/SayHello', - request_serializer=helloworld__pb2.HelloRequest.SerializeToString, - response_deserializer=helloworld__pb2.HelloReply.FromString, - ) - - -class GreeterServicer(object): - """The greeting service definition. - """ - - def SayHello(self, request, context): - """Sends a greeting - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - -def add_GreeterServicer_to_server(servicer, server): - rpc_method_handlers = { - 'SayHello': grpc.unary_unary_rpc_method_handler( - servicer.SayHello, - request_deserializer=helloworld__pb2.HelloRequest.FromString, - response_serializer=helloworld__pb2.HelloReply.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - 'helloworld.Greeter', rpc_method_handlers) - server.add_generic_rpc_handlers((generic_handler,)) diff --git a/examples/python/errors/error_handling_server.py b/examples/python/errors/server.py similarity index 86% rename from examples/python/errors/error_handling_server.py rename to examples/python/errors/server.py index c782f7d1a2d..f49586b848a 100644 --- a/examples/python/errors/error_handling_server.py +++ b/examples/python/errors/server.py @@ -24,8 +24,8 @@ from grpc_status import rpc_status from google.protobuf import any_pb2 from google.rpc import code_pb2, status_pb2, error_details_pb2 -import helloworld_pb2 -import helloworld_pb2_grpc +from examples.protos import helloworld_pb2 +from examples.protos import helloworld_pb2_grpc _ONE_DAY_IN_SECONDS = 60 * 60 * 24 @@ -36,7 +36,7 @@ def create_greet_limit_exceed_error_status(name): error_details_pb2.QuotaFailure( violations=[ error_details_pb2.QuotaFailure.Violation( - subject="name:%s" % name, + subject="name: %s" % name, description="Limit one greeting per person", ) ],)) @@ -64,10 +64,14 @@ class LimitedGreeter(helloworld_pb2_grpc.GreeterServicer): return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name) -def serve(): +def create_server(server_address): server = grpc.server(futures.ThreadPoolExecutor()) helloworld_pb2_grpc.add_GreeterServicer_to_server(LimitedGreeter(), server) - server.add_insecure_port('[::]:50051') + port = server.add_insecure_port(server_address) + return server, port + + +def serve(server): server.start() try: while True: @@ -76,6 +80,11 @@ def serve(): server.stop(None) +def main(): + server, unused_port = create_server('[::]:50051') + serve(server) + + if __name__ == '__main__': logging.basicConfig() - serve() + main() diff --git a/examples/python/errors/test/_error_handling_example_test.py b/examples/python/errors/test/_error_handling_example_test.py new file mode 100644 index 00000000000..da7f58a002e --- /dev/null +++ b/examples/python/errors/test/_error_handling_example_test.py @@ -0,0 +1,54 @@ +# Copyright 2019 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Tests of the error handling example.""" + +import unittest +import logging + +import grpc + +from examples.protos import helloworld_pb2_grpc +from examples.python.errors import client as error_handling_client +from examples.python.errors import server as error_handling_server + +# NOTE(lidiz) This module only exists in Bazel BUILD file, for more details +# please refer to comments in the "bazel_namespace_package_hack" module. +try: + from tests import bazel_namespace_package_hack + bazel_namespace_package_hack.sys_path_to_site_dir_hack() +except ImportError: + pass + + +class ErrorHandlingExampleTest(unittest.TestCase): + + def setUp(self): + self._server, port = error_handling_server.create_server('[::]:0') + self._server.start() + self._channel = grpc.insecure_channel('localhost:%d' % port) + + def tearDown(self): + self._channel.close() + self._server.stop(None) + + def test_error_handling_example(self): + stub = helloworld_pb2_grpc.GreeterStub(self._channel) + error_handling_client.process(stub) + error_handling_client.process(stub) + # No unhandled exception raised, test passed! + + +if __name__ == '__main__': + logging.basicConfig() + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/BUILD.bazel b/src/python/grpcio_tests/tests/BUILD.bazel index b908ab85173..b2b36ad10f3 100644 --- a/src/python/grpcio_tests/tests/BUILD.bazel +++ b/src/python/grpcio_tests/tests/BUILD.bazel @@ -4,5 +4,6 @@ py_library( visibility = [ "//src/python/grpcio_tests/tests/status:__subpackages__", "//src/python/grpcio_tests/tests/interop:__subpackages__", + "//examples/python/errors:__subpackages__", ], ) From 7771290fcd3b682e8b90ef5337895d96bc68eb68 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Mon, 25 Mar 2019 12:38:20 -0700 Subject: [PATCH 055/242] Pin the proto definitions to a specific commit --- examples/python/errors/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/python/errors/README.md b/examples/python/errors/README.md index 3c53690b99c..2cfc26a93b0 100644 --- a/examples/python/errors/README.md +++ b/examples/python/errors/README.md @@ -19,13 +19,13 @@ googleapis-common-protos>=1.5.5 You may provide any custom proto message as error detail in your implementation. Here are protos are defined by Google Cloud Library Team: -* [code.proto](https://github.com/googleapis/api-common-protos/blob/master/google/rpc/code.proto) contains definition of RPC error codes. -* [error_details.proto](https://github.com/googleapis/api-common-protos/blob/master/google/rpc/error_details.proto) contains definitions of common error details. +* [code.proto]([https://github.com/googleapis/api-common-protos/blob/master/google/rpc/code.proto](https://github.com/googleapis/api-common-protos/blob/87185dfffad4afa5a33a8c153f0e1ea53b4f85dc/google/rpc/code.proto)) contains definition of RPC error codes. +* [error_details.proto]([https://github.com/googleapis/api-common-protos/blob/master/google/rpc/error_details.proto](https://github.com/googleapis/api-common-protos/blob/87185dfffad4afa5a33a8c153f0e1ea53b4f85dc/google/rpc/error_details.proto)) contains definitions of common error details. ### Definition of Status Proto -Here is the definition of Status proto. For full text, please see [status.proto](https://github.com/googleapis/api-common-protos/blob/master/google/rpc/status.proto). +Here is the definition of Status proto. For full text, please see [status.proto](https://github.com/googleapis/api-common-protos/blob/87185dfffad4afa5a33a8c153f0e1ea53b4f85dc/google/rpc/status.proto). ```proto // The `Status` type defines a logical error model that is suitable for different From d7429dbb4ab257d5cb7c5ba86e20b24a12657293 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Mon, 25 Mar 2019 14:18:35 -0700 Subject: [PATCH 056/242] Fix the proto rules conflict --- examples/BUILD | 9 +++++++++ examples/protos/BUILD.bazel | 25 ------------------------- examples/python/errors/BUILD.bazel | 5 ++--- 3 files changed, 11 insertions(+), 28 deletions(-) delete mode 100644 examples/protos/BUILD.bazel diff --git a/examples/BUILD b/examples/BUILD index 0a1ca94a649..5e08b6cdec6 100644 --- a/examples/BUILD +++ b/examples/BUILD @@ -16,7 +16,9 @@ licenses(["notice"]) # 3-clause BSD package(default_visibility = ["//visibility:public"]) +load("@grpc_python_dependencies//:requirements.bzl", "requirement") load("//bazel:grpc_build_system.bzl", "grpc_proto_library") +load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_library") grpc_proto_library( name = "auth_sample", @@ -43,6 +45,13 @@ grpc_proto_library( srcs = ["protos/keyvaluestore.proto"], ) +py_proto_library( + name = "py_helloworld", + protos = ["protos/helloworld.proto"], + with_grpc = True, + deps = [requirement('protobuf'),], +) + cc_binary( name = "greeter_client", srcs = ["cpp/helloworld/greeter_client.cc"], diff --git a/examples/protos/BUILD.bazel b/examples/protos/BUILD.bazel deleted file mode 100644 index 197274e034c..00000000000 --- a/examples/protos/BUILD.bazel +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2019 The gRPC Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -load("@grpc_python_dependencies//:requirements.bzl", "requirement") -load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_library") - -package(default_visibility = ["//visibility:public"]) - -py_proto_library( - name = "py_helloworld_proto", - protos = ["helloworld.proto",], - with_grpc = True, - deps = [requirement('protobuf'),], -) diff --git a/examples/python/errors/BUILD.bazel b/examples/python/errors/BUILD.bazel index a2c3534f9bd..0b56e76ee4d 100644 --- a/examples/python/errors/BUILD.bazel +++ b/examples/python/errors/BUILD.bazel @@ -13,7 +13,6 @@ # limitations under the License. load("@grpc_python_dependencies//:requirements.bzl", "requirement") -load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_library") py_library( name = "client", @@ -22,7 +21,7 @@ py_library( deps = [ "//src/python/grpcio/grpc:grpcio", "//src/python/grpcio_status/grpc_status:grpc_status", - "//examples/protos:py_helloworld_proto", + "//examples:py_helloworld", requirement('googleapis-common-protos'), ], ) @@ -34,7 +33,7 @@ py_library( deps = [ "//src/python/grpcio/grpc:grpcio", "//src/python/grpcio_status/grpc_status:grpc_status", - "//examples/protos:py_helloworld_proto", + "//examples:py_helloworld", ] + select({ "//conditions:default": [requirement("futures")], "//:python3": [], From b3d907dce965f4e6635bbefbcf0a983e7c4094c5 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Mon, 25 Mar 2019 14:41:39 -0700 Subject: [PATCH 057/242] Explicitly depend on :grpcio --- examples/python/errors/BUILD.bazel | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/python/errors/BUILD.bazel b/examples/python/errors/BUILD.bazel index 0b56e76ee4d..1ef36a06471 100644 --- a/examples/python/errors/BUILD.bazel +++ b/examples/python/errors/BUILD.bazel @@ -46,6 +46,8 @@ py_test( data = [ ":client", ":server", + "//src/python/grpcio/grpc:grpcio", + "//examples:py_helloworld", "//src/python/grpcio_tests/tests:bazel_namespace_package_hack", ], size = "small", From 4e0923e802afe412e369937fde35c44e96f9014f Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Mon, 25 Mar 2019 15:49:22 -0700 Subject: [PATCH 058/242] Fix errors from clang_format_code.sh --- test/cpp/microbenchmarks/bm_opencensus_plugin.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/cpp/microbenchmarks/bm_opencensus_plugin.cc b/test/cpp/microbenchmarks/bm_opencensus_plugin.cc index 0b376c0a0c3..4f4884bef9b 100644 --- a/test/cpp/microbenchmarks/bm_opencensus_plugin.cc +++ b/test/cpp/microbenchmarks/bm_opencensus_plugin.cc @@ -33,9 +33,7 @@ using ::grpc::RegisterOpenCensusPlugin; using ::grpc::RegisterOpenCensusViewsForExport; absl::once_flag once; -void RegisterOnce() { - absl::call_once(once, RegisterOpenCensusPlugin); -} +void RegisterOnce() { absl::call_once(once, RegisterOpenCensusPlugin); } class EchoServer final : public grpc::testing::EchoTestService::Service { grpc::Status Echo(grpc::ServerContext* context, From e27ddbc87e8511ce23371190644fb36f8977656c Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Thu, 14 Mar 2019 14:10:26 -0700 Subject: [PATCH 059/242] Move ::grpc::HealthCheckServiceInterface to ::grpc_impl namespace --- BUILD | 1 + CMakeLists.txt | 3 + Makefile | 3 + build.yaml | 1 + gRPC-C++.podspec | 1 + .../grpcpp/health_check_service_interface.h | 31 +---------- .../health_check_service_interface_impl.h | 55 +++++++++++++++++++ include/grpcpp/server.h | 9 ++- src/cpp/server/server_cc.cc | 2 +- 9 files changed, 74 insertions(+), 32 deletions(-) create mode 100644 include/grpcpp/health_check_service_interface_impl.h diff --git a/BUILD b/BUILD index 12687c799ef..7be9f5adaf5 100644 --- a/BUILD +++ b/BUILD @@ -225,6 +225,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/generic/generic_stub.h", "include/grpcpp/grpcpp.h", "include/grpcpp/health_check_service_interface.h", + "include/grpcpp/health_check_service_interface_impl.h", "include/grpcpp/impl/call.h", "include/grpcpp/impl/channel_argument_option.h", "include/grpcpp/impl/client_unary_call.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index d39c1941a74..8a730469c81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3005,6 +3005,7 @@ foreach(_hdr include/grpcpp/generic/generic_stub.h include/grpcpp/grpcpp.h include/grpcpp/health_check_service_interface.h + include/grpcpp/health_check_service_interface_impl.h include/grpcpp/impl/call.h include/grpcpp/impl/channel_argument_option.h include/grpcpp/impl/client_unary_call.h @@ -3596,6 +3597,7 @@ foreach(_hdr include/grpcpp/generic/generic_stub.h include/grpcpp/grpcpp.h include/grpcpp/health_check_service_interface.h + include/grpcpp/health_check_service_interface_impl.h include/grpcpp/impl/call.h include/grpcpp/impl/channel_argument_option.h include/grpcpp/impl/client_unary_call.h @@ -4559,6 +4561,7 @@ foreach(_hdr include/grpcpp/generic/generic_stub.h include/grpcpp/grpcpp.h include/grpcpp/health_check_service_interface.h + include/grpcpp/health_check_service_interface_impl.h include/grpcpp/impl/call.h include/grpcpp/impl/channel_argument_option.h include/grpcpp/impl/client_unary_call.h diff --git a/Makefile b/Makefile index 85e621f87bb..04c1885974a 100644 --- a/Makefile +++ b/Makefile @@ -5332,6 +5332,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/generic/generic_stub.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ + include/grpcpp/health_check_service_interface_impl.h \ include/grpcpp/impl/call.h \ include/grpcpp/impl/channel_argument_option.h \ include/grpcpp/impl/client_unary_call.h \ @@ -5931,6 +5932,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/generic/generic_stub.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ + include/grpcpp/health_check_service_interface_impl.h \ include/grpcpp/impl/call.h \ include/grpcpp/impl/channel_argument_option.h \ include/grpcpp/impl/client_unary_call.h \ @@ -6843,6 +6845,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/generic/generic_stub.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ + include/grpcpp/health_check_service_interface_impl.h \ include/grpcpp/impl/call.h \ include/grpcpp/impl/channel_argument_option.h \ include/grpcpp/impl/client_unary_call.h \ diff --git a/build.yaml b/build.yaml index 34b271f58de..28ecec5f979 100644 --- a/build.yaml +++ b/build.yaml @@ -1350,6 +1350,7 @@ filegroups: - include/grpcpp/generic/generic_stub.h - include/grpcpp/grpcpp.h - include/grpcpp/health_check_service_interface.h + - include/grpcpp/health_check_service_interface_impl.h - include/grpcpp/impl/call.h - include/grpcpp/impl/channel_argument_option.h - include/grpcpp/impl/client_unary_call.h diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 5a850bc8438..2a74bfdb533 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -91,6 +91,7 @@ Pod::Spec.new do |s| 'include/grpcpp/generic/generic_stub.h', 'include/grpcpp/grpcpp.h', 'include/grpcpp/health_check_service_interface.h', + 'include/grpcpp/health_check_service_interface_impl.h', 'include/grpcpp/impl/call.h', 'include/grpcpp/impl/channel_argument_option.h', 'include/grpcpp/impl/client_unary_call.h', diff --git a/include/grpcpp/health_check_service_interface.h b/include/grpcpp/health_check_service_interface.h index dfd4c3983af..6dde0951768 100644 --- a/include/grpcpp/health_check_service_interface.h +++ b/include/grpcpp/health_check_service_interface.h @@ -1,6 +1,6 @@ /* * - * Copyright 2016 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,39 +19,14 @@ #ifndef GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_H #define GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_H -#include +#include namespace grpc { const char kHealthCheckServiceInterfaceArg[] = "grpc.health_check_service_interface"; -/// The gRPC server uses this interface to expose the health checking service -/// without depending on protobuf. -class HealthCheckServiceInterface { - public: - virtual ~HealthCheckServiceInterface() {} - - /// Set or change the serving status of the given \a service_name. - virtual void SetServingStatus(const grpc::string& service_name, - bool serving) = 0; - /// Apply to all registered service names. - virtual void SetServingStatus(bool serving) = 0; - - /// Set all registered service names to not serving and prevent future - /// state changes. - virtual void Shutdown() {} -}; - -/// Enable/disable the default health checking service. This applies to all C++ -/// servers created afterwards. For each server, user can override the default -/// with a HealthCheckServiceServerBuilderOption. -/// NOT thread safe. -void EnableDefaultHealthCheckService(bool enable); - -/// Returns whether the default health checking service is enabled. -/// NOT thread safe. -bool DefaultHealthCheckServiceEnabled(); +typedef ::grpc_impl::HealthCheckServiceInterface HealthCheckServiceInterface; } // namespace grpc diff --git a/include/grpcpp/health_check_service_interface_impl.h b/include/grpcpp/health_check_service_interface_impl.h new file mode 100644 index 00000000000..025dadb4e59 --- /dev/null +++ b/include/grpcpp/health_check_service_interface_impl.h @@ -0,0 +1,55 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_IMPL_H +#define GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_IMPL_H + +#include + +namespace grpc_impl { + +/// The gRPC server uses this interface to expose the health checking service +/// without depending on protobuf. +class HealthCheckServiceInterface { + public: + virtual ~HealthCheckServiceInterface() {} + + /// Set or change the serving status of the given \a service_name. + virtual void SetServingStatus(const grpc::string& service_name, + bool serving) = 0; + /// Apply to all registered service names. + virtual void SetServingStatus(bool serving) = 0; + + /// Set all registered service names to not serving and prevent future + /// state changes. + virtual void Shutdown() {} +}; + +/// Enable/disable the default health checking service. This applies to all C++ +/// servers created afterwards. For each server, user can override the default +/// with a HealthCheckServiceServerBuilderOption. +/// NOT thread safe. +void EnableDefaultHealthCheckService(bool enable); + +/// Returns whether the default health checking service is enabled. +/// NOT thread safe. +bool DefaultHealthCheckServiceEnabled(); + +} // namespace grpc_impl + +#endif // GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_IMPL_H diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index f5c99f22df2..3bbd8a2b3e2 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -40,10 +40,13 @@ struct grpc_server; +namespace grpc_impl { + +class HealthCheckServiceInterface; +} namespace grpc { class AsyncGenericService; -class HealthCheckServiceInterface; class ServerContext; class ServerInitializer; @@ -94,7 +97,7 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { grpc_server* c_server(); /// Returns the health check service. - HealthCheckServiceInterface* GetHealthCheckService() const { + grpc_impl::HealthCheckServiceInterface* GetHealthCheckService() const { return health_check_service_.get(); } @@ -323,7 +326,7 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { std::unique_ptr server_initializer_; - std::unique_ptr health_check_service_; + std::unique_ptr health_check_service_; bool health_check_service_disabled_; // When appropriate, use a default callback generic service to handle diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 26e84f1aed4..616b4738bc2 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -987,7 +987,7 @@ void Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) { DefaultHealthCheckService::HealthCheckServiceImpl* default_health_check_service_impl = nullptr; if (health_check_service_ == nullptr && !health_check_service_disabled_ && - DefaultHealthCheckServiceEnabled()) { + grpc_impl::DefaultHealthCheckServiceEnabled()) { auto* default_hc_service = new DefaultHealthCheckService; health_check_service_.reset(default_hc_service); // We create a non-polling CQ to avoid impacting application From b25f6da3f01f8480109528148517ce3019b1b61c Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Thu, 14 Mar 2019 17:00:34 -0700 Subject: [PATCH 060/242] Make changes to fix test failures --- include/grpcpp/server.h | 1 + .../health/default_health_check_service.h | 2 +- src/cpp/server/health/health_check_service.cc | 6 ++--- src/cpp/server/server_cc.cc | 2 +- test/cpp/end2end/client_lb_end2end_test.cc | 8 +++--- .../end2end/health_service_end2end_test.cc | 26 +++++++++---------- 6 files changed, 23 insertions(+), 22 deletions(-) diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index 3bbd8a2b3e2..6638b098954 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include diff --git a/src/cpp/server/health/default_health_check_service.h b/src/cpp/server/health/default_health_check_service.h index 9551cd2e2cf..0ed8a45bb3f 100644 --- a/src/cpp/server/health/default_health_check_service.h +++ b/src/cpp/server/health/default_health_check_service.h @@ -37,7 +37,7 @@ namespace grpc { // Default implementation of HealthCheckServiceInterface. Server will create and // own it. -class DefaultHealthCheckService final : public HealthCheckServiceInterface { +class DefaultHealthCheckService final : public grpc_impl::HealthCheckServiceInterface { public: enum ServingStatus { NOT_FOUND, SERVING, NOT_SERVING }; diff --git a/src/cpp/server/health/health_check_service.cc b/src/cpp/server/health/health_check_service.cc index a0fa2d62f58..ca0b49a1ae8 100644 --- a/src/cpp/server/health/health_check_service.cc +++ b/src/cpp/server/health/health_check_service.cc @@ -16,9 +16,9 @@ * */ -#include +#include -namespace grpc { +namespace grpc_impl { namespace { bool g_grpc_default_health_check_service_enabled = false; } // namespace @@ -31,4 +31,4 @@ void EnableDefaultHealthCheckService(bool enable) { g_grpc_default_health_check_service_enabled = enable; } -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 616b4738bc2..589440d6660 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -802,7 +802,7 @@ Server::Server( if (channel_args.args[i].value.pointer.p == nullptr) { health_check_service_disabled_ = true; } else { - health_check_service_.reset(static_cast( + health_check_service_.reset(static_cast( channel_args.args[i].value.pointer.p)); } break; diff --git a/test/cpp/end2end/client_lb_end2end_test.cc b/test/cpp/end2end/client_lb_end2end_test.cc index 3cd06e9e28c..6856883c2af 100644 --- a/test/cpp/end2end/client_lb_end2end_test.cc +++ b/test/cpp/end2end/client_lb_end2end_test.cc @@ -1242,7 +1242,7 @@ TEST_F(ClientLbEnd2endTest, } TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthChecking) { - EnableDefaultHealthCheckService(true); + grpc_impl::EnableDefaultHealthCheckService(true); // Start servers. const int kNumServers = 3; StartServers(kNumServers); @@ -1311,11 +1311,11 @@ TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthChecking) { EXPECT_TRUE(WaitForChannelNotReady(channel.get())); CheckRpcSendFailure(stub); // Clean up. - EnableDefaultHealthCheckService(false); + grpc_impl::EnableDefaultHealthCheckService(false); } TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthCheckingInhibitPerChannel) { - EnableDefaultHealthCheckService(true); + grpc_impl::EnableDefaultHealthCheckService(true); // Start server. const int kNumServers = 1; StartServers(kNumServers); @@ -1341,7 +1341,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthCheckingInhibitPerChannel) { EXPECT_TRUE(WaitForChannelReady(channel2.get(), 1)); CheckRpcSendOk(stub2, DEBUG_LOCATION); // Clean up. - EnableDefaultHealthCheckService(false); + grpc_impl::EnableDefaultHealthCheckService(false); } class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest { diff --git a/test/cpp/end2end/health_service_end2end_test.cc b/test/cpp/end2end/health_service_end2end_test.cc index b96ff53a3ea..c36d6e4d296 100644 --- a/test/cpp/end2end/health_service_end2end_test.cc +++ b/test/cpp/end2end/health_service_end2end_test.cc @@ -285,8 +285,8 @@ class HealthServiceEnd2endTest : public ::testing::Test { }; TEST_F(HealthServiceEnd2endTest, DefaultHealthServiceDisabled) { - EnableDefaultHealthCheckService(false); - EXPECT_FALSE(DefaultHealthCheckServiceEnabled()); + grpc_impl::EnableDefaultHealthCheckService(false); + EXPECT_FALSE(grpc_impl::DefaultHealthCheckServiceEnabled()); SetUpServer(true, false, false, nullptr); HealthCheckServiceInterface* default_service = server_->GetHealthCheckService(); @@ -298,8 +298,8 @@ TEST_F(HealthServiceEnd2endTest, DefaultHealthServiceDisabled) { } TEST_F(HealthServiceEnd2endTest, DefaultHealthService) { - EnableDefaultHealthCheckService(true); - EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); + grpc_impl::EnableDefaultHealthCheckService(true); + EXPECT_TRUE(grpc_impl::DefaultHealthCheckServiceEnabled()); SetUpServer(true, false, false, nullptr); VerifyHealthCheckService(); VerifyHealthCheckServiceStreaming(); @@ -311,19 +311,19 @@ TEST_F(HealthServiceEnd2endTest, DefaultHealthService) { } TEST_F(HealthServiceEnd2endTest, DefaultHealthServiceShutdown) { - EnableDefaultHealthCheckService(true); - EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); + grpc_impl::EnableDefaultHealthCheckService(true); + EXPECT_TRUE(grpc_impl::DefaultHealthCheckServiceEnabled()); SetUpServer(true, false, false, nullptr); VerifyHealthCheckServiceShutdown(); } // Provide an empty service to disable the default service. TEST_F(HealthServiceEnd2endTest, ExplicitlyDisableViaOverride) { - EnableDefaultHealthCheckService(true); - EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); + grpc_impl::EnableDefaultHealthCheckService(true); + EXPECT_TRUE(grpc_impl::DefaultHealthCheckServiceEnabled()); std::unique_ptr empty_service; SetUpServer(true, false, true, std::move(empty_service)); - HealthCheckServiceInterface* service = server_->GetHealthCheckService(); + grpc_impl::HealthCheckServiceInterface* service = server_->GetHealthCheckService(); EXPECT_TRUE(service == nullptr); ResetStubs(); @@ -333,8 +333,8 @@ TEST_F(HealthServiceEnd2endTest, ExplicitlyDisableViaOverride) { // Provide an explicit override of health checking service interface. TEST_F(HealthServiceEnd2endTest, ExplicitlyOverride) { - EnableDefaultHealthCheckService(true); - EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); + grpc_impl::EnableDefaultHealthCheckService(true); + EXPECT_TRUE(grpc_impl::DefaultHealthCheckServiceEnabled()); std::unique_ptr override_service( new CustomHealthCheckService(&health_check_service_impl_)); HealthCheckServiceInterface* underlying_service = override_service.get(); @@ -349,8 +349,8 @@ TEST_F(HealthServiceEnd2endTest, ExplicitlyOverride) { } TEST_F(HealthServiceEnd2endTest, ExplicitlyHealthServiceShutdown) { - EnableDefaultHealthCheckService(true); - EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); + grpc_impl::EnableDefaultHealthCheckService(true); + EXPECT_TRUE(grpc_impl::DefaultHealthCheckServiceEnabled()); std::unique_ptr override_service( new CustomHealthCheckService(&health_check_service_impl_)); HealthCheckServiceInterface* underlying_service = override_service.get(); From a5814f89b611b1ec3e50942168010e0083320ad1 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Fri, 15 Mar 2019 14:23:00 -0700 Subject: [PATCH 061/242] Fix errors from tools/buildgen/generate_projects.sh --- tools/doxygen/Doxyfile.c++ | 1 + tools/doxygen/Doxyfile.c++.internal | 1 + tools/run_tests/generated/sources_and_headers.json | 2 ++ 3 files changed, 4 insertions(+) diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 9f17a25298a..796bc99672a 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -936,6 +936,7 @@ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ +include/grpcpp/health_check_service_interface_impl.h \ include/grpcpp/impl/call.h \ include/grpcpp/impl/channel_argument_option.h \ include/grpcpp/impl/client_unary_call.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index c0078bf2764..cdd5be33d7e 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -937,6 +937,7 @@ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ +include/grpcpp/health_check_service_interface_impl.h \ include/grpcpp/impl/call.h \ include/grpcpp/impl/channel_argument_option.h \ include/grpcpp/impl/client_unary_call.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 501e53560ab..e1e0dfb1a87 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -10069,6 +10069,7 @@ "include/grpcpp/generic/generic_stub.h", "include/grpcpp/grpcpp.h", "include/grpcpp/health_check_service_interface.h", + "include/grpcpp/health_check_service_interface_impl.h", "include/grpcpp/impl/call.h", "include/grpcpp/impl/channel_argument_option.h", "include/grpcpp/impl/client_unary_call.h", @@ -10178,6 +10179,7 @@ "include/grpcpp/generic/generic_stub.h", "include/grpcpp/grpcpp.h", "include/grpcpp/health_check_service_interface.h", + "include/grpcpp/health_check_service_interface_impl.h", "include/grpcpp/impl/call.h", "include/grpcpp/impl/channel_argument_option.h", "include/grpcpp/impl/client_unary_call.h", From 92bde3922f635d0354df2cc7177a210a4a8157d1 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Fri, 15 Mar 2019 16:16:53 -0700 Subject: [PATCH 062/242] Fix tests to use grpc namespace. --- .../grpcpp/health_check_service_interface.h | 9 +++++++ test/cpp/end2end/client_lb_end2end_test.cc | 8 +++---- .../end2end/health_service_end2end_test.cc | 24 +++++++++---------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/include/grpcpp/health_check_service_interface.h b/include/grpcpp/health_check_service_interface.h index 6dde0951768..13286728438 100644 --- a/include/grpcpp/health_check_service_interface.h +++ b/include/grpcpp/health_check_service_interface.h @@ -28,6 +28,15 @@ const char kHealthCheckServiceInterfaceArg[] = typedef ::grpc_impl::HealthCheckServiceInterface HealthCheckServiceInterface; +static inline void EnableDefaultHealthCheckService(bool enable) { + ::grpc_impl::EnableDefaultHealthCheckService(enable); +} + +static inline bool DefaultHealthCheckServiceEnabled() { + return ::grpc_impl::DefaultHealthCheckServiceEnabled(); +} + + } // namespace grpc #endif // GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_H diff --git a/test/cpp/end2end/client_lb_end2end_test.cc b/test/cpp/end2end/client_lb_end2end_test.cc index 6856883c2af..3cd06e9e28c 100644 --- a/test/cpp/end2end/client_lb_end2end_test.cc +++ b/test/cpp/end2end/client_lb_end2end_test.cc @@ -1242,7 +1242,7 @@ TEST_F(ClientLbEnd2endTest, } TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthChecking) { - grpc_impl::EnableDefaultHealthCheckService(true); + EnableDefaultHealthCheckService(true); // Start servers. const int kNumServers = 3; StartServers(kNumServers); @@ -1311,11 +1311,11 @@ TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthChecking) { EXPECT_TRUE(WaitForChannelNotReady(channel.get())); CheckRpcSendFailure(stub); // Clean up. - grpc_impl::EnableDefaultHealthCheckService(false); + EnableDefaultHealthCheckService(false); } TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthCheckingInhibitPerChannel) { - grpc_impl::EnableDefaultHealthCheckService(true); + EnableDefaultHealthCheckService(true); // Start server. const int kNumServers = 1; StartServers(kNumServers); @@ -1341,7 +1341,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinWithHealthCheckingInhibitPerChannel) { EXPECT_TRUE(WaitForChannelReady(channel2.get(), 1)); CheckRpcSendOk(stub2, DEBUG_LOCATION); // Clean up. - grpc_impl::EnableDefaultHealthCheckService(false); + EnableDefaultHealthCheckService(false); } class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest { diff --git a/test/cpp/end2end/health_service_end2end_test.cc b/test/cpp/end2end/health_service_end2end_test.cc index c36d6e4d296..a3a04b121c2 100644 --- a/test/cpp/end2end/health_service_end2end_test.cc +++ b/test/cpp/end2end/health_service_end2end_test.cc @@ -285,8 +285,8 @@ class HealthServiceEnd2endTest : public ::testing::Test { }; TEST_F(HealthServiceEnd2endTest, DefaultHealthServiceDisabled) { - grpc_impl::EnableDefaultHealthCheckService(false); - EXPECT_FALSE(grpc_impl::DefaultHealthCheckServiceEnabled()); + EnableDefaultHealthCheckService(false); + EXPECT_FALSE(DefaultHealthCheckServiceEnabled()); SetUpServer(true, false, false, nullptr); HealthCheckServiceInterface* default_service = server_->GetHealthCheckService(); @@ -298,8 +298,8 @@ TEST_F(HealthServiceEnd2endTest, DefaultHealthServiceDisabled) { } TEST_F(HealthServiceEnd2endTest, DefaultHealthService) { - grpc_impl::EnableDefaultHealthCheckService(true); - EXPECT_TRUE(grpc_impl::DefaultHealthCheckServiceEnabled()); + EnableDefaultHealthCheckService(true); + EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); SetUpServer(true, false, false, nullptr); VerifyHealthCheckService(); VerifyHealthCheckServiceStreaming(); @@ -311,16 +311,16 @@ TEST_F(HealthServiceEnd2endTest, DefaultHealthService) { } TEST_F(HealthServiceEnd2endTest, DefaultHealthServiceShutdown) { - grpc_impl::EnableDefaultHealthCheckService(true); - EXPECT_TRUE(grpc_impl::DefaultHealthCheckServiceEnabled()); + EnableDefaultHealthCheckService(true); + EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); SetUpServer(true, false, false, nullptr); VerifyHealthCheckServiceShutdown(); } // Provide an empty service to disable the default service. TEST_F(HealthServiceEnd2endTest, ExplicitlyDisableViaOverride) { - grpc_impl::EnableDefaultHealthCheckService(true); - EXPECT_TRUE(grpc_impl::DefaultHealthCheckServiceEnabled()); + EnableDefaultHealthCheckService(true); + EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); std::unique_ptr empty_service; SetUpServer(true, false, true, std::move(empty_service)); grpc_impl::HealthCheckServiceInterface* service = server_->GetHealthCheckService(); @@ -333,8 +333,8 @@ TEST_F(HealthServiceEnd2endTest, ExplicitlyDisableViaOverride) { // Provide an explicit override of health checking service interface. TEST_F(HealthServiceEnd2endTest, ExplicitlyOverride) { - grpc_impl::EnableDefaultHealthCheckService(true); - EXPECT_TRUE(grpc_impl::DefaultHealthCheckServiceEnabled()); + EnableDefaultHealthCheckService(true); + EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); std::unique_ptr override_service( new CustomHealthCheckService(&health_check_service_impl_)); HealthCheckServiceInterface* underlying_service = override_service.get(); @@ -349,8 +349,8 @@ TEST_F(HealthServiceEnd2endTest, ExplicitlyOverride) { } TEST_F(HealthServiceEnd2endTest, ExplicitlyHealthServiceShutdown) { - grpc_impl::EnableDefaultHealthCheckService(true); - EXPECT_TRUE(grpc_impl::DefaultHealthCheckServiceEnabled()); + EnableDefaultHealthCheckService(true); + EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); std::unique_ptr override_service( new CustomHealthCheckService(&health_check_service_impl_)); HealthCheckServiceInterface* underlying_service = override_service.get(); From 8dbaa13f52bbbe2418a62ee87d8495d0a49e6d6e Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Fri, 15 Mar 2019 16:25:16 -0700 Subject: [PATCH 063/242] Fix more grpc namespace issues --- include/grpcpp/server.h | 8 ++------ src/cpp/server/health/default_health_check_service.h | 2 +- src/cpp/server/server_cc.cc | 4 ++-- test/cpp/end2end/health_service_end2end_test.cc | 2 +- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index 6638b098954..48a0da173ac 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -41,10 +41,6 @@ struct grpc_server; -namespace grpc_impl { - -class HealthCheckServiceInterface; -} namespace grpc { class AsyncGenericService; @@ -98,7 +94,7 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { grpc_server* c_server(); /// Returns the health check service. - grpc_impl::HealthCheckServiceInterface* GetHealthCheckService() const { + HealthCheckServiceInterface* GetHealthCheckService() const { return health_check_service_.get(); } @@ -327,7 +323,7 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { std::unique_ptr server_initializer_; - std::unique_ptr health_check_service_; + std::unique_ptr health_check_service_; bool health_check_service_disabled_; // When appropriate, use a default callback generic service to handle diff --git a/src/cpp/server/health/default_health_check_service.h b/src/cpp/server/health/default_health_check_service.h index 0ed8a45bb3f..9551cd2e2cf 100644 --- a/src/cpp/server/health/default_health_check_service.h +++ b/src/cpp/server/health/default_health_check_service.h @@ -37,7 +37,7 @@ namespace grpc { // Default implementation of HealthCheckServiceInterface. Server will create and // own it. -class DefaultHealthCheckService final : public grpc_impl::HealthCheckServiceInterface { +class DefaultHealthCheckService final : public HealthCheckServiceInterface { public: enum ServingStatus { NOT_FOUND, SERVING, NOT_SERVING }; diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 589440d6660..26e84f1aed4 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -802,7 +802,7 @@ Server::Server( if (channel_args.args[i].value.pointer.p == nullptr) { health_check_service_disabled_ = true; } else { - health_check_service_.reset(static_cast( + health_check_service_.reset(static_cast( channel_args.args[i].value.pointer.p)); } break; @@ -987,7 +987,7 @@ void Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) { DefaultHealthCheckService::HealthCheckServiceImpl* default_health_check_service_impl = nullptr; if (health_check_service_ == nullptr && !health_check_service_disabled_ && - grpc_impl::DefaultHealthCheckServiceEnabled()) { + DefaultHealthCheckServiceEnabled()) { auto* default_hc_service = new DefaultHealthCheckService; health_check_service_.reset(default_hc_service); // We create a non-polling CQ to avoid impacting application diff --git a/test/cpp/end2end/health_service_end2end_test.cc b/test/cpp/end2end/health_service_end2end_test.cc index a3a04b121c2..b96ff53a3ea 100644 --- a/test/cpp/end2end/health_service_end2end_test.cc +++ b/test/cpp/end2end/health_service_end2end_test.cc @@ -323,7 +323,7 @@ TEST_F(HealthServiceEnd2endTest, ExplicitlyDisableViaOverride) { EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); std::unique_ptr empty_service; SetUpServer(true, false, true, std::move(empty_service)); - grpc_impl::HealthCheckServiceInterface* service = server_->GetHealthCheckService(); + HealthCheckServiceInterface* service = server_->GetHealthCheckService(); EXPECT_TRUE(service == nullptr); ResetStubs(); From 35e793d23a94614ad3439ad93688da1c3cbe6471 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Fri, 15 Mar 2019 16:27:43 -0700 Subject: [PATCH 064/242] Fix more more tests. --- include/grpcpp/server.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index 48a0da173ac..3284565be67 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -44,6 +44,7 @@ struct grpc_server; namespace grpc { class AsyncGenericService; +class HealthCheckServiceInterface; class ServerContext; class ServerInitializer; From 6e5587b1653dd57232cc764bd5bece81f5fdc2f6 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Fri, 15 Mar 2019 17:17:10 -0700 Subject: [PATCH 065/242] Fix build issues. --- include/grpcpp/server.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index 3284565be67..48a0da173ac 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -44,7 +44,6 @@ struct grpc_server; namespace grpc { class AsyncGenericService; -class HealthCheckServiceInterface; class ServerContext; class ServerInitializer; From d204654836b0639b9af9ded4e2c852cc276c6679 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Mon, 25 Mar 2019 15:51:28 -0700 Subject: [PATCH 066/242] Fix errors from clang_format_code.sh --- include/grpcpp/health_check_service_interface.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/grpcpp/health_check_service_interface.h b/include/grpcpp/health_check_service_interface.h index 13286728438..a51b0d18bba 100644 --- a/include/grpcpp/health_check_service_interface.h +++ b/include/grpcpp/health_check_service_interface.h @@ -36,7 +36,6 @@ static inline bool DefaultHealthCheckServiceEnabled() { return ::grpc_impl::DefaultHealthCheckServiceEnabled(); } - } // namespace grpc #endif // GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_H From d23753ca46469d23aca93ffe1fad658c9742cc72 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Thu, 14 Mar 2019 14:40:49 -0700 Subject: [PATCH 067/242] Move create_channel_posix from grpc to grpc_impl namespace --- BUILD | 1 + CMakeLists.txt | 3 + Makefile | 3 + build.yaml | 1 + include/grpcpp/create_channel_posix.h | 49 +-------------- include/grpcpp/create_channel_posix_impl.h | 69 ++++++++++++++++++++++ 6 files changed, 79 insertions(+), 47 deletions(-) create mode 100644 include/grpcpp/create_channel_posix_impl.h diff --git a/BUILD b/BUILD index 12687c799ef..5e654421418 100644 --- a/BUILD +++ b/BUILD @@ -220,6 +220,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", "include/grpcpp/create_channel_posix.h", + "include/grpcpp/create_channel_posix_impl.h", "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", "include/grpcpp/generic/generic_stub.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index d39c1941a74..89634db6796 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3000,6 +3000,7 @@ foreach(_hdr include/grpcpp/completion_queue.h include/grpcpp/create_channel.h include/grpcpp/create_channel_posix.h + include/grpcpp/create_channel_posix_impl.h include/grpcpp/ext/health_check_service_server_builder_option.h include/grpcpp/generic/async_generic_service.h include/grpcpp/generic/generic_stub.h @@ -3591,6 +3592,7 @@ foreach(_hdr include/grpcpp/completion_queue.h include/grpcpp/create_channel.h include/grpcpp/create_channel_posix.h + include/grpcpp/create_channel_posix_impl.h include/grpcpp/ext/health_check_service_server_builder_option.h include/grpcpp/generic/async_generic_service.h include/grpcpp/generic/generic_stub.h @@ -4554,6 +4556,7 @@ foreach(_hdr include/grpcpp/completion_queue.h include/grpcpp/create_channel.h include/grpcpp/create_channel_posix.h + include/grpcpp/create_channel_posix_impl.h include/grpcpp/ext/health_check_service_server_builder_option.h include/grpcpp/generic/async_generic_service.h include/grpcpp/generic/generic_stub.h diff --git a/Makefile b/Makefile index 85e621f87bb..04d3133eb7f 100644 --- a/Makefile +++ b/Makefile @@ -5327,6 +5327,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ include/grpcpp/create_channel_posix.h \ + include/grpcpp/create_channel_posix_impl.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ @@ -5926,6 +5927,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ include/grpcpp/create_channel_posix.h \ + include/grpcpp/create_channel_posix_impl.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ @@ -6838,6 +6840,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ include/grpcpp/create_channel_posix.h \ + include/grpcpp/create_channel_posix_impl.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ diff --git a/build.yaml b/build.yaml index 34b271f58de..19edebe12a0 100644 --- a/build.yaml +++ b/build.yaml @@ -1345,6 +1345,7 @@ filegroups: - include/grpcpp/completion_queue.h - include/grpcpp/create_channel.h - include/grpcpp/create_channel_posix.h + - include/grpcpp/create_channel_posix_impl.h - include/grpcpp/ext/health_check_service_server_builder_option.h - include/grpcpp/generic/async_generic_service.h - include/grpcpp/generic/generic_stub.h diff --git a/include/grpcpp/create_channel_posix.h b/include/grpcpp/create_channel_posix.h index 808514041b8..d86f92d831b 100644 --- a/include/grpcpp/create_channel_posix.h +++ b/include/grpcpp/create_channel_posix.h @@ -1,6 +1,6 @@ /* * - * Copyright 2016 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,51 +19,6 @@ #ifndef GRPCPP_CREATE_CHANNEL_POSIX_H #define GRPCPP_CREATE_CHANNEL_POSIX_H -#include - -#include -#include -#include - -namespace grpc { - -#ifdef GPR_SUPPORT_CHANNELS_FROM_FD - -/// Create a new \a Channel communicating over the given file descriptor. -/// -/// \param target The name of the target. -/// \param fd The file descriptor representing a socket. -std::shared_ptr CreateInsecureChannelFromFd(const grpc::string& target, - int fd); - -/// Create a new \a Channel communicating over given file descriptor with custom -/// channel arguments. -/// -/// \param target The name of the target. -/// \param fd The file descriptor representing a socket. -/// \param args Options for channel creation. -std::shared_ptr CreateCustomInsecureChannelFromFd( - const grpc::string& target, int fd, const ChannelArguments& args); - -namespace experimental { - -/// Create a new \a Channel communicating over given file descriptor with custom -/// channel arguments. -/// -/// \param target The name of the target. -/// \param fd The file descriptor representing a socket. -/// \param args Options for channel creation. -/// \param interceptor_creators Vector of interceptor factory objects. -std::shared_ptr CreateCustomInsecureChannelWithInterceptorsFromFd( - const grpc::string& target, int fd, const ChannelArguments& args, - std::unique_ptr>> - interceptor_creators); - -} // namespace experimental - -#endif // GPR_SUPPORT_CHANNELS_FROM_FD - -} // namespace grpc +#include #endif // GRPCPP_CREATE_CHANNEL_POSIX_H diff --git a/include/grpcpp/create_channel_posix_impl.h b/include/grpcpp/create_channel_posix_impl.h new file mode 100644 index 00000000000..053f20ca286 --- /dev/null +++ b/include/grpcpp/create_channel_posix_impl.h @@ -0,0 +1,69 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_CREATE_CHANNEL_POSIX_IMPL_H +#define GRPCPP_CREATE_CHANNEL_POSIX_IMPL_H + +#include + +#include +#include +#include + +namespace grpc_impl { + +#ifdef GPR_SUPPORT_CHANNELS_FROM_FD + +/// Create a new \a Channel communicating over the given file descriptor. +/// +/// \param target The name of the target. +/// \param fd The file descriptor representing a socket. +std::shared_ptr CreateInsecureChannelFromFd(const grpc::string& target, + int fd); + +/// Create a new \a Channel communicating over given file descriptor with custom +/// channel arguments. +/// +/// \param target The name of the target. +/// \param fd The file descriptor representing a socket. +/// \param args Options for channel creation. +std::shared_ptr CreateCustomInsecureChannelFromFd( + const grpc::string& target, int fd, const ChannelArguments& args); + +namespace experimental { + +/// Create a new \a Channel communicating over given file descriptor with custom +/// channel arguments. +/// +/// \param target The name of the target. +/// \param fd The file descriptor representing a socket. +/// \param args Options for channel creation. +/// \param interceptor_creators Vector of interceptor factory objects. +std::shared_ptr CreateCustomInsecureChannelWithInterceptorsFromFd( + const grpc::string& target, int fd, const ChannelArguments& args, + std::unique_ptr>> + interceptor_creators); + +} // namespace experimental + +#endif // GPR_SUPPORT_CHANNELS_FROM_FD + +} // namespace grpc_impl + +#endif // GRPCPP_CREATE_CHANNEL_POSIX_IMPL_H From 6ffbfaac83a27b270fc41b03459ac25d2d23cb40 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Thu, 14 Mar 2019 17:12:54 -0700 Subject: [PATCH 068/242] Fix errors from tests --- gRPC-C++.podspec | 1 + tools/doxygen/Doxyfile.c++ | 1 + tools/doxygen/Doxyfile.c++.internal | 1 + tools/run_tests/generated/sources_and_headers.json | 2 ++ 4 files changed, 5 insertions(+) diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 5a850bc8438..0ed19a9b03c 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -86,6 +86,7 @@ Pod::Spec.new do |s| 'include/grpcpp/completion_queue.h', 'include/grpcpp/create_channel.h', 'include/grpcpp/create_channel_posix.h', + 'include/grpcpp/create_channel_posix_impl.h', 'include/grpcpp/ext/health_check_service_server_builder_option.h', 'include/grpcpp/generic/async_generic_service.h', 'include/grpcpp/generic/generic_stub.h', diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 9f17a25298a..a5d74126212 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -931,6 +931,7 @@ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ include/grpcpp/create_channel_posix.h \ +include/grpcpp/create_channel_posix_impl.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index c0078bf2764..b56b0380088 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -932,6 +932,7 @@ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ include/grpcpp/create_channel_posix.h \ +include/grpcpp/create_channel_posix_impl.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 501e53560ab..5c22d32b02d 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -10064,6 +10064,7 @@ "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", "include/grpcpp/create_channel_posix.h", + "include/grpcpp/create_channel_posix_impl.h", "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", "include/grpcpp/generic/generic_stub.h", @@ -10173,6 +10174,7 @@ "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", "include/grpcpp/create_channel_posix.h", + "include/grpcpp/create_channel_posix_impl.h", "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", "include/grpcpp/generic/generic_stub.h", From 49773cbe9a525aa6c2fbda4fa81eef519b2e2a40 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Fri, 15 Mar 2019 16:44:39 -0700 Subject: [PATCH 069/242] Fix namespace to grpc --- include/grpcpp/create_channel_posix.h | 33 +++++++++++++++++++++- include/grpcpp/create_channel_posix_impl.h | 12 ++++---- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/include/grpcpp/create_channel_posix.h b/include/grpcpp/create_channel_posix.h index d86f92d831b..0e0b352259e 100644 --- a/include/grpcpp/create_channel_posix.h +++ b/include/grpcpp/create_channel_posix.h @@ -19,6 +19,37 @@ #ifndef GRPCPP_CREATE_CHANNEL_POSIX_H #define GRPCPP_CREATE_CHANNEL_POSIX_H -#include +#include + +namespace grpc { + +#ifdef GPR_SUPPORT_CHANNELS_FROM_FD + +static inline std::shared_ptr CreateInsecureChannelFromFd(const grpc::string& target, + int fd) { + return ::grpc_impl::CreateInsecureChannelFromFd(target, fd); +} + +static inline std::shared_ptr CreateCustomInsecureChannelFromFd( + const grpc::string& target, int fd, const ChannelArguments& args) { + return ::grpc_impl::CreateCustomInsecureChannelFromFd(target, fd, args); +} + +namespace experimental { + +static inline std::shared_ptr CreateCustomInsecureChannelWithInterceptorsFromFd( + const grpc::string& target, int fd, const ChannelArguments& args, + std::unique_ptr>> + interceptor_creators) { + return CreateCustomInsecureChannelWithInterceptorsFromFd(target, fd, args, std::move(interceptor_creators)); +} + +} // namespace experimental + +#endif // GPR_SUPPORT_CHANNELS_FROM_FD + +} // namespace grpc + #endif // GRPCPP_CREATE_CHANNEL_POSIX_H diff --git a/include/grpcpp/create_channel_posix_impl.h b/include/grpcpp/create_channel_posix_impl.h index 053f20ca286..7fccfa1c78d 100644 --- a/include/grpcpp/create_channel_posix_impl.h +++ b/include/grpcpp/create_channel_posix_impl.h @@ -33,7 +33,7 @@ namespace grpc_impl { /// /// \param target The name of the target. /// \param fd The file descriptor representing a socket. -std::shared_ptr CreateInsecureChannelFromFd(const grpc::string& target, +std::shared_ptr CreateInsecureChannelFromFd(const grpc::string& target, int fd); /// Create a new \a Channel communicating over given file descriptor with custom @@ -42,8 +42,8 @@ std::shared_ptr CreateInsecureChannelFromFd(const grpc::string& target, /// \param target The name of the target. /// \param fd The file descriptor representing a socket. /// \param args Options for channel creation. -std::shared_ptr CreateCustomInsecureChannelFromFd( - const grpc::string& target, int fd, const ChannelArguments& args); +std::shared_ptr CreateCustomInsecureChannelFromFd( + const grpc::string& target, int fd, const grpc::ChannelArguments& args); namespace experimental { @@ -54,10 +54,10 @@ namespace experimental { /// \param fd The file descriptor representing a socket. /// \param args Options for channel creation. /// \param interceptor_creators Vector of interceptor factory objects. -std::shared_ptr CreateCustomInsecureChannelWithInterceptorsFromFd( - const grpc::string& target, int fd, const ChannelArguments& args, +std::shared_ptr CreateCustomInsecureChannelWithInterceptorsFromFd( + const grpc::string& target, int fd, const grpc::ChannelArguments& args, std::unique_ptr>> + std::unique_ptr>> interceptor_creators); } // namespace experimental From 392554e3410e0a4792586e3a97e1b072405d847e Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Fri, 15 Mar 2019 17:19:28 -0700 Subject: [PATCH 070/242] Fixing clang_tidy_format.sh issues. --- include/grpcpp/create_channel_posix.h | 11 ++++++----- include/grpcpp/create_channel_posix_impl.h | 7 ++++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/grpcpp/create_channel_posix.h b/include/grpcpp/create_channel_posix.h index 0e0b352259e..a8c25187b6e 100644 --- a/include/grpcpp/create_channel_posix.h +++ b/include/grpcpp/create_channel_posix.h @@ -25,8 +25,8 @@ namespace grpc { #ifdef GPR_SUPPORT_CHANNELS_FROM_FD -static inline std::shared_ptr CreateInsecureChannelFromFd(const grpc::string& target, - int fd) { +static inline std::shared_ptr CreateInsecureChannelFromFd( + const grpc::string& target, int fd) { return ::grpc_impl::CreateInsecureChannelFromFd(target, fd); } @@ -37,12 +37,14 @@ static inline std::shared_ptr CreateCustomInsecureChannelFromFd( namespace experimental { -static inline std::shared_ptr CreateCustomInsecureChannelWithInterceptorsFromFd( +static inline std::shared_ptr +CreateCustomInsecureChannelWithInterceptorsFromFd( const grpc::string& target, int fd, const ChannelArguments& args, std::unique_ptr>> interceptor_creators) { - return CreateCustomInsecureChannelWithInterceptorsFromFd(target, fd, args, std::move(interceptor_creators)); + return CreateCustomInsecureChannelWithInterceptorsFromFd( + target, fd, args, std::move(interceptor_creators)); } } // namespace experimental @@ -51,5 +53,4 @@ static inline std::shared_ptr CreateCustomInsecureChannelWithIntercepto } // namespace grpc - #endif // GRPCPP_CREATE_CHANNEL_POSIX_H diff --git a/include/grpcpp/create_channel_posix_impl.h b/include/grpcpp/create_channel_posix_impl.h index 7fccfa1c78d..5c11120611a 100644 --- a/include/grpcpp/create_channel_posix_impl.h +++ b/include/grpcpp/create_channel_posix_impl.h @@ -33,8 +33,8 @@ namespace grpc_impl { /// /// \param target The name of the target. /// \param fd The file descriptor representing a socket. -std::shared_ptr CreateInsecureChannelFromFd(const grpc::string& target, - int fd); +std::shared_ptr CreateInsecureChannelFromFd( + const grpc::string& target, int fd); /// Create a new \a Channel communicating over given file descriptor with custom /// channel arguments. @@ -54,7 +54,8 @@ namespace experimental { /// \param fd The file descriptor representing a socket. /// \param args Options for channel creation. /// \param interceptor_creators Vector of interceptor factory objects. -std::shared_ptr CreateCustomInsecureChannelWithInterceptorsFromFd( +std::shared_ptr +CreateCustomInsecureChannelWithInterceptorsFromFd( const grpc::string& target, int fd, const grpc::ChannelArguments& args, std::unique_ptr>> From 130962490bbcf77e048e39fa17dbbc3d54e7f415 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Tue, 19 Mar 2019 11:40:42 -0700 Subject: [PATCH 071/242] Make changes to fix test failures --- include/grpcpp/create_channel_posix.h | 2 +- src/cpp/client/create_channel_posix.cc | 32 +++++++++++++------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/grpcpp/create_channel_posix.h b/include/grpcpp/create_channel_posix.h index a8c25187b6e..8fee2f8f0dd 100644 --- a/include/grpcpp/create_channel_posix.h +++ b/include/grpcpp/create_channel_posix.h @@ -43,7 +43,7 @@ CreateCustomInsecureChannelWithInterceptorsFromFd( std::unique_ptr>> interceptor_creators) { - return CreateCustomInsecureChannelWithInterceptorsFromFd( + return ::grpc_impl::experimental::CreateCustomInsecureChannelWithInterceptorsFromFd( target, fd, args, std::move(interceptor_creators)); } diff --git a/src/cpp/client/create_channel_posix.cc b/src/cpp/client/create_channel_posix.cc index 3affc1ef391..9a55ebc3ec6 100644 --- a/src/cpp/client/create_channel_posix.cc +++ b/src/cpp/client/create_channel_posix.cc @@ -24,45 +24,45 @@ #include "src/cpp/client/create_channel_internal.h" -namespace grpc { +namespace grpc_impl { #ifdef GPR_SUPPORT_CHANNELS_FROM_FD -std::shared_ptr CreateInsecureChannelFromFd(const grpc::string& target, +std::shared_ptr CreateInsecureChannelFromFd(const grpc::string& target, int fd) { - internal::GrpcLibrary init_lib; + grpc::internal::GrpcLibrary init_lib; init_lib.init(); - return CreateChannelInternal( + return grpc::CreateChannelInternal( "", grpc_insecure_channel_create_from_fd(target.c_str(), fd, nullptr), std::vector< - std::unique_ptr>()); + std::unique_ptr>()); } -std::shared_ptr CreateCustomInsecureChannelFromFd( - const grpc::string& target, int fd, const ChannelArguments& args) { - internal::GrpcLibrary init_lib; +std::shared_ptr CreateCustomInsecureChannelFromFd( + const grpc::string& target, int fd, const grpc::ChannelArguments& args) { + grpc::internal::GrpcLibrary init_lib; init_lib.init(); grpc_channel_args channel_args; args.SetChannelArgs(&channel_args); - return CreateChannelInternal( + return grpc::CreateChannelInternal( "", grpc_insecure_channel_create_from_fd(target.c_str(), fd, &channel_args), std::vector< - std::unique_ptr>()); + std::unique_ptr>()); } namespace experimental { -std::shared_ptr CreateCustomInsecureChannelWithInterceptorsFromFd( - const grpc::string& target, int fd, const ChannelArguments& args, +std::shared_ptr CreateCustomInsecureChannelWithInterceptorsFromFd( + const grpc::string& target, int fd, const grpc::ChannelArguments& args, std::vector< - std::unique_ptr> + std::unique_ptr> interceptor_creators) { - internal::GrpcLibrary init_lib; + grpc::internal::GrpcLibrary init_lib; init_lib.init(); grpc_channel_args channel_args; args.SetChannelArgs(&channel_args); - return CreateChannelInternal( + return grpc::CreateChannelInternal( "", grpc_insecure_channel_create_from_fd(target.c_str(), fd, &channel_args), std::move(interceptor_creators)); @@ -72,4 +72,4 @@ std::shared_ptr CreateCustomInsecureChannelWithInterceptorsFromFd( #endif // GPR_SUPPORT_CHANNELS_FROM_FD -} // namespace grpc +} // namespace grpc_impl From 4b0175f2c8e857010f3d201a14b660b78ebd6a17 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Mon, 25 Mar 2019 15:53:22 -0700 Subject: [PATCH 072/242] Fix errors from clang_format_code.sh --- include/grpcpp/create_channel_posix.h | 5 +++-- src/cpp/client/create_channel_posix.cc | 15 ++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/include/grpcpp/create_channel_posix.h b/include/grpcpp/create_channel_posix.h index 8fee2f8f0dd..b8a1f5e5c46 100644 --- a/include/grpcpp/create_channel_posix.h +++ b/include/grpcpp/create_channel_posix.h @@ -43,8 +43,9 @@ CreateCustomInsecureChannelWithInterceptorsFromFd( std::unique_ptr>> interceptor_creators) { - return ::grpc_impl::experimental::CreateCustomInsecureChannelWithInterceptorsFromFd( - target, fd, args, std::move(interceptor_creators)); + return ::grpc_impl::experimental:: + CreateCustomInsecureChannelWithInterceptorsFromFd( + target, fd, args, std::move(interceptor_creators)); } } // namespace experimental diff --git a/src/cpp/client/create_channel_posix.cc b/src/cpp/client/create_channel_posix.cc index 9a55ebc3ec6..6de373577eb 100644 --- a/src/cpp/client/create_channel_posix.cc +++ b/src/cpp/client/create_channel_posix.cc @@ -28,14 +28,14 @@ namespace grpc_impl { #ifdef GPR_SUPPORT_CHANNELS_FROM_FD -std::shared_ptr CreateInsecureChannelFromFd(const grpc::string& target, - int fd) { +std::shared_ptr CreateInsecureChannelFromFd( + const grpc::string& target, int fd) { grpc::internal::GrpcLibrary init_lib; init_lib.init(); return grpc::CreateChannelInternal( "", grpc_insecure_channel_create_from_fd(target.c_str(), fd, nullptr), - std::vector< - std::unique_ptr>()); + std::vector>()); } std::shared_ptr CreateCustomInsecureChannelFromFd( @@ -47,13 +47,14 @@ std::shared_ptr CreateCustomInsecureChannelFromFd( return grpc::CreateChannelInternal( "", grpc_insecure_channel_create_from_fd(target.c_str(), fd, &channel_args), - std::vector< - std::unique_ptr>()); + std::vector>()); } namespace experimental { -std::shared_ptr CreateCustomInsecureChannelWithInterceptorsFromFd( +std::shared_ptr +CreateCustomInsecureChannelWithInterceptorsFromFd( const grpc::string& target, int fd, const grpc::ChannelArguments& args, std::vector< std::unique_ptr> From 850d02d67df90984f3ad0b0d28d658e8177a0f47 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Thu, 14 Mar 2019 15:13:29 -0700 Subject: [PATCH 073/242] Move channelz_service_plugin from grpc to grpc_impl namespace --- BUILD | 1 + CMakeLists.txt | 1 + Makefile | 1 + build.yaml | 1 + include/grpcpp/ext/channelz_service_plugin.h | 19 +-------- .../grpcpp/ext/channelz_service_plugin_impl.h | 41 +++++++++++++++++++ 6 files changed, 46 insertions(+), 18 deletions(-) create mode 100644 include/grpcpp/ext/channelz_service_plugin_impl.h diff --git a/BUILD b/BUILD index 12687c799ef..d91d519b56d 100644 --- a/BUILD +++ b/BUILD @@ -2219,6 +2219,7 @@ grpc_cc_library( language = "c++", public_hdrs = [ "include/grpcpp/ext/channelz_service_plugin.h", + "include/grpcpp/ext/channelz_service_plugin_impl.h", ], deps = [ ":grpc++", diff --git a/CMakeLists.txt b/CMakeLists.txt index d39c1941a74..7dbedbb0327 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4965,6 +4965,7 @@ target_link_libraries(grpcpp_channelz foreach(_hdr include/grpcpp/ext/channelz_service_plugin.h + include/grpcpp/ext/channelz_service_plugin_impl.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) diff --git a/Makefile b/Makefile index 85e621f87bb..c33c2b08a93 100644 --- a/Makefile +++ b/Makefile @@ -7218,6 +7218,7 @@ LIBGRPCPP_CHANNELZ_SRC = \ PUBLIC_HEADERS_CXX += \ include/grpcpp/ext/channelz_service_plugin.h \ + include/grpcpp/ext/channelz_service_plugin_impl.h \ LIBGRPCPP_CHANNELZ_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPCPP_CHANNELZ_SRC)))) diff --git a/build.yaml b/build.yaml index 34b271f58de..0345ccafd4a 100644 --- a/build.yaml +++ b/build.yaml @@ -1917,6 +1917,7 @@ libs: language: c++ public_headers: - include/grpcpp/ext/channelz_service_plugin.h + - include/grpcpp/ext/channelz_service_plugin_impl.h headers: - src/cpp/server/channelz/channelz_service.h src: diff --git a/include/grpcpp/ext/channelz_service_plugin.h b/include/grpcpp/ext/channelz_service_plugin.h index af3192d4513..6358a2bc1f2 100644 --- a/include/grpcpp/ext/channelz_service_plugin.h +++ b/include/grpcpp/ext/channelz_service_plugin.h @@ -19,23 +19,6 @@ #ifndef GRPCPP_EXT_CHANNELZ_SERVICE_PLUGIN_H #define GRPCPP_EXT_CHANNELZ_SERVICE_PLUGIN_H -#include - -#include -#include -#include - -namespace grpc { -namespace channelz { -namespace experimental { - -/// Add channelz server plugin to \a ServerBuilder. This function should -/// be called at static initialization time. This service is experimental -/// for now. Track progress in https://github.com/grpc/grpc/issues/15988. -void InitChannelzService(); - -} // namespace experimental -} // namespace channelz -} // namespace grpc +#include #endif // GRPCPP_EXT_CHANNELZ_SERVICE_PLUGIN_H diff --git a/include/grpcpp/ext/channelz_service_plugin_impl.h b/include/grpcpp/ext/channelz_service_plugin_impl.h new file mode 100644 index 00000000000..3a5f3c4b99e --- /dev/null +++ b/include/grpcpp/ext/channelz_service_plugin_impl.h @@ -0,0 +1,41 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_EXT_CHANNELZ_SERVICE_PLUGIN_IMPL_H +#define GRPCPP_EXT_CHANNELZ_SERVICE_PLUGIN_IMPL_H + +#include + +#include +#include +#include + +namespace grpc_impl { +namespace channelz { +namespace experimental { + +/// Add channelz server plugin to \a ServerBuilder. This function should +/// be called at static initialization time. This service is experimental +/// for now. Track progress in https://github.com/grpc/grpc/issues/15988. +void InitChannelzService(); + +} // namespace experimental +} // namespace channelz +} // namespace grpc_impl + +#endif // GRPCPP_EXT_CHANNELZ_SERVICE_PLUGIN_IMPL_H From b2b1e57337b89cec11d27aee203fc92489fd4724 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Fri, 15 Mar 2019 14:44:20 -0700 Subject: [PATCH 074/242] Fix errors from test scripts. --- include/grpcpp/ext/channelz_service_plugin.h | 12 ++++++++++++ src/cpp/server/channelz/channelz_service_plugin.cc | 12 ++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/include/grpcpp/ext/channelz_service_plugin.h b/include/grpcpp/ext/channelz_service_plugin.h index 6358a2bc1f2..95cb93e3216 100644 --- a/include/grpcpp/ext/channelz_service_plugin.h +++ b/include/grpcpp/ext/channelz_service_plugin.h @@ -21,4 +21,16 @@ #include +namespace grpc { +namespace channelz { +namespace experimental { + +static inline void InitChannelzService() { + ::grpc_impl::channelz::experimental::InitChannelzService(); +} + +} // namespace experimental +} // namespace channelz +} // namespace grpc + #endif // GRPCPP_EXT_CHANNELZ_SERVICE_PLUGIN_H diff --git a/src/cpp/server/channelz/channelz_service_plugin.cc b/src/cpp/server/channelz/channelz_service_plugin.cc index b93e5b551e1..04c6411d5a3 100644 --- a/src/cpp/server/channelz/channelz_service_plugin.cc +++ b/src/cpp/server/channelz/channelz_service_plugin.cc @@ -67,13 +67,21 @@ CreateChannelzServicePlugin() { new ChannelzServicePlugin()); } +} // namespace experimental +} // namespace channelz +} // namespace grpc +namespace grpc_impl { +namespace channelz { +namespace experimental { + void InitChannelzService() { static bool already_here = false; if (already_here) return; already_here = true; - ::grpc::ServerBuilder::InternalAddPluginFactory(&CreateChannelzServicePlugin); + ::grpc::ServerBuilder::InternalAddPluginFactory( + &grpc::channelz::experimental::CreateChannelzServicePlugin); } } // namespace experimental } // namespace channelz -} // namespace grpc +} // namespace grpc_impl From 7b88e58a6cda8ed45ef53ed70d038ae0469106f5 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Mon, 18 Mar 2019 10:04:44 -0700 Subject: [PATCH 075/242] Fix errors from generate project script --- tools/run_tests/generated/sources_and_headers.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 501e53560ab..a5e68b50fdb 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -6921,6 +6921,7 @@ ], "headers": [ "include/grpcpp/ext/channelz_service_plugin.h", + "include/grpcpp/ext/channelz_service_plugin_impl.h", "src/cpp/server/channelz/channelz_service.h" ], "is_filegroup": false, @@ -6928,6 +6929,7 @@ "name": "grpcpp_channelz", "src": [ "include/grpcpp/ext/channelz_service_plugin.h", + "include/grpcpp/ext/channelz_service_plugin_impl.h", "src/cpp/server/channelz/channelz_service.cc", "src/cpp/server/channelz/channelz_service.h", "src/cpp/server/channelz/channelz_service_plugin.cc" From 8e393ea13e2be230f021855e46def4d4e90f28a4 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 26 Mar 2019 02:34:51 -0400 Subject: [PATCH 076/242] rename BindServiceAttribute --- src/compiler/csharp_generator.cc | 2 +- ...indServiceAttribute.cs => BindServiceMethodAttribute.cs} | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename src/csharp/Grpc.Core.Api/{BindServiceAttribute.cs => BindServiceMethodAttribute.cs} (92%) diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index 682ce59efbf..778e5c39284 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -383,7 +383,7 @@ void GenerateServerClass(Printer* out, const ServiceDescriptor* service) { "$servicename$\n", "servicename", GetServiceClassName(service)); out->Print( - "[grpc::BindService(typeof($classname$), " + "[grpc::BindServiceMethod(typeof($classname$), " "\"BindService\")]\n", "classname", GetServiceClassName(service)); out->Print("public abstract partial class $name$\n", "name", diff --git a/src/csharp/Grpc.Core.Api/BindServiceAttribute.cs b/src/csharp/Grpc.Core.Api/BindServiceMethodAttribute.cs similarity index 92% rename from src/csharp/Grpc.Core.Api/BindServiceAttribute.cs rename to src/csharp/Grpc.Core.Api/BindServiceMethodAttribute.cs index d4ac6a10570..329b23dadff 100644 --- a/src/csharp/Grpc.Core.Api/BindServiceAttribute.cs +++ b/src/csharp/Grpc.Core.Api/BindServiceMethodAttribute.cs @@ -27,14 +27,14 @@ namespace Grpc.Core /// instance of the service base class, e.g. static void BindService(ServiceBinderBase, GreeterService). /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] - public class BindServiceAttribute : Attribute + public class BindServiceMethodAttribute : Attribute { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The type the service bind method is defined on. /// The name of the service bind method. - public BindServiceAttribute(Type bindType, string bindMethodName) + public BindServiceMethodAttribute(Type bindType, string bindMethodName) { BindType = bindType; BindMethodName = bindMethodName; From 3624963ec9109f6e7e21c8b1813f797f10cf2076 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 26 Mar 2019 02:43:32 -0400 Subject: [PATCH 077/242] regenerate c# protos --- src/csharp/Grpc.Examples/MathGrpc.cs | 2 +- src/csharp/Grpc.HealthCheck/HealthGrpc.cs | 2 +- src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs | 2 +- src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs | 2 +- src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs | 2 +- .../Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs | 2 +- src/csharp/Grpc.IntegrationTesting/TestGrpc.cs | 6 +++--- src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs | 2 +- src/csharp/Grpc.Reflection/ReflectionGrpc.cs | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index 8315b2be82e..fab64354411 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -67,7 +67,7 @@ namespace Math { } /// Base class for server-side implementations of Math - [grpc::BindService(typeof(Math), "BindService")] + [grpc::BindServiceMethod(typeof(Math), "BindService")] public abstract partial class MathBase { /// diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs index bc7ae6cedf1..7137b907274 100644 --- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs +++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs @@ -54,7 +54,7 @@ namespace Grpc.Health.V1 { } /// Base class for server-side implementations of Health - [grpc::BindService(typeof(Health), "BindService")] + [grpc::BindServiceMethod(typeof(Health), "BindService")] public abstract partial class HealthBase { /// diff --git a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs index 00821bb41bd..5b37b144f2a 100644 --- a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs @@ -74,7 +74,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of BenchmarkService - [grpc::BindService(typeof(BenchmarkService), "BindService")] + [grpc::BindServiceMethod(typeof(BenchmarkService), "BindService")] public abstract partial class BenchmarkServiceBase { /// diff --git a/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs index 20f415f72de..50c6e159206 100644 --- a/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs @@ -39,7 +39,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of EmptyService - [grpc::BindService(typeof(EmptyService), "BindService")] + [grpc::BindServiceMethod(typeof(EmptyService), "BindService")] public abstract partial class EmptyServiceBase { } diff --git a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs index 6e59d1eb6c1..9b11e990d2d 100644 --- a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs @@ -58,7 +58,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of MetricsService - [grpc::BindService(typeof(MetricsService), "BindService")] + [grpc::BindServiceMethod(typeof(MetricsService), "BindService")] public abstract partial class MetricsServiceBase { /// diff --git a/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs index b86dfbf7ec9..1a505ebc764 100644 --- a/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs @@ -46,7 +46,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of ReportQpsScenarioService - [grpc::BindService(typeof(ReportQpsScenarioService), "BindService")] + [grpc::BindServiceMethod(typeof(ReportQpsScenarioService), "BindService")] public abstract partial class ReportQpsScenarioServiceBase { /// diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs index c4aa5249ab9..e7b93094c65 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs @@ -105,7 +105,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of TestService - [grpc::BindService(typeof(TestService), "BindService")] + [grpc::BindServiceMethod(typeof(TestService), "BindService")] public abstract partial class TestServiceBase { /// @@ -581,7 +581,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of UnimplementedService - [grpc::BindService(typeof(UnimplementedService), "BindService")] + [grpc::BindServiceMethod(typeof(UnimplementedService), "BindService")] public abstract partial class UnimplementedServiceBase { /// @@ -721,7 +721,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of ReconnectService - [grpc::BindService(typeof(ReconnectService), "BindService")] + [grpc::BindServiceMethod(typeof(ReconnectService), "BindService")] public abstract partial class ReconnectServiceBase { public virtual global::System.Threading.Tasks.Task Start(global::Grpc.Testing.ReconnectParams request, grpc::ServerCallContext context) diff --git a/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs index 5c079a5ec43..14c26f99a6b 100644 --- a/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs @@ -72,7 +72,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of WorkerService - [grpc::BindService(typeof(WorkerService), "BindService")] + [grpc::BindServiceMethod(typeof(WorkerService), "BindService")] public abstract partial class WorkerServiceBase { /// diff --git a/src/csharp/Grpc.Reflection/ReflectionGrpc.cs b/src/csharp/Grpc.Reflection/ReflectionGrpc.cs index 768879bd2a1..f97b3143a69 100644 --- a/src/csharp/Grpc.Reflection/ReflectionGrpc.cs +++ b/src/csharp/Grpc.Reflection/ReflectionGrpc.cs @@ -46,7 +46,7 @@ namespace Grpc.Reflection.V1Alpha { } /// Base class for server-side implementations of ServerReflection - [grpc::BindService(typeof(ServerReflection), "BindService")] + [grpc::BindServiceMethod(typeof(ServerReflection), "BindService")] public abstract partial class ServerReflectionBase { /// From 996da586675fe6f6553bc3ceed234393caf989f5 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Tue, 26 Mar 2019 08:04:32 -0700 Subject: [PATCH 078/242] Revert "Revert "Moving ::grpc::ServerBuilder to ::grpc_impl::ServerBuilder"" --- BUILD | 1 + CMakeLists.txt | 3 + Makefile | 3 + build.yaml | 1 + gRPC-C++.podspec | 1 + .../grpcpp/impl/codegen/completion_queue.h | 7 +- include/grpcpp/impl/server_builder_plugin.h | 7 +- include/grpcpp/server.h | 2 +- include/grpcpp/server_builder.h | 315 +--------------- include/grpcpp/server_builder_impl.h | 346 ++++++++++++++++++ src/cpp/server/server_builder.cc | 47 +-- tools/doxygen/Doxyfile.c++ | 1 + tools/doxygen/Doxyfile.c++.internal | 1 + .../generated/sources_and_headers.json | 2 + 14 files changed, 397 insertions(+), 340 deletions(-) create mode 100644 include/grpcpp/server_builder_impl.h diff --git a/BUILD b/BUILD index 12687c799ef..5bfc88dc186 100644 --- a/BUILD +++ b/BUILD @@ -247,6 +247,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/security/server_credentials.h", "include/grpcpp/server.h", "include/grpcpp/server_builder.h", + "include/grpcpp/server_builder_impl.h", "include/grpcpp/server_context.h", "include/grpcpp/server_posix.h", "include/grpcpp/support/async_stream.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index d39c1941a74..9fe76cf11cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3025,6 +3025,7 @@ foreach(_hdr include/grpcpp/security/server_credentials.h include/grpcpp/server.h include/grpcpp/server_builder.h + include/grpcpp/server_builder_impl.h include/grpcpp/server_context.h include/grpcpp/server_posix.h include/grpcpp/support/async_stream.h @@ -3616,6 +3617,7 @@ foreach(_hdr include/grpcpp/security/server_credentials.h include/grpcpp/server.h include/grpcpp/server_builder.h + include/grpcpp/server_builder_impl.h include/grpcpp/server_context.h include/grpcpp/server_posix.h include/grpcpp/support/async_stream.h @@ -4579,6 +4581,7 @@ foreach(_hdr include/grpcpp/security/server_credentials.h include/grpcpp/server.h include/grpcpp/server_builder.h + include/grpcpp/server_builder_impl.h include/grpcpp/server_context.h include/grpcpp/server_posix.h include/grpcpp/support/async_stream.h diff --git a/Makefile b/Makefile index 85e621f87bb..055300cef00 100644 --- a/Makefile +++ b/Makefile @@ -5352,6 +5352,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/security/server_credentials.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ + include/grpcpp/server_builder_impl.h \ include/grpcpp/server_context.h \ include/grpcpp/server_posix.h \ include/grpcpp/support/async_stream.h \ @@ -5951,6 +5952,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/security/server_credentials.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ + include/grpcpp/server_builder_impl.h \ include/grpcpp/server_context.h \ include/grpcpp/server_posix.h \ include/grpcpp/support/async_stream.h \ @@ -6863,6 +6865,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/security/server_credentials.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ + include/grpcpp/server_builder_impl.h \ include/grpcpp/server_context.h \ include/grpcpp/server_posix.h \ include/grpcpp/support/async_stream.h \ diff --git a/build.yaml b/build.yaml index 34b271f58de..4251ed9ba01 100644 --- a/build.yaml +++ b/build.yaml @@ -1370,6 +1370,7 @@ filegroups: - include/grpcpp/security/server_credentials.h - include/grpcpp/server.h - include/grpcpp/server_builder.h + - include/grpcpp/server_builder_impl.h - include/grpcpp/server_context.h - include/grpcpp/server_posix.h - include/grpcpp/support/async_stream.h diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 5a850bc8438..282a4a1e76c 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -111,6 +111,7 @@ Pod::Spec.new do |s| 'include/grpcpp/security/server_credentials.h', 'include/grpcpp/server.h', 'include/grpcpp/server_builder.h', + 'include/grpcpp/server_builder_impl.h', 'include/grpcpp/server_context.h', 'include/grpcpp/server_posix.h', 'include/grpcpp/support/async_stream.h', diff --git a/include/grpcpp/impl/codegen/completion_queue.h b/include/grpcpp/impl/codegen/completion_queue.h index 4812f0253d4..73556ce9899 100644 --- a/include/grpcpp/impl/codegen/completion_queue.h +++ b/include/grpcpp/impl/codegen/completion_queue.h @@ -41,6 +41,10 @@ struct grpc_completion_queue; +namespace grpc_impl { + +class ServerBuilder; +} namespace grpc { template @@ -63,7 +67,6 @@ class ChannelInterface; class ClientContext; class CompletionQueue; class Server; -class ServerBuilder; class ServerContext; class ServerInterface; @@ -405,7 +408,7 @@ class ServerCompletionQueue : public CompletionQueue { polling_type_(polling_type) {} grpc_cq_polling_type polling_type_; - friend class ServerBuilder; + friend class ::grpc_impl::ServerBuilder; friend class Server; }; diff --git a/include/grpcpp/impl/server_builder_plugin.h b/include/grpcpp/impl/server_builder_plugin.h index 39450b42d56..2898f8cfae7 100644 --- a/include/grpcpp/impl/server_builder_plugin.h +++ b/include/grpcpp/impl/server_builder_plugin.h @@ -23,9 +23,12 @@ #include -namespace grpc { +namespace grpc_impl { class ServerBuilder; +} +namespace grpc { + class ServerInitializer; class ChannelArguments; @@ -40,7 +43,7 @@ class ServerBuilderPlugin { /// UpdateServerBuilder will be called at an early stage in /// ServerBuilder::BuildAndStart(), right after the ServerBuilderOptions have /// done their updates. - virtual void UpdateServerBuilder(ServerBuilder* builder) {} + virtual void UpdateServerBuilder(grpc_impl::ServerBuilder* builder) {} /// InitServer will be called in ServerBuilder::BuildAndStart(), after the /// Server instance is created. diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index f5c99f22df2..f8947a98cab 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -198,7 +198,7 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { } friend class AsyncGenericService; - friend class ServerBuilder; + friend class ::grpc_impl::ServerBuilder; friend class ServerInitializer; class SyncRequest; diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h index 498e5b7bb31..5b8fc72eeea 100644 --- a/include/grpcpp/server_builder.h +++ b/include/grpcpp/server_builder.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015-2016 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,320 +19,11 @@ #ifndef GRPCPP_SERVER_BUILDER_H #define GRPCPP_SERVER_BUILDER_H -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -struct grpc_resource_quota; +#include namespace grpc { -class AsyncGenericService; -class ResourceQuota; -class CompletionQueue; -class Server; -class ServerCompletionQueue; -class ServerCredentials; -class Service; - -namespace testing { -class ServerBuilderPluginTest; -} // namespace testing - -namespace experimental { -class CallbackGenericService; -} // namespace experimental - -/// A builder class for the creation and startup of \a grpc::Server instances. -class ServerBuilder { - public: - ServerBuilder(); - virtual ~ServerBuilder(); - - ////////////////////////////////////////////////////////////////////////////// - // Primary API's - - /// Return a running server which is ready for processing calls. - /// Before calling, one typically needs to ensure that: - /// 1. a service is registered - so that the server knows what to serve - /// (via RegisterService, or RegisterAsyncGenericService) - /// 2. a listening port has been added - so the server knows where to receive - /// traffic (via AddListeningPort) - /// 3. [for async api only] completion queues have been added via - /// AddCompletionQueue - virtual std::unique_ptr BuildAndStart(); - - /// Register a service. This call does not take ownership of the service. - /// The service must exist for the lifetime of the \a Server instance returned - /// by \a BuildAndStart(). - /// Matches requests with any :authority - ServerBuilder& RegisterService(Service* service); - - /// Enlists an endpoint \a addr (port with an optional IP address) to - /// bind the \a grpc::Server object to be created to. - /// - /// It can be invoked multiple times. - /// - /// \param addr_uri The address to try to bind to the server in URI form. If - /// the scheme name is omitted, "dns:///" is assumed. To bind to any address, - /// please use IPv6 any, i.e., [::]:, which also accepts IPv4 - /// connections. Valid values include dns:///localhost:1234, / - /// 192.168.1.1:31416, dns:///[::1]:27182, etc.). - /// \param creds The credentials associated with the server. - /// \param selected_port[out] If not `nullptr`, gets populated with the port - /// number bound to the \a grpc::Server for the corresponding endpoint after - /// it is successfully bound by BuildAndStart(), 0 otherwise. AddListeningPort - /// does not modify this pointer. - ServerBuilder& AddListeningPort(const grpc::string& addr_uri, - std::shared_ptr creds, - int* selected_port = nullptr); - - /// Add a completion queue for handling asynchronous services. - /// - /// Best performance is typically obtained by using one thread per polling - /// completion queue. - /// - /// Caller is required to shutdown the server prior to shutting down the - /// returned completion queue. Caller is also required to drain the - /// completion queue after shutting it down. A typical usage scenario: - /// - /// // While building the server: - /// ServerBuilder builder; - /// ... - /// cq_ = builder.AddCompletionQueue(); - /// server_ = builder.BuildAndStart(); - /// - /// // While shutting down the server; - /// server_->Shutdown(); - /// cq_->Shutdown(); // Always *after* the associated server's Shutdown()! - /// // Drain the cq_ that was created - /// void* ignored_tag; - /// bool ignored_ok; - /// while (cq_->Next(&ignored_tag, &ignored_ok)) { } - /// - /// \param is_frequently_polled This is an optional parameter to inform gRPC - /// library about whether this completion queue would be frequently polled - /// (i.e. by calling \a Next() or \a AsyncNext()). The default value is - /// 'true' and is the recommended setting. Setting this to 'false' (i.e. - /// not polling the completion queue frequently) will have a significantly - /// negative performance impact and hence should not be used in production - /// use cases. - std::unique_ptr AddCompletionQueue( - bool is_frequently_polled = true); - - ////////////////////////////////////////////////////////////////////////////// - // Less commonly used RegisterService variants - - /// Register a service. This call does not take ownership of the service. - /// The service must exist for the lifetime of the \a Server instance returned - /// by \a BuildAndStart(). - /// Only matches requests with :authority \a host - ServerBuilder& RegisterService(const grpc::string& host, Service* service); - - /// Register a generic service. - /// Matches requests with any :authority - /// This is mostly useful for writing generic gRPC Proxies where the exact - /// serialization format is unknown - ServerBuilder& RegisterAsyncGenericService(AsyncGenericService* service); - - ////////////////////////////////////////////////////////////////////////////// - // Fine control knobs - - /// Set max receive message size in bytes. - /// The default is GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH. - ServerBuilder& SetMaxReceiveMessageSize(int max_receive_message_size) { - max_receive_message_size_ = max_receive_message_size; - return *this; - } - - /// Set max send message size in bytes. - /// The default is GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH. - ServerBuilder& SetMaxSendMessageSize(int max_send_message_size) { - max_send_message_size_ = max_send_message_size; - return *this; - } - - /// \deprecated For backward compatibility. - ServerBuilder& SetMaxMessageSize(int max_message_size) { - return SetMaxReceiveMessageSize(max_message_size); - } - - /// Set the support status for compression algorithms. All algorithms are - /// enabled by default. - /// - /// Incoming calls compressed with an unsupported algorithm will fail with - /// \a GRPC_STATUS_UNIMPLEMENTED. - ServerBuilder& SetCompressionAlgorithmSupportStatus( - grpc_compression_algorithm algorithm, bool enabled); - - /// The default compression level to use for all channel calls in the - /// absence of a call-specific level. - ServerBuilder& SetDefaultCompressionLevel(grpc_compression_level level); - - /// The default compression algorithm to use for all channel calls in the - /// absence of a call-specific level. Note that it overrides any compression - /// level set by \a SetDefaultCompressionLevel. - ServerBuilder& SetDefaultCompressionAlgorithm( - grpc_compression_algorithm algorithm); - - /// Set the attached buffer pool for this server - ServerBuilder& SetResourceQuota(const ResourceQuota& resource_quota); - - ServerBuilder& SetOption(std::unique_ptr option); - - /// Options for synchronous servers. - enum SyncServerOption { - NUM_CQS, ///< Number of completion queues. - MIN_POLLERS, ///< Minimum number of polling threads. - MAX_POLLERS, ///< Maximum number of polling threads. - CQ_TIMEOUT_MSEC ///< Completion queue timeout in milliseconds. - }; - - /// Only useful if this is a Synchronous server. - ServerBuilder& SetSyncServerOption(SyncServerOption option, int value); - - /// Add a channel argument (an escape hatch to tuning core library parameters - /// directly) - template - ServerBuilder& AddChannelArgument(const grpc::string& arg, const T& value) { - return SetOption(MakeChannelArgumentOption(arg, value)); - } - - /// For internal use only: Register a ServerBuilderPlugin factory function. - static void InternalAddPluginFactory( - std::unique_ptr (*CreatePlugin)()); - - /// Enable a server workaround. Do not use unless you know what the workaround - /// does. For explanation and detailed descriptions of workarounds, see - /// doc/workarounds.md. - ServerBuilder& EnableWorkaround(grpc_workaround_list id); - - /// NOTE: class experimental_type is not part of the public API of this class. - /// TODO(yashykt): Integrate into public API when this is no longer - /// experimental. - class experimental_type { - public: - explicit experimental_type(ServerBuilder* builder) : builder_(builder) {} - - void SetInterceptorCreators( - std::vector< - std::unique_ptr> - interceptor_creators) { - builder_->interceptor_creators_ = std::move(interceptor_creators); - } - - ServerBuilder& RegisterCallbackGenericService( - experimental::CallbackGenericService* service); - - private: - ServerBuilder* builder_; - }; - - /// NOTE: The function experimental() is not stable public API. It is a view - /// to the experimental components of this class. It may be changed or removed - /// at any time. - experimental_type experimental() { return experimental_type(this); } - - protected: - /// Experimental, to be deprecated - struct Port { - grpc::string addr; - std::shared_ptr creds; - int* selected_port; - }; - - /// Experimental, to be deprecated - typedef std::unique_ptr HostString; - struct NamedService { - explicit NamedService(Service* s) : service(s) {} - NamedService(const grpc::string& h, Service* s) - : host(new grpc::string(h)), service(s) {} - HostString host; - Service* service; - }; - - /// Experimental, to be deprecated - std::vector ports() { return ports_; } - - /// Experimental, to be deprecated - std::vector services() { - std::vector service_refs; - for (auto& ptr : services_) { - service_refs.push_back(ptr.get()); - } - return service_refs; - } - - /// Experimental, to be deprecated - std::vector options() { - std::vector option_refs; - for (auto& ptr : options_) { - option_refs.push_back(ptr.get()); - } - return option_refs; - } - - private: - friend class ::grpc::testing::ServerBuilderPluginTest; - - struct SyncServerSettings { - SyncServerSettings() - : num_cqs(1), min_pollers(1), max_pollers(2), cq_timeout_msec(10000) {} - - /// Number of server completion queues to create to listen to incoming RPCs. - int num_cqs; - - /// Minimum number of threads per completion queue that should be listening - /// to incoming RPCs. - int min_pollers; - - /// Maximum number of threads per completion queue that can be listening to - /// incoming RPCs. - int max_pollers; - - /// The timeout for server completion queue's AsyncNext call. - int cq_timeout_msec; - }; - - int max_receive_message_size_; - int max_send_message_size_; - std::vector> options_; - std::vector> services_; - std::vector ports_; - - SyncServerSettings sync_server_settings_; - - /// List of completion queues added via \a AddCompletionQueue method. - std::vector cqs_; - - std::shared_ptr creds_; - std::vector> plugins_; - grpc_resource_quota* resource_quota_; - AsyncGenericService* generic_service_{nullptr}; - experimental::CallbackGenericService* callback_generic_service_{nullptr}; - struct { - bool is_set; - grpc_compression_level level; - } maybe_default_compression_level_; - struct { - bool is_set; - grpc_compression_algorithm algorithm; - } maybe_default_compression_algorithm_; - uint32_t enabled_compression_algorithms_bitset_; - std::vector> - interceptor_creators_; -}; - +typedef ::grpc_impl::ServerBuilder ServerBuilder; } // namespace grpc #endif // GRPCPP_SERVER_BUILDER_H diff --git a/include/grpcpp/server_builder_impl.h b/include/grpcpp/server_builder_impl.h new file mode 100644 index 00000000000..a8323c38510 --- /dev/null +++ b/include/grpcpp/server_builder_impl.h @@ -0,0 +1,346 @@ +/* + * + * Copyright 2015-2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_SERVER_BUILDER_IMPL_H +#define GRPCPP_SERVER_BUILDER_IMPL_H + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +struct grpc_resource_quota; + +namespace grpc { + +class AsyncGenericService; +class ResourceQuota; +class CompletionQueue; +class Server; +class ServerCompletionQueue; +class ServerCredentials; +class Service; + +namespace testing { +class ServerBuilderPluginTest; +} // namespace testing + +namespace experimental { +class CallbackGenericService; +} +} // namespace grpc +namespace grpc_impl { + +/// A builder class for the creation and startup of \a grpc::Server instances. +class ServerBuilder { + public: + ServerBuilder(); + virtual ~ServerBuilder(); + + ////////////////////////////////////////////////////////////////////////////// + // Primary API's + + /// Return a running server which is ready for processing calls. + /// Before calling, one typically needs to ensure that: + /// 1. a service is registered - so that the server knows what to serve + /// (via RegisterService, or RegisterAsyncGenericService) + /// 2. a listening port has been added - so the server knows where to receive + /// traffic (via AddListeningPort) + /// 3. [for async api only] completion queues have been added via + /// AddCompletionQueue + virtual std::unique_ptr BuildAndStart(); + + /// Register a service. This call does not take ownership of the service. + /// The service must exist for the lifetime of the \a Server instance returned + /// by \a BuildAndStart(). + /// Matches requests with any :authority + ServerBuilder& RegisterService(grpc::Service* service); + + /// Enlists an endpoint \a addr (port with an optional IP address) to + /// bind the \a grpc::Server object to be created to. + /// + /// It can be invoked multiple times. + /// + /// \param addr_uri The address to try to bind to the server in URI form. If + /// the scheme name is omitted, "dns:///" is assumed. To bind to any address, + /// please use IPv6 any, i.e., [::]:, which also accepts IPv4 + /// connections. Valid values include dns:///localhost:1234, / + /// 192.168.1.1:31416, dns:///[::1]:27182, etc.). + /// \param creds The credentials associated with the server. + /// \param selected_port[out] If not `nullptr`, gets populated with the port + /// number bound to the \a grpc::Server for the corresponding endpoint after + /// it is successfully bound by BuildAndStart(), 0 otherwise. AddListeningPort + /// does not modify this pointer. + ServerBuilder& AddListeningPort( + const grpc::string& addr_uri, + std::shared_ptr creds, + int* selected_port = nullptr); + + /// Add a completion queue for handling asynchronous services. + /// + /// Best performance is typically obtained by using one thread per polling + /// completion queue. + /// + /// Caller is required to shutdown the server prior to shutting down the + /// returned completion queue. Caller is also required to drain the + /// completion queue after shutting it down. A typical usage scenario: + /// + /// // While building the server: + /// ServerBuilder builder; + /// ... + /// cq_ = builder.AddCompletionQueue(); + /// server_ = builder.BuildAndStart(); + /// + /// // While shutting down the server; + /// server_->Shutdown(); + /// cq_->Shutdown(); // Always *after* the associated server's Shutdown()! + /// // Drain the cq_ that was created + /// void* ignored_tag; + /// bool ignored_ok; + /// while (cq_->Next(&ignored_tag, &ignored_ok)) { } + /// + /// \param is_frequently_polled This is an optional parameter to inform gRPC + /// library about whether this completion queue would be frequently polled + /// (i.e. by calling \a Next() or \a AsyncNext()). The default value is + /// 'true' and is the recommended setting. Setting this to 'false' (i.e. + /// not polling the completion queue frequently) will have a significantly + /// negative performance impact and hence should not be used in production + /// use cases. + std::unique_ptr AddCompletionQueue( + bool is_frequently_polled = true); + + ////////////////////////////////////////////////////////////////////////////// + // Less commonly used RegisterService variants + + /// Register a service. This call does not take ownership of the service. + /// The service must exist for the lifetime of the \a Server instance + /// returned by \a BuildAndStart(). Only matches requests with :authority \a + /// host + ServerBuilder& RegisterService(const grpc::string& host, + grpc::Service* service); + + /// Register a generic service. + /// Matches requests with any :authority + /// This is mostly useful for writing generic gRPC Proxies where the exact + /// serialization format is unknown + ServerBuilder& RegisterAsyncGenericService( + grpc::AsyncGenericService* service); + + ////////////////////////////////////////////////////////////////////////////// + // Fine control knobs + + /// Set max receive message size in bytes. + /// The default is GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH. + ServerBuilder& SetMaxReceiveMessageSize(int max_receive_message_size) { + max_receive_message_size_ = max_receive_message_size; + return *this; + } + + /// Set max send message size in bytes. + /// The default is GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH. + ServerBuilder& SetMaxSendMessageSize(int max_send_message_size) { + max_send_message_size_ = max_send_message_size; + return *this; + } + + /// \deprecated For backward compatibility. + ServerBuilder& SetMaxMessageSize(int max_message_size) { + return SetMaxReceiveMessageSize(max_message_size); + } + + /// Set the support status for compression algorithms. All algorithms are + /// enabled by default. + /// + /// Incoming calls compressed with an unsupported algorithm will fail with + /// \a GRPC_STATUS_UNIMPLEMENTED. + ServerBuilder& SetCompressionAlgorithmSupportStatus( + grpc_compression_algorithm algorithm, bool enabled); + + /// The default compression level to use for all channel calls in the + /// absence of a call-specific level. + ServerBuilder& SetDefaultCompressionLevel(grpc_compression_level level); + + /// The default compression algorithm to use for all channel calls in the + /// absence of a call-specific level. Note that it overrides any compression + /// level set by \a SetDefaultCompressionLevel. + ServerBuilder& SetDefaultCompressionAlgorithm( + grpc_compression_algorithm algorithm); + + /// Set the attached buffer pool for this server + ServerBuilder& SetResourceQuota(const grpc::ResourceQuota& resource_quota); + + ServerBuilder& SetOption(std::unique_ptr option); + + /// Options for synchronous servers. + enum SyncServerOption { + NUM_CQS, ///< Number of completion queues. + MIN_POLLERS, ///< Minimum number of polling threads. + MAX_POLLERS, ///< Maximum number of polling threads. + CQ_TIMEOUT_MSEC ///< Completion queue timeout in milliseconds. + }; + + /// Only useful if this is a Synchronous server. + ServerBuilder& SetSyncServerOption(SyncServerOption option, int value); + + /// Add a channel argument (an escape hatch to tuning core library parameters + /// directly) + template + ServerBuilder& AddChannelArgument(const grpc::string& arg, const T& value) { + return SetOption(grpc::MakeChannelArgumentOption(arg, value)); + } + + /// For internal use only: Register a ServerBuilderPlugin factory function. + static void InternalAddPluginFactory( + std::unique_ptr (*CreatePlugin)()); + + /// Enable a server workaround. Do not use unless you know what the workaround + /// does. For explanation and detailed descriptions of workarounds, see + /// doc/workarounds.md. + ServerBuilder& EnableWorkaround(grpc_workaround_list id); + + /// NOTE: class experimental_type is not part of the public API of this class. + /// TODO(yashykt): Integrate into public API when this is no longer + /// experimental. + class experimental_type { + public: + explicit experimental_type(grpc_impl::ServerBuilder* builder) + : builder_(builder) {} + + void SetInterceptorCreators( + std::vector> + interceptor_creators) { + builder_->interceptor_creators_ = std::move(interceptor_creators); + } + + ServerBuilder& RegisterCallbackGenericService( + grpc::experimental::CallbackGenericService* service); + + private: + ServerBuilder* builder_; + }; + + /// NOTE: The function experimental() is not stable public API. It is a view + /// to the experimental components of this class. It may be changed or removed + /// at any time. + experimental_type experimental() { return experimental_type(this); } + + protected: + /// Experimental, to be deprecated + struct Port { + grpc::string addr; + std::shared_ptr creds; + int* selected_port; + }; + + /// Experimental, to be deprecated + typedef std::unique_ptr HostString; + struct NamedService { + explicit NamedService(grpc::Service* s) : service(s) {} + NamedService(const grpc::string& h, grpc::Service* s) + : host(new grpc::string(h)), service(s) {} + HostString host; + grpc::Service* service; + }; + + /// Experimental, to be deprecated + std::vector ports() { return ports_; } + + /// Experimental, to be deprecated + std::vector services() { + std::vector service_refs; + for (auto& ptr : services_) { + service_refs.push_back(ptr.get()); + } + return service_refs; + } + + /// Experimental, to be deprecated + std::vector options() { + std::vector option_refs; + for (auto& ptr : options_) { + option_refs.push_back(ptr.get()); + } + return option_refs; + } + + private: + friend class ::grpc::testing::ServerBuilderPluginTest; + + struct SyncServerSettings { + SyncServerSettings() + : num_cqs(1), min_pollers(1), max_pollers(2), cq_timeout_msec(10000) {} + + /// Number of server completion queues to create to listen to incoming RPCs. + int num_cqs; + + /// Minimum number of threads per completion queue that should be listening + /// to incoming RPCs. + int min_pollers; + + /// Maximum number of threads per completion queue that can be listening to + /// incoming RPCs. + int max_pollers; + + /// The timeout for server completion queue's AsyncNext call. + int cq_timeout_msec; + }; + + int max_receive_message_size_; + int max_send_message_size_; + std::vector> options_; + std::vector> services_; + std::vector ports_; + + SyncServerSettings sync_server_settings_; + + /// List of completion queues added via \a AddCompletionQueue method. + std::vector cqs_; + + std::shared_ptr creds_; + std::vector> plugins_; + grpc_resource_quota* resource_quota_; + grpc::AsyncGenericService* generic_service_{nullptr}; + grpc::experimental::CallbackGenericService* callback_generic_service_{ + nullptr}; + struct { + bool is_set; + grpc_compression_level level; + } maybe_default_compression_level_; + struct { + bool is_set; + grpc_compression_algorithm algorithm; + } maybe_default_compression_algorithm_; + uint32_t enabled_compression_algorithms_bitset_; + std::vector< + std::unique_ptr> + interceptor_creators_; +}; + +} // namespace grpc_impl + +#endif // GRPCPP_SERVER_BUILDER_IMPL_H diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index cd0e516d9a3..c0cb706a5b1 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -29,15 +29,15 @@ #include "src/core/lib/gpr/useful.h" #include "src/cpp/server/thread_pool_interface.h" -namespace grpc { +namespace grpc_impl { -static std::vector (*)()>* +static std::vector (*)()>* g_plugin_factory_list; static gpr_once once_init_plugin_list = GPR_ONCE_INIT; static void do_plugin_list_init(void) { g_plugin_factory_list = - new std::vector (*)()>(); + new std::vector (*)()>(); } ServerBuilder::ServerBuilder() @@ -67,29 +67,29 @@ ServerBuilder::~ServerBuilder() { } } -std::unique_ptr ServerBuilder::AddCompletionQueue( +std::unique_ptr ServerBuilder::AddCompletionQueue( bool is_frequently_polled) { - ServerCompletionQueue* cq = new ServerCompletionQueue( + grpc::ServerCompletionQueue* cq = new grpc::ServerCompletionQueue( GRPC_CQ_NEXT, is_frequently_polled ? GRPC_CQ_DEFAULT_POLLING : GRPC_CQ_NON_LISTENING, nullptr); cqs_.push_back(cq); - return std::unique_ptr(cq); + return std::unique_ptr(cq); } -ServerBuilder& ServerBuilder::RegisterService(Service* service) { +ServerBuilder& ServerBuilder::RegisterService(grpc::Service* service) { services_.emplace_back(new NamedService(service)); return *this; } ServerBuilder& ServerBuilder::RegisterService(const grpc::string& addr, - Service* service) { + grpc::Service* service) { services_.emplace_back(new NamedService(addr, service)); return *this; } ServerBuilder& ServerBuilder::RegisterAsyncGenericService( - AsyncGenericService* service) { + grpc::AsyncGenericService* service) { if (generic_service_ || callback_generic_service_) { gpr_log(GPR_ERROR, "Adding multiple generic services is unsupported for now. " @@ -102,7 +102,7 @@ ServerBuilder& ServerBuilder::RegisterAsyncGenericService( } ServerBuilder& ServerBuilder::experimental_type::RegisterCallbackGenericService( - experimental::CallbackGenericService* service) { + grpc::experimental::CallbackGenericService* service) { if (builder_->generic_service_ || builder_->callback_generic_service_) { gpr_log(GPR_ERROR, "Adding multiple generic services is unsupported for now. " @@ -115,7 +115,7 @@ ServerBuilder& ServerBuilder::experimental_type::RegisterCallbackGenericService( } ServerBuilder& ServerBuilder::SetOption( - std::unique_ptr option) { + std::unique_ptr option) { options_.push_back(std::move(option)); return *this; } @@ -174,8 +174,8 @@ ServerBuilder& ServerBuilder::SetResourceQuota( } ServerBuilder& ServerBuilder::AddListeningPort( - const grpc::string& addr_uri, std::shared_ptr creds, - int* selected_port) { + const grpc::string& addr_uri, + std::shared_ptr creds, int* selected_port) { const grpc::string uri_scheme = "dns:"; grpc::string addr = addr_uri; if (addr_uri.compare(0, uri_scheme.size(), uri_scheme) == 0) { @@ -188,8 +188,8 @@ ServerBuilder& ServerBuilder::AddListeningPort( return *this; } -std::unique_ptr ServerBuilder::BuildAndStart() { - ChannelArguments args; +std::unique_ptr ServerBuilder::BuildAndStart() { + grpc::ChannelArguments args; for (auto option = options_.begin(); option != options_.end(); ++option) { (*option)->UpdateArguments(&args); (*option)->UpdatePlugins(&plugins_); @@ -251,9 +251,10 @@ std::unique_ptr ServerBuilder::BuildAndStart() { // This is different from the completion queues added to the server via // ServerBuilder's AddCompletionQueue() method (those completion queues // are in 'cqs_' member variable of ServerBuilder object) - std::shared_ptr>> - sync_server_cqs(std::make_shared< - std::vector>>()); + std::shared_ptr>> + sync_server_cqs( + std::make_shared< + std::vector>>()); bool has_frequently_polled_cqs = false; for (auto it = cqs_.begin(); it != cqs_.end(); ++it) { @@ -282,7 +283,7 @@ std::unique_ptr ServerBuilder::BuildAndStart() { // Create completion queues to listen to incoming rpc requests for (int i = 0; i < sync_server_settings_.num_cqs; i++) { sync_server_cqs->emplace_back( - new ServerCompletionQueue(GRPC_CQ_NEXT, polling_type, nullptr)); + new grpc::ServerCompletionQueue(GRPC_CQ_NEXT, polling_type, nullptr)); } } @@ -303,13 +304,13 @@ std::unique_ptr ServerBuilder::BuildAndStart() { gpr_log(GPR_INFO, "Callback server."); } - std::unique_ptr server(new Server( + std::unique_ptr server(new grpc::Server( max_receive_message_size_, &args, sync_server_cqs, sync_server_settings_.min_pollers, sync_server_settings_.max_pollers, sync_server_settings_.cq_timeout_msec, resource_quota_, std::move(interceptor_creators_))); - ServerInitializer* initializer = server->initializer(); + grpc::ServerInitializer* initializer = server->initializer(); // Register all the completion queues with the server. i.e // 1. sync_server_cqs: internal completion queues created IF this is a sync @@ -393,7 +394,7 @@ std::unique_ptr ServerBuilder::BuildAndStart() { } void ServerBuilder::InternalAddPluginFactory( - std::unique_ptr (*CreatePlugin)()) { + std::unique_ptr (*CreatePlugin)()) { gpr_once_init(&once_init_plugin_list, do_plugin_list_init); (*g_plugin_factory_list).push_back(CreatePlugin); } @@ -408,4 +409,4 @@ ServerBuilder& ServerBuilder::EnableWorkaround(grpc_workaround_list id) { } } -} // namespace grpc +} // namespace grpc_impl diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 9f17a25298a..49f0419bacf 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -1001,6 +1001,7 @@ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ +include/grpcpp/server_builder_impl.h \ include/grpcpp/server_context.h \ include/grpcpp/server_posix.h \ include/grpcpp/support/async_stream.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index c0078bf2764..937ed0e6749 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -1003,6 +1003,7 @@ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ +include/grpcpp/server_builder_impl.h \ include/grpcpp/server_context.h \ include/grpcpp/server_posix.h \ include/grpcpp/support/async_stream.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 501e53560ab..5e116090819 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -10089,6 +10089,7 @@ "include/grpcpp/security/server_credentials.h", "include/grpcpp/server.h", "include/grpcpp/server_builder.h", + "include/grpcpp/server_builder_impl.h", "include/grpcpp/server_context.h", "include/grpcpp/server_posix.h", "include/grpcpp/support/async_stream.h", @@ -10198,6 +10199,7 @@ "include/grpcpp/security/server_credentials.h", "include/grpcpp/server.h", "include/grpcpp/server_builder.h", + "include/grpcpp/server_builder_impl.h", "include/grpcpp/server_context.h", "include/grpcpp/server_posix.h", "include/grpcpp/support/async_stream.h", From 9ff845961ea95c6beb4236fac3770fcc21b768b0 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Tue, 26 Mar 2019 19:21:18 +0100 Subject: [PATCH 079/242] Breakout of #18445 - part 2 --- src/core/lib/transport/transport.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index 9d4b5615e57..8631a1af81f 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -273,40 +273,40 @@ struct grpc_transport_stream_op_batch_payload { /** Transport op: a set of operations to perform on a transport as a whole */ typedef struct grpc_transport_op { /** Called when processing of this op is done. */ - grpc_closure* on_consumed; + grpc_closure* on_consumed = nullptr; /** connectivity monitoring - set connectivity_state to NULL to unsubscribe */ - grpc_closure* on_connectivity_state_change; - grpc_connectivity_state* connectivity_state; + grpc_closure* on_connectivity_state_change = nullptr; + grpc_connectivity_state* connectivity_state = nullptr; /** should the transport be disconnected * Error contract: the transport that gets this op must cause * disconnect_with_error to be unref'ed after processing it */ - grpc_error* disconnect_with_error; + grpc_error* disconnect_with_error = nullptr; /** what should the goaway contain? * Error contract: the transport that gets this op must cause * goaway_error to be unref'ed after processing it */ - grpc_error* goaway_error; + grpc_error* goaway_error = nullptr; /** set the callback for accepting new streams; this is a permanent callback, unlike the other one-shot closures. If true, the callback is set to set_accept_stream_fn, with its user_data argument set to set_accept_stream_user_data */ - bool set_accept_stream; + bool set_accept_stream = false; void (*set_accept_stream_fn)(void* user_data, grpc_transport* transport, - const void* server_data); - void* set_accept_stream_user_data; + const void* server_data) = nullptr; + void* set_accept_stream_user_data = nullptr; /** add this transport to a pollset */ - grpc_pollset* bind_pollset; + grpc_pollset* bind_pollset = nullptr; /** add this transport to a pollset_set */ - grpc_pollset_set* bind_pollset_set; + grpc_pollset_set* bind_pollset_set = nullptr; /** send a ping, if either on_initiate or on_ack is not NULL */ struct { /** Ping may be delayed by the transport, on_initiate callback will be called when the ping is actually being sent. */ - grpc_closure* on_initiate; + grpc_closure* on_initiate = nullptr; /** Called when the ping ack is received */ - grpc_closure* on_ack; + grpc_closure* on_ack = nullptr; } send_ping; // If true, will reset the channel's connection backoff. - bool reset_connect_backoff; + bool reset_connect_backoff = false; /*************************************************************************** * remaining fields are initialized and used at the discretion of the From 084ebec9af83b524567abd71fa8886708d516196 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 26 Mar 2019 15:41:19 -0700 Subject: [PATCH 080/242] Update jessie-backports URL --- templates/tools/dockerfile/cmake_jessie_backports.include | 2 +- test/distrib/cpp/run_distrib_test_cmake.sh | 3 +-- test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh | 3 +-- tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile | 2 +- tools/dockerfile/grpc_artifact_linux_x64/Dockerfile | 2 +- tools/dockerfile/grpc_artifact_linux_x86/Dockerfile | 2 +- tools/dockerfile/test/cxx_jessie_x64/Dockerfile | 2 +- tools/dockerfile/test/cxx_jessie_x86/Dockerfile | 2 +- tools/dockerfile/test/fuzzer/Dockerfile | 2 +- 9 files changed, 9 insertions(+), 11 deletions(-) diff --git a/templates/tools/dockerfile/cmake_jessie_backports.include b/templates/tools/dockerfile/cmake_jessie_backports.include index 2fc49dc8d60..6acb991cd78 100644 --- a/templates/tools/dockerfile/cmake_jessie_backports.include +++ b/templates/tools/dockerfile/cmake_jessie_backports.include @@ -2,5 +2,5 @@ # Use cmake 3.6 from jessie-backports # should only be used for images based on debian jessie. -RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean diff --git a/test/distrib/cpp/run_distrib_test_cmake.sh b/test/distrib/cpp/run_distrib_test_cmake.sh index 6ec3cab6024..06406a40d29 100755 --- a/test/distrib/cpp/run_distrib_test_cmake.sh +++ b/test/distrib/cpp/run_distrib_test_cmake.sh @@ -17,7 +17,7 @@ set -ex cd "$(dirname "$0")/../../.." -echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list apt-get update apt-get install -t jessie-backports -y libssl-dev @@ -63,4 +63,3 @@ mkdir -p cmake/build cd cmake/build cmake ../.. make - diff --git a/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh b/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh index 163527fbd50..59d7674db6d 100755 --- a/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh +++ b/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh @@ -17,7 +17,7 @@ set -ex cd "$(dirname "$0")/../../.." -echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list apt-get update apt-get install -t jessie-backports -y libssl-dev @@ -38,4 +38,3 @@ mkdir -p cmake/build cd cmake/build cmake ../.. make - diff --git a/tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile b/tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile index 894f114951c..dcab64aaeae 100644 --- a/tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile +++ b/tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile @@ -29,7 +29,7 @@ RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y golang && apt-get clean -RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean CMD ["bash"] diff --git a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile index f247cc9ca54..5b2b3dbf6de 100644 --- a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile +++ b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile @@ -72,7 +72,7 @@ RUN apt-get update && apt-get install -y \ # C# dependencies (needed to build grpc_csharp_ext) # Use cmake 3.6 from jessie-backports -RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean RUN mkdir /var/local/jenkins diff --git a/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile index e403f75b594..ee0a7105389 100644 --- a/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile +++ b/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile @@ -64,7 +64,7 @@ RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-ri --no-rdoc" # C# dependencies (needed to build grpc_csharp_ext) # Use cmake 3.6 from jessie-backports -RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean RUN mkdir /var/local/jenkins diff --git a/tools/dockerfile/test/cxx_jessie_x64/Dockerfile b/tools/dockerfile/test/cxx_jessie_x64/Dockerfile index f9dc8f20d7c..c801edfa386 100644 --- a/tools/dockerfile/test/cxx_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/cxx_jessie_x64/Dockerfile @@ -76,7 +76,7 @@ RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev c # Use cmake 3.6 from jessie-backports # should only be used for images based on debian jessie. -RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean diff --git a/tools/dockerfile/test/cxx_jessie_x86/Dockerfile b/tools/dockerfile/test/cxx_jessie_x86/Dockerfile index 76015c8c42d..3fdbb27f6e1 100644 --- a/tools/dockerfile/test/cxx_jessie_x86/Dockerfile +++ b/tools/dockerfile/test/cxx_jessie_x86/Dockerfile @@ -79,7 +79,7 @@ RUN mkdir /var/local/jenkins # Use cmake 3.6 from jessie-backports # should only be used for images based on debian jessie. -RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean diff --git a/tools/dockerfile/test/fuzzer/Dockerfile b/tools/dockerfile/test/fuzzer/Dockerfile index 7f871f2f62a..ef9305bcc8d 100644 --- a/tools/dockerfile/test/fuzzer/Dockerfile +++ b/tools/dockerfile/test/fuzzer/Dockerfile @@ -76,7 +76,7 @@ RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev c # Use cmake 3.6 from jessie-backports # should only be used for images based on debian jessie. -RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean #================= From 93dc0d6ec3c4a3146d06d307db8b196f9be3f450 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 26 Mar 2019 17:43:20 -0700 Subject: [PATCH 081/242] Update fix with new information from post --- templates/tools/dockerfile/cmake_jessie_backports.include | 4 ++-- test/distrib/cpp/run_distrib_test_cmake.sh | 4 ++-- test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh | 4 ++-- tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile | 4 ++-- tools/dockerfile/grpc_artifact_linux_x64/Dockerfile | 4 ++-- tools/dockerfile/grpc_artifact_linux_x86/Dockerfile | 4 ++-- tools/dockerfile/test/cxx_jessie_x64/Dockerfile | 4 ++-- tools/dockerfile/test/cxx_jessie_x86/Dockerfile | 4 ++-- tools/dockerfile/test/fuzzer/Dockerfile | 4 ++-- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/templates/tools/dockerfile/cmake_jessie_backports.include b/templates/tools/dockerfile/cmake_jessie_backports.include index 6acb991cd78..1da6ed79190 100644 --- a/templates/tools/dockerfile/cmake_jessie_backports.include +++ b/templates/tools/dockerfile/cmake_jessie_backports.include @@ -2,5 +2,5 @@ # Use cmake 3.6 from jessie-backports # should only be used for images based on debian jessie. -RUN echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean +RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN apt-get -o Acquire::Check-Valid-Until=false update && apt-get install -t jessie-backports -y cmake && apt-get clean diff --git a/test/distrib/cpp/run_distrib_test_cmake.sh b/test/distrib/cpp/run_distrib_test_cmake.sh index 06406a40d29..f0e1b8c8e39 100755 --- a/test/distrib/cpp/run_distrib_test_cmake.sh +++ b/test/distrib/cpp/run_distrib_test_cmake.sh @@ -17,8 +17,8 @@ set -ex cd "$(dirname "$0")/../../.." -echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -apt-get update +echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +apt-get -o Acquire::Check-Valid-Until=false update apt-get install -t jessie-backports -y libssl-dev # Install c-ares diff --git a/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh b/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh index 59d7674db6d..ea37bd53b4f 100755 --- a/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh +++ b/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh @@ -17,8 +17,8 @@ set -ex cd "$(dirname "$0")/../../.." -echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -apt-get update +echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +apt-get -o Acquire::Check-Valid-Until=false update apt-get install -t jessie-backports -y libssl-dev # To increase the confidence that gRPC installation works without depending on diff --git a/tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile b/tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile index dcab64aaeae..d157a278b1e 100644 --- a/tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile +++ b/tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile @@ -29,7 +29,7 @@ RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y golang && apt-get clean -RUN echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean +RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN apt-get -o Acquire::Check-Valid-Until=false update && apt-get install -t jessie-backports -y cmake && apt-get clean CMD ["bash"] diff --git a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile index 5b2b3dbf6de..07564dc40a9 100644 --- a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile +++ b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile @@ -72,8 +72,8 @@ RUN apt-get update && apt-get install -y \ # C# dependencies (needed to build grpc_csharp_ext) # Use cmake 3.6 from jessie-backports -RUN echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean +RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN apt-get -o Acquire::Check-Valid-Until=false update && apt-get install -t jessie-backports -y cmake && apt-get clean RUN mkdir /var/local/jenkins diff --git a/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile index ee0a7105389..55091f4fffa 100644 --- a/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile +++ b/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile @@ -64,8 +64,8 @@ RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-ri --no-rdoc" # C# dependencies (needed to build grpc_csharp_ext) # Use cmake 3.6 from jessie-backports -RUN echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean +RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN apt-get -o Acquire::Check-Valid-Until=false update && apt-get install -t jessie-backports -y cmake && apt-get clean RUN mkdir /var/local/jenkins diff --git a/tools/dockerfile/test/cxx_jessie_x64/Dockerfile b/tools/dockerfile/test/cxx_jessie_x64/Dockerfile index c801edfa386..6afad4869fd 100644 --- a/tools/dockerfile/test/cxx_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/cxx_jessie_x64/Dockerfile @@ -76,8 +76,8 @@ RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev c # Use cmake 3.6 from jessie-backports # should only be used for images based on debian jessie. -RUN echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean +RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN apt-get -o Acquire::Check-Valid-Until=false update && apt-get install -t jessie-backports -y cmake && apt-get clean RUN mkdir /var/local/jenkins diff --git a/tools/dockerfile/test/cxx_jessie_x86/Dockerfile b/tools/dockerfile/test/cxx_jessie_x86/Dockerfile index 3fdbb27f6e1..c153cd037e6 100644 --- a/tools/dockerfile/test/cxx_jessie_x86/Dockerfile +++ b/tools/dockerfile/test/cxx_jessie_x86/Dockerfile @@ -79,8 +79,8 @@ RUN mkdir /var/local/jenkins # Use cmake 3.6 from jessie-backports # should only be used for images based on debian jessie. -RUN echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean +RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN apt-get -o Acquire::Check-Valid-Until=false update && apt-get install -t jessie-backports -y cmake && apt-get clean # Install gcc-4.8 and other relevant items diff --git a/tools/dockerfile/test/fuzzer/Dockerfile b/tools/dockerfile/test/fuzzer/Dockerfile index ef9305bcc8d..591ca0ce014 100644 --- a/tools/dockerfile/test/fuzzer/Dockerfile +++ b/tools/dockerfile/test/fuzzer/Dockerfile @@ -76,8 +76,8 @@ RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev c # Use cmake 3.6 from jessie-backports # should only be used for images based on debian jessie. -RUN echo "deb [check-valid-until=no] http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean +RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN apt-get -o Acquire::Check-Valid-Until=false update && apt-get install -t jessie-backports -y cmake && apt-get clean #================= # Update clang to a version with improved tsan and fuzzing capabilities From cdf3e001cb9aa26e8ef9af4f58cbdc252e139afa Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Wed, 27 Mar 2019 10:26:41 -0700 Subject: [PATCH 082/242] wip selective build for windows --- bazel/grpc_build_system.bzl | 20 +++++++++++--------- test/core/end2end/generate_tests.bzl | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/bazel/grpc_build_system.bzl b/bazel/grpc_build_system.bzl index c5eb9ec8bf3..84455cdafc2 100644 --- a/bazel/grpc_build_system.bzl +++ b/bazel/grpc_build_system.bzl @@ -28,12 +28,6 @@ load("//bazel:cc_grpc_library.bzl", "cc_grpc_library") # The set of pollers to test against if a test exercises polling POLLERS = ["epollex", "epoll1", "poll"] -def is_msvc(): - return select({ - "//:windows_msvc": True, - "//conditions:default": False, - }) - def if_not_windows(a): return select({ "//:windows": [], @@ -157,7 +151,6 @@ def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data if language.upper() == "C": copts = copts + if_not_windows(["-std=c99"]) args = { - "name": name, "srcs": srcs, "args": args, "data": data, @@ -172,8 +165,17 @@ def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data # Only run targets with pollers for non-MSVC # Only run targets without pollers for MSVC native.cc_test( + name = name, + testonly = True, + tags = [ + "manual", + "no_windows", + ], + **args + ) + native.cc_test( + name = name + "_windows", testonly = True, - tags = tags if is_msvc() else ["manual"], **args ) for poller in POLLERS: @@ -189,7 +191,7 @@ def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data poller, "$(location %s)" % name, ] + args["args"], - tags = (tags + ["no_windows"]) if is_msvc() else tags, + tags = (tags + ["no_windows"]), exec_compatible_with = exec_compatible_with, ) else: diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index 8020780a909..fa666bac976 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -15,7 +15,7 @@ """Generates the appropriate build.json data for all the end2end tests.""" -load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "is_msvc") +load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library") POLLERS = ["epollex", "epoll1", "poll"] From 961f25bd2752549f4f4c5fadf605cf3770cd1ee0 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Wed, 27 Mar 2019 11:13:02 -0700 Subject: [PATCH 083/242] Slightly different check-valid-until fix --- templates/tools/dockerfile/cmake_jessie_backports.include | 3 ++- test/distrib/cpp/run_distrib_test_cmake.sh | 3 ++- test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh | 3 ++- tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile | 3 ++- tools/dockerfile/grpc_artifact_linux_x64/Dockerfile | 3 ++- tools/dockerfile/grpc_artifact_linux_x86/Dockerfile | 3 ++- tools/dockerfile/test/cxx_jessie_x64/Dockerfile | 3 ++- tools/dockerfile/test/cxx_jessie_x86/Dockerfile | 3 ++- tools/dockerfile/test/fuzzer/Dockerfile | 3 ++- 9 files changed, 18 insertions(+), 9 deletions(-) diff --git a/templates/tools/dockerfile/cmake_jessie_backports.include b/templates/tools/dockerfile/cmake_jessie_backports.include index 1da6ed79190..ad08dc95451 100644 --- a/templates/tools/dockerfile/cmake_jessie_backports.include +++ b/templates/tools/dockerfile/cmake_jessie_backports.include @@ -3,4 +3,5 @@ # should only be used for images based on debian jessie. RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -RUN apt-get -o Acquire::Check-Valid-Until=false update && apt-get install -t jessie-backports -y cmake && apt-get clean +RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf +RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean diff --git a/test/distrib/cpp/run_distrib_test_cmake.sh b/test/distrib/cpp/run_distrib_test_cmake.sh index f0e1b8c8e39..d3ecde7cf88 100755 --- a/test/distrib/cpp/run_distrib_test_cmake.sh +++ b/test/distrib/cpp/run_distrib_test_cmake.sh @@ -18,7 +18,8 @@ set -ex cd "$(dirname "$0")/../../.." echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -apt-get -o Acquire::Check-Valid-Until=false update +echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf +apt-get update apt-get install -t jessie-backports -y libssl-dev # Install c-ares diff --git a/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh b/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh index ea37bd53b4f..58d98a9124a 100755 --- a/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh +++ b/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh @@ -18,7 +18,8 @@ set -ex cd "$(dirname "$0")/../../.." echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -apt-get -o Acquire::Check-Valid-Until=false update +echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf +apt-get update apt-get install -t jessie-backports -y libssl-dev # To increase the confidence that gRPC installation works without depending on diff --git a/tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile b/tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile index d157a278b1e..acce897242a 100644 --- a/tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile +++ b/tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile @@ -30,6 +30,7 @@ RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y golang && apt-get clean RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -RUN apt-get -o Acquire::Check-Valid-Until=false update && apt-get install -t jessie-backports -y cmake && apt-get clean +RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf +RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean CMD ["bash"] diff --git a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile index 07564dc40a9..7d85efe2eb2 100644 --- a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile +++ b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile @@ -73,7 +73,8 @@ RUN apt-get update && apt-get install -y \ # Use cmake 3.6 from jessie-backports RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -RUN apt-get -o Acquire::Check-Valid-Until=false update && apt-get install -t jessie-backports -y cmake && apt-get clean +RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf +RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean RUN mkdir /var/local/jenkins diff --git a/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile index 55091f4fffa..e370fafd7fc 100644 --- a/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile +++ b/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile @@ -65,7 +65,8 @@ RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-ri --no-rdoc" # Use cmake 3.6 from jessie-backports RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -RUN apt-get -o Acquire::Check-Valid-Until=false update && apt-get install -t jessie-backports -y cmake && apt-get clean +RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf +RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean RUN mkdir /var/local/jenkins diff --git a/tools/dockerfile/test/cxx_jessie_x64/Dockerfile b/tools/dockerfile/test/cxx_jessie_x64/Dockerfile index 6afad4869fd..b4899f1e3fe 100644 --- a/tools/dockerfile/test/cxx_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/cxx_jessie_x64/Dockerfile @@ -77,7 +77,8 @@ RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev c # should only be used for images based on debian jessie. RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -RUN apt-get -o Acquire::Check-Valid-Until=false update && apt-get install -t jessie-backports -y cmake && apt-get clean +RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf +RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean RUN mkdir /var/local/jenkins diff --git a/tools/dockerfile/test/cxx_jessie_x86/Dockerfile b/tools/dockerfile/test/cxx_jessie_x86/Dockerfile index c153cd037e6..59bed835418 100644 --- a/tools/dockerfile/test/cxx_jessie_x86/Dockerfile +++ b/tools/dockerfile/test/cxx_jessie_x86/Dockerfile @@ -80,7 +80,8 @@ RUN mkdir /var/local/jenkins # should only be used for images based on debian jessie. RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -RUN apt-get -o Acquire::Check-Valid-Until=false update && apt-get install -t jessie-backports -y cmake && apt-get clean +RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf +RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean # Install gcc-4.8 and other relevant items diff --git a/tools/dockerfile/test/fuzzer/Dockerfile b/tools/dockerfile/test/fuzzer/Dockerfile index 591ca0ce014..25e417cecba 100644 --- a/tools/dockerfile/test/fuzzer/Dockerfile +++ b/tools/dockerfile/test/fuzzer/Dockerfile @@ -77,7 +77,8 @@ RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev c # should only be used for images based on debian jessie. RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list -RUN apt-get -o Acquire::Check-Valid-Until=false update && apt-get install -t jessie-backports -y cmake && apt-get clean +RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf +RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean #================= # Update clang to a version with improved tsan and fuzzing capabilities From 85bcce2e086d5bbb03eca386665ffd76bd4e957a Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Wed, 27 Mar 2019 12:19:00 -0700 Subject: [PATCH 084/242] Fix typo in BUILD.bazel --- examples/python/errors/BUILD.bazel | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/python/errors/BUILD.bazel b/examples/python/errors/BUILD.bazel index 1ef36a06471..38bed132844 100644 --- a/examples/python/errors/BUILD.bazel +++ b/examples/python/errors/BUILD.bazel @@ -43,11 +43,9 @@ py_library( py_test( name = "test/_error_handling_example_test", srcs = ["test/_error_handling_example_test.py"], - data = [ + deps = [ ":client", ":server", - "//src/python/grpcio/grpc:grpcio", - "//examples:py_helloworld", "//src/python/grpcio_tests/tests:bazel_namespace_package_hack", ], size = "small", From a88e3f4c2eaace140bcff9cce034266ae6f89566 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Thu, 14 Mar 2019 15:32:51 -0700 Subject: [PATCH 085/242] Move ServerBuilderOption from grpc to grpc_impl namespace --- BUILD | 1 + CMakeLists.txt | 3 ++ Makefile | 3 ++ build.yaml | 1 + gRPC-C++.podspec | 1 + include/grpcpp/impl/server_builder_option.h | 19 ++------ .../grpcpp/impl/server_builder_option_impl.h | 43 +++++++++++++++++++ 7 files changed, 55 insertions(+), 16 deletions(-) create mode 100644 include/grpcpp/impl/server_builder_option_impl.h diff --git a/BUILD b/BUILD index 349ade626b4..90d60c3a0c0 100644 --- a/BUILD +++ b/BUILD @@ -235,6 +235,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/impl/rpc_service_method.h", "include/grpcpp/impl/serialization_traits.h", "include/grpcpp/impl/server_builder_option.h", + "include/grpcpp/impl/server_builder_option_impl.h", "include/grpcpp/impl/server_builder_plugin.h", "include/grpcpp/impl/server_initializer.h", "include/grpcpp/impl/service_type.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index e7857d5d84e..0090b8ad34f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3015,6 +3015,7 @@ foreach(_hdr include/grpcpp/impl/rpc_service_method.h include/grpcpp/impl/serialization_traits.h include/grpcpp/impl/server_builder_option.h + include/grpcpp/impl/server_builder_option_impl.h include/grpcpp/impl/server_builder_plugin.h include/grpcpp/impl/server_initializer.h include/grpcpp/impl/service_type.h @@ -3606,6 +3607,7 @@ foreach(_hdr include/grpcpp/impl/rpc_service_method.h include/grpcpp/impl/serialization_traits.h include/grpcpp/impl/server_builder_option.h + include/grpcpp/impl/server_builder_option_impl.h include/grpcpp/impl/server_builder_plugin.h include/grpcpp/impl/server_initializer.h include/grpcpp/impl/service_type.h @@ -4569,6 +4571,7 @@ foreach(_hdr include/grpcpp/impl/rpc_service_method.h include/grpcpp/impl/serialization_traits.h include/grpcpp/impl/server_builder_option.h + include/grpcpp/impl/server_builder_option_impl.h include/grpcpp/impl/server_builder_plugin.h include/grpcpp/impl/server_initializer.h include/grpcpp/impl/service_type.h diff --git a/Makefile b/Makefile index c0b277f0fb1..0c2a8a95ed6 100644 --- a/Makefile +++ b/Makefile @@ -5342,6 +5342,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/rpc_service_method.h \ include/grpcpp/impl/serialization_traits.h \ include/grpcpp/impl/server_builder_option.h \ + include/grpcpp/impl/server_builder_option_impl.h \ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ @@ -5941,6 +5942,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/rpc_service_method.h \ include/grpcpp/impl/serialization_traits.h \ include/grpcpp/impl/server_builder_option.h \ + include/grpcpp/impl/server_builder_option_impl.h \ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ @@ -6853,6 +6855,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/rpc_service_method.h \ include/grpcpp/impl/serialization_traits.h \ include/grpcpp/impl/server_builder_option.h \ + include/grpcpp/impl/server_builder_option_impl.h \ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ diff --git a/build.yaml b/build.yaml index c1271be9131..c300ff38289 100644 --- a/build.yaml +++ b/build.yaml @@ -1360,6 +1360,7 @@ filegroups: - include/grpcpp/impl/rpc_service_method.h - include/grpcpp/impl/serialization_traits.h - include/grpcpp/impl/server_builder_option.h + - include/grpcpp/impl/server_builder_option_impl.h - include/grpcpp/impl/server_builder_plugin.h - include/grpcpp/impl/server_initializer.h - include/grpcpp/impl/service_type.h diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 7afd9ef1a84..9f0a4156d24 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -101,6 +101,7 @@ Pod::Spec.new do |s| 'include/grpcpp/impl/rpc_service_method.h', 'include/grpcpp/impl/serialization_traits.h', 'include/grpcpp/impl/server_builder_option.h', + 'include/grpcpp/impl/server_builder_option_impl.h', 'include/grpcpp/impl/server_builder_plugin.h', 'include/grpcpp/impl/server_initializer.h', 'include/grpcpp/impl/service_type.h', diff --git a/include/grpcpp/impl/server_builder_option.h b/include/grpcpp/impl/server_builder_option.h index c7b7801dab3..4b3d6b54118 100644 --- a/include/grpcpp/impl/server_builder_option.h +++ b/include/grpcpp/impl/server_builder_option.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,24 +19,11 @@ #ifndef GRPCPP_IMPL_SERVER_BUILDER_OPTION_H #define GRPCPP_IMPL_SERVER_BUILDER_OPTION_H -#include -#include - -#include -#include +#include namespace grpc { -/// Interface to pass an option to a \a ServerBuilder. -class ServerBuilderOption { - public: - virtual ~ServerBuilderOption() {} - /// Alter the \a ChannelArguments used to create the gRPC server. - virtual void UpdateArguments(ChannelArguments* args) = 0; - /// Alter the ServerBuilderPlugin map that will be added into ServerBuilder. - virtual void UpdatePlugins( - std::vector>* plugins) = 0; -}; +typedef ::grpc_impl::ServerBuilderOption ServerBuilderOption; } // namespace grpc diff --git a/include/grpcpp/impl/server_builder_option_impl.h b/include/grpcpp/impl/server_builder_option_impl.h new file mode 100644 index 00000000000..8271d0f56b2 --- /dev/null +++ b/include/grpcpp/impl/server_builder_option_impl.h @@ -0,0 +1,43 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_IMPL_SERVER_BUILDER_OPTION_IMPL_H +#define GRPCPP_IMPL_SERVER_BUILDER_OPTION_IMPL_H + +#include +#include + +#include +#include + +namespace grpc_impl { + +/// Interface to pass an option to a \a ServerBuilder. +class ServerBuilderOption { + public: + virtual ~ServerBuilderOption() {} + /// Alter the \a ChannelArguments used to create the gRPC server. + virtual void UpdateArguments(grpc::ChannelArguments* args) = 0; + /// Alter the ServerBuilderPlugin map that will be added into ServerBuilder. + virtual void UpdatePlugins( + std::vector>* plugins) = 0; +}; + +} // namespace grpc_impl + +#endif // GRPCPP_IMPL_SERVER_BUILDER_OPTION_IMPL_H From ab2bf7abf08a74d3e4118eee92b8b9b77c3fd80a Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Fri, 15 Mar 2019 14:47:56 -0700 Subject: [PATCH 086/242] Fix presubmit script errors. --- tools/doxygen/Doxyfile.c++ | 1 + tools/doxygen/Doxyfile.c++.internal | 1 + tools/run_tests/generated/sources_and_headers.json | 2 ++ 3 files changed, 4 insertions(+) diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 9f17a25298a..c5bf7d6fcb2 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -991,6 +991,7 @@ include/grpcpp/impl/rpc_method.h \ include/grpcpp/impl/rpc_service_method.h \ include/grpcpp/impl/serialization_traits.h \ include/grpcpp/impl/server_builder_option.h \ +include/grpcpp/impl/server_builder_option_impl.h \ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 1e17ab8f88b..ebcd10d3e50 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -993,6 +993,7 @@ include/grpcpp/impl/rpc_method.h \ include/grpcpp/impl/rpc_service_method.h \ include/grpcpp/impl/serialization_traits.h \ include/grpcpp/impl/server_builder_option.h \ +include/grpcpp/impl/server_builder_option_impl.h \ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ include/grpcpp/impl/service_type.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index cd88082f884..af918aff6f1 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -10080,6 +10080,7 @@ "include/grpcpp/impl/rpc_service_method.h", "include/grpcpp/impl/serialization_traits.h", "include/grpcpp/impl/server_builder_option.h", + "include/grpcpp/impl/server_builder_option_impl.h", "include/grpcpp/impl/server_builder_plugin.h", "include/grpcpp/impl/server_initializer.h", "include/grpcpp/impl/service_type.h", @@ -10189,6 +10190,7 @@ "include/grpcpp/impl/rpc_service_method.h", "include/grpcpp/impl/serialization_traits.h", "include/grpcpp/impl/server_builder_option.h", + "include/grpcpp/impl/server_builder_option_impl.h", "include/grpcpp/impl/server_builder_plugin.h", "include/grpcpp/impl/server_initializer.h", "include/grpcpp/impl/service_type.h", From 7660adfd80718acc65b104accae6e4f4885c9664 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Wed, 27 Mar 2019 12:23:32 -0700 Subject: [PATCH 087/242] Fix BUILD.gn file --- BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/BUILD.gn b/BUILD.gn index d15961a4879..183f983e338 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1066,6 +1066,7 @@ config("grpc_config") { "include/grpcpp/impl/rpc_service_method.h", "include/grpcpp/impl/serialization_traits.h", "include/grpcpp/impl/server_builder_option.h", + "include/grpcpp/impl/server_builder_option_impl.h", "include/grpcpp/impl/server_builder_plugin.h", "include/grpcpp/impl/server_initializer.h", "include/grpcpp/impl/service_type.h", From 577ddfb1a1fa2d4025c623e89596a0b1d513c24c Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Thu, 14 Mar 2019 16:17:21 -0700 Subject: [PATCH 088/242] Move ServerInitializer to grpc_impl namespace from grpc --- BUILD | 1 + CMakeLists.txt | 3 + Makefile | 3 + build.yaml | 1 + gRPC-C++.podspec | 1 + .../ext/proto_server_reflection_plugin.h | 9 ++- include/grpcpp/impl/server_builder_plugin.h | 9 ++- include/grpcpp/impl/server_initializer.h | 31 +--------- include/grpcpp/impl/server_initializer_impl.h | 57 +++++++++++++++++++ include/grpcpp/server.h | 11 ++-- ..._reporting_service_server_builder_plugin.h | 6 +- src/cpp/server/server_builder.cc | 2 +- src/cpp/server/server_cc.cc | 2 +- 13 files changed, 93 insertions(+), 43 deletions(-) create mode 100644 include/grpcpp/impl/server_initializer_impl.h diff --git a/BUILD b/BUILD index 349ade626b4..4da4a6017e9 100644 --- a/BUILD +++ b/BUILD @@ -237,6 +237,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/impl/server_builder_option.h", "include/grpcpp/impl/server_builder_plugin.h", "include/grpcpp/impl/server_initializer.h", + "include/grpcpp/impl/server_initializer_impl.h", "include/grpcpp/impl/service_type.h", "include/grpcpp/impl/sync_cxx11.h", "include/grpcpp/impl/sync_no_cxx11.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index e7857d5d84e..168e66b827c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3017,6 +3017,7 @@ foreach(_hdr include/grpcpp/impl/server_builder_option.h include/grpcpp/impl/server_builder_plugin.h include/grpcpp/impl/server_initializer.h + include/grpcpp/impl/server_initializer_impl.h include/grpcpp/impl/service_type.h include/grpcpp/resource_quota.h include/grpcpp/security/auth_context.h @@ -3608,6 +3609,7 @@ foreach(_hdr include/grpcpp/impl/server_builder_option.h include/grpcpp/impl/server_builder_plugin.h include/grpcpp/impl/server_initializer.h + include/grpcpp/impl/server_initializer_impl.h include/grpcpp/impl/service_type.h include/grpcpp/resource_quota.h include/grpcpp/security/auth_context.h @@ -4571,6 +4573,7 @@ foreach(_hdr include/grpcpp/impl/server_builder_option.h include/grpcpp/impl/server_builder_plugin.h include/grpcpp/impl/server_initializer.h + include/grpcpp/impl/server_initializer_impl.h include/grpcpp/impl/service_type.h include/grpcpp/resource_quota.h include/grpcpp/security/auth_context.h diff --git a/Makefile b/Makefile index c0b277f0fb1..69d4e0e2db5 100644 --- a/Makefile +++ b/Makefile @@ -5344,6 +5344,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/server_builder_option.h \ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ + include/grpcpp/impl/server_initializer_impl.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ include/grpcpp/security/auth_context.h \ @@ -5943,6 +5944,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/server_builder_option.h \ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ + include/grpcpp/impl/server_initializer_impl.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ include/grpcpp/security/auth_context.h \ @@ -6855,6 +6857,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/server_builder_option.h \ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ + include/grpcpp/impl/server_initializer_impl.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ include/grpcpp/security/auth_context.h \ diff --git a/build.yaml b/build.yaml index c1271be9131..342a70cafaf 100644 --- a/build.yaml +++ b/build.yaml @@ -1362,6 +1362,7 @@ filegroups: - include/grpcpp/impl/server_builder_option.h - include/grpcpp/impl/server_builder_plugin.h - include/grpcpp/impl/server_initializer.h + - include/grpcpp/impl/server_initializer_impl.h - include/grpcpp/impl/service_type.h - include/grpcpp/resource_quota.h - include/grpcpp/security/auth_context.h diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 7afd9ef1a84..b33280c46d1 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -103,6 +103,7 @@ Pod::Spec.new do |s| 'include/grpcpp/impl/server_builder_option.h', 'include/grpcpp/impl/server_builder_plugin.h', 'include/grpcpp/impl/server_initializer.h', + 'include/grpcpp/impl/server_initializer_impl.h', 'include/grpcpp/impl/service_type.h', 'include/grpcpp/resource_quota.h', 'include/grpcpp/security/auth_context.h', diff --git a/include/grpcpp/ext/proto_server_reflection_plugin.h b/include/grpcpp/ext/proto_server_reflection_plugin.h index 1cfdc1b6ccf..584e44190a0 100644 --- a/include/grpcpp/ext/proto_server_reflection_plugin.h +++ b/include/grpcpp/ext/proto_server_reflection_plugin.h @@ -22,8 +22,11 @@ #include #include -namespace grpc { +namespace grpc_impl { + class ServerInitializer; +} +namespace grpc { class ProtoServerReflection; } // namespace grpc @@ -34,8 +37,8 @@ class ProtoServerReflectionPlugin : public ::grpc::ServerBuilderPlugin { public: ProtoServerReflectionPlugin(); ::grpc::string name() override; - void InitServer(::grpc::ServerInitializer* si) override; - void Finish(::grpc::ServerInitializer* si) override; + void InitServer(::grpc_impl::ServerInitializer* si) override; + void Finish(::grpc_impl::ServerInitializer* si) override; void ChangeArguments(const ::grpc::string& name, void* value) override; bool has_async_methods() const override; bool has_sync_methods() const override; diff --git a/include/grpcpp/impl/server_builder_plugin.h b/include/grpcpp/impl/server_builder_plugin.h index 39450b42d56..adde29da7d1 100644 --- a/include/grpcpp/impl/server_builder_plugin.h +++ b/include/grpcpp/impl/server_builder_plugin.h @@ -23,10 +23,13 @@ #include +namespace grpc_impl { + +class ServerInitializer; +} namespace grpc { class ServerBuilder; -class ServerInitializer; class ChannelArguments; /// This interface is meant for internal usage only. Implementations of this @@ -44,10 +47,10 @@ class ServerBuilderPlugin { /// InitServer will be called in ServerBuilder::BuildAndStart(), after the /// Server instance is created. - virtual void InitServer(ServerInitializer* si) = 0; + virtual void InitServer(grpc_impl::ServerInitializer* si) = 0; /// Finish will be called at the end of ServerBuilder::BuildAndStart(). - virtual void Finish(ServerInitializer* si) = 0; + virtual void Finish(grpc_impl::ServerInitializer* si) = 0; /// ChangeArguments is an interface that can be used in /// ServerBuilderOption::UpdatePlugins diff --git a/include/grpcpp/impl/server_initializer.h b/include/grpcpp/impl/server_initializer.h index f949fabfe6f..d40bb98feb6 100644 --- a/include/grpcpp/impl/server_initializer.h +++ b/include/grpcpp/impl/server_initializer.h @@ -1,6 +1,6 @@ /* * - * Copyright 2016 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,36 +19,11 @@ #ifndef GRPCPP_IMPL_SERVER_INITIALIZER_H #define GRPCPP_IMPL_SERVER_INITIALIZER_H -#include -#include - -#include +#include namespace grpc { -class Server; -class Service; - -class ServerInitializer { - public: - ServerInitializer(Server* server) : server_(server) {} - - bool RegisterService(std::shared_ptr service) { - if (!server_->RegisterService(nullptr, service.get())) { - return false; - } - default_services_.push_back(service); - return true; - } - - const std::vector* GetServiceList() { - return &server_->services_; - } - - private: - Server* server_; - std::vector > default_services_; -}; +typedef ::grpc_impl::ServerInitializer ServerInitializer; } // namespace grpc diff --git a/include/grpcpp/impl/server_initializer_impl.h b/include/grpcpp/impl/server_initializer_impl.h new file mode 100644 index 00000000000..ff610efa2ac --- /dev/null +++ b/include/grpcpp/impl/server_initializer_impl.h @@ -0,0 +1,57 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_IMPL_SERVER_INITIALIZER_IMPL_H +#define GRPCPP_IMPL_SERVER_INITIALIZER_IMPL_H + +#include +#include + +#include + +namespace grpc { + +class Server; +class Service; +} // namespace grpc +namespace grpc_impl { + +class ServerInitializer { + public: + ServerInitializer(grpc::Server* server) : server_(server) {} + + bool RegisterService(std::shared_ptr service) { + if (!server_->RegisterService(nullptr, service.get())) { + return false; + } + default_services_.push_back(service); + return true; + } + + const std::vector* GetServiceList() { + return &server_->services_; + } + + private: + grpc::Server* server_; + std::vector > default_services_; +}; + +} // namespace grpc_impl + +#endif // GRPCPP_IMPL_SERVER_INITIALIZER_IMPL_H diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index f5c99f22df2..6ff392787af 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -40,12 +40,15 @@ struct grpc_server; +namespace grpc_impl { + +class ServerInitializer; +} namespace grpc { class AsyncGenericService; class HealthCheckServiceInterface; class ServerContext; -class ServerInitializer; /// Represents a gRPC server. /// @@ -199,7 +202,7 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { friend class AsyncGenericService; friend class ServerBuilder; - friend class ServerInitializer; + friend class grpc_impl::ServerInitializer; class SyncRequest; class CallbackRequestBase; @@ -257,7 +260,7 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { CompletionQueue* CallbackCQ() override; - ServerInitializer* initializer(); + grpc_impl::ServerInitializer* initializer(); // A vector of interceptor factory objects. // This should be destroyed after health_check_service_ and this requirement @@ -321,7 +324,7 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { // Pointer to the wrapped grpc_server. grpc_server* server_; - std::unique_ptr server_initializer_; + std::unique_ptr server_initializer_; std::unique_ptr health_check_service_; bool health_check_service_disabled_; diff --git a/src/cpp/server/load_reporter/load_reporting_service_server_builder_plugin.h b/src/cpp/server/load_reporter/load_reporting_service_server_builder_plugin.h index 1f098591d4d..c80802b2638 100644 --- a/src/cpp/server/load_reporter/load_reporting_service_server_builder_plugin.h +++ b/src/cpp/server/load_reporter/load_reporting_service_server_builder_plugin.h @@ -36,13 +36,13 @@ class LoadReportingServiceServerBuilderPlugin : public ServerBuilderPlugin { grpc::string name() override { return "load_reporting_service"; } // Creates a load reporting service. - void UpdateServerBuilder(grpc::ServerBuilder* builder) override; + void UpdateServerBuilder(ServerBuilder* builder) override; // Registers the load reporter service. - void InitServer(grpc::ServerInitializer* si) override; + void InitServer(grpc_impl::ServerInitializer* si) override; // Starts the load reporter service. - void Finish(grpc::ServerInitializer* si) override; + void Finish(grpc_impl::ServerInitializer* si) override; void ChangeArguments(const grpc::string& name, void* value) override {} void UpdateChannelArguments(grpc::ChannelArguments* args) override {} diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index cd0e516d9a3..46a8b11c425 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -309,7 +309,7 @@ std::unique_ptr ServerBuilder::BuildAndStart() { sync_server_settings_.cq_timeout_msec, resource_quota_, std::move(interceptor_creators_))); - ServerInitializer* initializer = server->initializer(); + grpc_impl::ServerInitializer* initializer = server->initializer(); // Register all the completion queues with the server. i.e // 1. sync_server_cqs: internal completion queues created IF this is a sync diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 26e84f1aed4..aa9fdac9bea 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -766,7 +766,7 @@ Server::Server( shutdown_(false), shutdown_notified_(false), server_(nullptr), - server_initializer_(new ServerInitializer(this)), + server_initializer_(new grpc_impl::ServerInitializer(this)), health_check_service_disabled_(false) { g_gli_initializer.summon(); gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks); From 76860add9bb53f24ba308de54983177930791c4b Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Fri, 15 Mar 2019 14:50:07 -0700 Subject: [PATCH 089/242] Fix error from presubmit test scripts. --- tools/doxygen/Doxyfile.c++ | 1 + tools/doxygen/Doxyfile.c++.internal | 1 + tools/run_tests/generated/sources_and_headers.json | 2 ++ 3 files changed, 4 insertions(+) diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 9f17a25298a..45b86e27f52 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -993,6 +993,7 @@ include/grpcpp/impl/serialization_traits.h \ include/grpcpp/impl/server_builder_option.h \ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ +include/grpcpp/impl/server_initializer_impl.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ include/grpcpp/security/auth_context.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 1e17ab8f88b..9fea1377b05 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -995,6 +995,7 @@ include/grpcpp/impl/serialization_traits.h \ include/grpcpp/impl/server_builder_option.h \ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ +include/grpcpp/impl/server_initializer_impl.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ include/grpcpp/security/auth_context.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index cd88082f884..4112d7bc2e2 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -10082,6 +10082,7 @@ "include/grpcpp/impl/server_builder_option.h", "include/grpcpp/impl/server_builder_plugin.h", "include/grpcpp/impl/server_initializer.h", + "include/grpcpp/impl/server_initializer_impl.h", "include/grpcpp/impl/service_type.h", "include/grpcpp/resource_quota.h", "include/grpcpp/security/auth_context.h", @@ -10191,6 +10192,7 @@ "include/grpcpp/impl/server_builder_option.h", "include/grpcpp/impl/server_builder_plugin.h", "include/grpcpp/impl/server_initializer.h", + "include/grpcpp/impl/server_initializer_impl.h", "include/grpcpp/impl/service_type.h", "include/grpcpp/resource_quota.h", "include/grpcpp/security/auth_context.h", From 12cd0dbd1d2554b3822645db1002eb6d4c4d18a7 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Wed, 27 Mar 2019 12:29:08 -0700 Subject: [PATCH 090/242] Fix BUILD.gn file --- BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/BUILD.gn b/BUILD.gn index d15961a4879..fee71e5b093 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1068,6 +1068,7 @@ config("grpc_config") { "include/grpcpp/impl/server_builder_option.h", "include/grpcpp/impl/server_builder_plugin.h", "include/grpcpp/impl/server_initializer.h", + "include/grpcpp/impl/server_initializer_impl.h", "include/grpcpp/impl/service_type.h", "include/grpcpp/resource_quota.h", "include/grpcpp/security/auth_context.h", From da1ea4d77ef14a7bd5a20079837b67a0e9926ba3 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Wed, 27 Mar 2019 12:33:44 -0700 Subject: [PATCH 091/242] Fix BUILD.gn files --- BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/BUILD.gn b/BUILD.gn index d15961a4879..a8dd50111e6 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1004,6 +1004,7 @@ config("grpc_config") { "include/grpcpp/client_context.h", "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", + "include/grpcpp/create_channel_impl.h", "include/grpcpp/create_channel_posix.h", "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", From da78fdc0510cd4c4acfa85c7b5bd3222e75a502f Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Wed, 27 Mar 2019 12:35:41 -0700 Subject: [PATCH 092/242] Fix BUILD.gn files --- BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/BUILD.gn b/BUILD.gn index d15961a4879..1fcb8f357f3 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1005,6 +1005,7 @@ config("grpc_config") { "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", "include/grpcpp/create_channel_posix.h", + "include/grpcpp/create_channel_posix_impl.h", "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", "include/grpcpp/generic/generic_stub.h", From 8d22a7b7752d6d818ff0d8b5501b5aa83a224fed Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Wed, 27 Mar 2019 12:39:10 -0700 Subject: [PATCH 093/242] Fix BUILD.gn file --- BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/BUILD.gn b/BUILD.gn index d15961a4879..b3a1fda8723 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1010,6 +1010,7 @@ config("grpc_config") { "include/grpcpp/generic/generic_stub.h", "include/grpcpp/grpcpp.h", "include/grpcpp/health_check_service_interface.h", + "include/grpcpp/health_check_service_interface_impl.h", "include/grpcpp/impl/call.h", "include/grpcpp/impl/channel_argument_option.h", "include/grpcpp/impl/client_unary_call.h", From 47c26836b8ea4dafbd27a2f0f711b8c1a8e14bf8 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Wed, 27 Mar 2019 12:51:31 -0700 Subject: [PATCH 094/242] Fix BUILD.gn --- BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/BUILD.gn b/BUILD.gn index d15961a4879..05c2a735407 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1076,6 +1076,7 @@ config("grpc_config") { "include/grpcpp/security/server_credentials.h", "include/grpcpp/server.h", "include/grpcpp/server_builder.h", + "include/grpcpp/server_builder_impl.h", "include/grpcpp/server_context.h", "include/grpcpp/server_posix.h", "include/grpcpp/support/async_stream.h", From 326e06256bef4e618fa2f1c25657606c8a13d2bc Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 21 Mar 2019 11:00:38 -0400 Subject: [PATCH 095/242] C# distribtests should test Grpc.Tools codegen too --- .../DistribTest/DistribTestDotNet.csproj | 5 ++++ .../csharp/DistribTest/testcodegen.proto | 29 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 test/distrib/csharp/DistribTest/testcodegen.proto diff --git a/test/distrib/csharp/DistribTest/DistribTestDotNet.csproj b/test/distrib/csharp/DistribTest/DistribTestDotNet.csproj index f16a0f99591..d19eac91ba4 100644 --- a/test/distrib/csharp/DistribTest/DistribTestDotNet.csproj +++ b/test/distrib/csharp/DistribTest/DistribTestDotNet.csproj @@ -16,8 +16,13 @@ + + + + + /usr/lib/mono/4.5-api diff --git a/test/distrib/csharp/DistribTest/testcodegen.proto b/test/distrib/csharp/DistribTest/testcodegen.proto new file mode 100644 index 00000000000..7845ac92c49 --- /dev/null +++ b/test/distrib/csharp/DistribTest/testcodegen.proto @@ -0,0 +1,29 @@ +// Copyright 2019 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package testcodegen; + +service Greeter { + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +message HelloRequest { + string name = 1; +} + +message HelloReply { + string message = 1; +} From 89281d44989133a2b36bc2c5457d138a41036bfe Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 21 Mar 2019 11:23:44 -0400 Subject: [PATCH 096/242] test protobuf used --- test/distrib/csharp/DistribTest/Program.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/distrib/csharp/DistribTest/Program.cs b/test/distrib/csharp/DistribTest/Program.cs index 376add6b7b5..0ea7211fc45 100644 --- a/test/distrib/csharp/DistribTest/Program.cs +++ b/test/distrib/csharp/DistribTest/Program.cs @@ -25,6 +25,9 @@ namespace TestGrpcPackage { public static void Main(string[] args) { + // test codegen works + var reply = new Testcodegen.HelloReply(); + // This code doesn't do much but makes sure the native extension is loaded // which is what we are testing here. Channel c = new Channel("127.0.0.1:1000", ChannelCredentials.Insecure); From 133ff03e97c9d1389b321e25bef587ded6689de8 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 21 Mar 2019 11:24:21 -0400 Subject: [PATCH 097/242] classic .csproj Grpc.Tools test --- test/distrib/csharp/DistribTest/DistribTest.csproj | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/distrib/csharp/DistribTest/DistribTest.csproj b/test/distrib/csharp/DistribTest/DistribTest.csproj index d18bb05be68..20d103a41b3 100644 --- a/test/distrib/csharp/DistribTest/DistribTest.csproj +++ b/test/distrib/csharp/DistribTest/DistribTest.csproj @@ -1,6 +1,7 @@  + Debug AnyCPU @@ -98,16 +99,22 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + - 1.20.0-dev + 1.21.0-dev 3.7.0 diff --git a/src/csharp/build_unitypackage.bat b/src/csharp/build_unitypackage.bat index 7d403d1338a..8c7718f727f 100644 --- a/src/csharp/build_unitypackage.bat +++ b/src/csharp/build_unitypackage.bat @@ -13,7 +13,7 @@ @rem limitations under the License. @rem Current package versions -set VERSION=1.20.0-dev +set VERSION=1.21.0-dev @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec index a318af8f540..af876287038 100644 --- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec @@ -42,7 +42,7 @@ Pod::Spec.new do |s| # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler-gRPCPlugin' - v = '1.20.0-dev' + v = '1.21.0-dev' s.version = v s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.' s.description = <<-DESC diff --git a/src/objective-c/GRPCClient/private/version.h b/src/objective-c/GRPCClient/private/version.h index 4d4431ee365..fcbdfb21539 100644 --- a/src/objective-c/GRPCClient/private/version.h +++ b/src/objective-c/GRPCClient/private/version.h @@ -22,4 +22,4 @@ // instead. This file can be regenerated from the template by running // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.20.0-dev" +#define GRPC_OBJC_VERSION_STRING @"1.21.0-dev" diff --git a/src/objective-c/tests/version.h b/src/objective-c/tests/version.h index b3c4788f496..87516de11e8 100644 --- a/src/objective-c/tests/version.h +++ b/src/objective-c/tests/version.h @@ -22,5 +22,5 @@ // instead. This file can be regenerated from the template by running // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.20.0-dev" +#define GRPC_OBJC_VERSION_STRING @"1.21.0-dev" #define GRPC_C_VERSION_STRING @"7.0.0" diff --git a/src/php/composer.json b/src/php/composer.json index e8106db7288..a9d0aebffca 100644 --- a/src/php/composer.json +++ b/src/php/composer.json @@ -2,7 +2,7 @@ "name": "grpc/grpc-dev", "description": "gRPC library for PHP - for Developement use only", "license": "Apache-2.0", - "version": "1.20.0", + "version": "1.21.0", "require": { "php": ">=5.5.0", "google/protobuf": "^v3.3.0" diff --git a/src/php/ext/grpc/version.h b/src/php/ext/grpc/version.h index fac3e85d849..43b3fa629ff 100644 --- a/src/php/ext/grpc/version.h +++ b/src/php/ext/grpc/version.h @@ -20,6 +20,6 @@ #ifndef VERSION_H #define VERSION_H -#define PHP_GRPC_VERSION "1.20.0dev" +#define PHP_GRPC_VERSION "1.21.0dev" #endif /* VERSION_H */ diff --git a/src/python/grpcio/grpc/_grpcio_metadata.py b/src/python/grpcio/grpc/_grpcio_metadata.py index 069dbf1a1c5..651f8f778f2 100644 --- a/src/python/grpcio/grpc/_grpcio_metadata.py +++ b/src/python/grpcio/grpc/_grpcio_metadata.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc/_grpcio_metadata.py.template`!!! -__version__ = """1.20.0.dev0""" +__version__ = """1.21.0.dev0""" diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py index 9e7af710f49..e430cc20a6d 100644 --- a/src/python/grpcio/grpc_version.py +++ b/src/python/grpcio/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!! -VERSION = '1.20.0.dev0' +VERSION = '1.21.0.dev0' diff --git a/src/python/grpcio_channelz/grpc_version.py b/src/python/grpcio_channelz/grpc_version.py index 9a33dc35b26..d716b953f4b 100644 --- a/src/python/grpcio_channelz/grpc_version.py +++ b/src/python/grpcio_channelz/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_channelz/grpc_version.py.template`!!! -VERSION = '1.20.0.dev0' +VERSION = '1.21.0.dev0' diff --git a/src/python/grpcio_health_checking/grpc_version.py b/src/python/grpcio_health_checking/grpc_version.py index eeacbe23bfd..2bb47aaf133 100644 --- a/src/python/grpcio_health_checking/grpc_version.py +++ b/src/python/grpcio_health_checking/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!! -VERSION = '1.20.0.dev0' +VERSION = '1.21.0.dev0' diff --git a/src/python/grpcio_reflection/grpc_version.py b/src/python/grpcio_reflection/grpc_version.py index c76cbbd7a95..e1c4f3df694 100644 --- a/src/python/grpcio_reflection/grpc_version.py +++ b/src/python/grpcio_reflection/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!! -VERSION = '1.20.0.dev0' +VERSION = '1.21.0.dev0' diff --git a/src/python/grpcio_status/grpc_version.py b/src/python/grpcio_status/grpc_version.py index 40d823ed0cd..b484a7ba478 100644 --- a/src/python/grpcio_status/grpc_version.py +++ b/src/python/grpcio_status/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_status/grpc_version.py.template`!!! -VERSION = '1.20.0.dev0' +VERSION = '1.21.0.dev0' diff --git a/src/python/grpcio_testing/grpc_version.py b/src/python/grpcio_testing/grpc_version.py index df40ba743a6..21981ee79d2 100644 --- a/src/python/grpcio_testing/grpc_version.py +++ b/src/python/grpcio_testing/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_testing/grpc_version.py.template`!!! -VERSION = '1.20.0.dev0' +VERSION = '1.21.0.dev0' diff --git a/src/python/grpcio_tests/grpc_version.py b/src/python/grpcio_tests/grpc_version.py index b2db0d0949d..8ce4fdb627d 100644 --- a/src/python/grpcio_tests/grpc_version.py +++ b/src/python/grpcio_tests/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!! -VERSION = '1.20.0.dev0' +VERSION = '1.21.0.dev0' diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb index 0e20b361b7d..cca795b64ec 100644 --- a/src/ruby/lib/grpc/version.rb +++ b/src/ruby/lib/grpc/version.rb @@ -14,5 +14,5 @@ # GRPC contains the General RPC module. module GRPC - VERSION = '1.20.0.dev' + VERSION = '1.21.0.dev' end diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb index 79201ad1e6e..5604e215b58 100644 --- a/src/ruby/tools/version.rb +++ b/src/ruby/tools/version.rb @@ -14,6 +14,6 @@ module GRPC module Tools - VERSION = '1.20.0.dev' + VERSION = '1.21.0.dev' end end diff --git a/tools/distrib/python/grpcio_tools/grpc_version.py b/tools/distrib/python/grpcio_tools/grpc_version.py index 950b2e2d111..22d04c5a1af 100644 --- a/tools/distrib/python/grpcio_tools/grpc_version.py +++ b/tools/distrib/python/grpcio_tools/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!! -VERSION = '1.20.0.dev0' +VERSION = '1.21.0.dev0' diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 3774d75d16a..c10b71568bc 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.20.0-dev +PROJECT_NUMBER = 1.21.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 7bfee1d1465..8acf3db3a34 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.20.0-dev +PROJECT_NUMBER = 1.21.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a From b2c773d26f6126517526919a31093d919302e688 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 29 Mar 2019 17:06:09 -0700 Subject: [PATCH 143/242] Global Registry for Service Config Parsers --- .../filters/client_channel/service_config.cc | 2 ++ .../filters/client_channel/service_config.h | 36 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/core/ext/filters/client_channel/service_config.cc b/src/core/ext/filters/client_channel/service_config.cc index bbf671d979e..e2d23010c8a 100644 --- a/src/core/ext/filters/client_channel/service_config.cc +++ b/src/core/ext/filters/client_channel/service_config.cc @@ -33,6 +33,8 @@ namespace grpc_core { +int ServiceConfig::registered_parsers_count = 0; + RefCountedPtr ServiceConfig::Create(const char* json) { UniquePtr service_config_json(gpr_strdup(json)); UniquePtr json_string(gpr_strdup(json)); diff --git a/src/core/ext/filters/client_channel/service_config.h b/src/core/ext/filters/client_channel/service_config.h index d9063479e32..b211d732d3f 100644 --- a/src/core/ext/filters/client_channel/service_config.h +++ b/src/core/ext/filters/client_channel/service_config.h @@ -54,6 +54,15 @@ namespace grpc_core { +/// This is the base class that all service config parsers MUST use to store +/// parsed service config data. +class ServiceConfigParsedObject { + public: + virtual ~ServiceConfigParsedObject() = default; + + GRPC_ABSTRACT_BASE_CLASS; +}; + class ServiceConfig : public RefCounted { public: /// Creates a new service config from parsing \a json_string. @@ -96,6 +105,26 @@ class ServiceConfig : public RefCounted { static RefCountedPtr MethodConfigTableLookup( const SliceHashTable>& table, const grpc_slice& path); + /// Retrieves the parsed object at index \a index. + ServiceConfigParsedObject* GetParsedServiceConfigObject(int index) { + GPR_DEBUG_ASSERT(index < registered_parsers_count); + return parsed_service_config_objects[index].get(); + } + + typedef UniquePtr (*ServiceConfigParser)( + const char* service_config_json); + + /// Globally register a service config parser. On successful registration, it + /// returns the index at which the parser was registered. On failure, -1 is + /// returned. Each new service config update will go through all the + /// registered parser. Each parser is responsible for reading the service + /// config json and returning a parsed object. This parsed object can later be + /// retrieved using the same index that was returned at registration time. + static int RegisterParser(ServiceConfigParser func) { + registered_parsers[registered_parsers_count] = func; + return registered_parsers_count++; + } + private: // So New() can call our private ctor. template @@ -120,9 +149,16 @@ class ServiceConfig : public RefCounted { grpc_json* json, CreateValue create_value, typename SliceHashTable>::Entry* entries, size_t* idx); + static constexpr int kMaxParsers = 32; + static int registered_parsers_count; + static ServiceConfigParser registered_parsers[kMaxParsers]; + UniquePtr service_config_json_; UniquePtr json_string_; // Underlying storage for json_tree. grpc_json* json_tree_; + + InlinedVector, kMaxParsers> + parsed_service_config_objects; }; // From 47132c099e42c4947cc045cb847b46cf1c994afa Mon Sep 17 00:00:00 2001 From: yang-g Date: Fri, 29 Mar 2019 17:20:38 -0700 Subject: [PATCH 144/242] error handling for start_bdp_ping --- src/core/ext/transport/chttp2/transport/chttp2_transport.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index df9e273c71f..07e01733f66 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -2598,6 +2598,9 @@ static void start_bdp_ping_locked(void* tp, grpc_error* error) { gpr_log(GPR_INFO, "%s: Start BDP ping err=%s", t->peer_string, grpc_error_string(error)); } + if (error != GRPC_ERROR_NONE || t->closed_with_error != GRPC_ERROR_NONE) { + return; + } /* Reset the keepalive ping timer */ if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING) { grpc_timer_cancel(&t->keepalive_ping_timer); From da3a2320a2912d0f91fb23938c59f5036ea639b3 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Tue, 26 Mar 2019 17:10:41 -0400 Subject: [PATCH 145/242] Ref transport and stream before init of chttp2_stream structure. The stream structure is really big and by the time we get to ref the stream and the transport, the fields are out of cache. We need to ref them immediately, before starting to initialize the stream. This commit introduces a 0-byte Reffer so that we can ref the streams on time before the field initializers. --- .../chttp2/transport/chttp2_transport.cc | 19 ++++++++++++------- .../ext/transport/chttp2/transport/internal.h | 6 ++++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index 404539c9e13..cb6596f9d1f 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -645,17 +645,22 @@ void grpc_chttp2_stream_unref(grpc_chttp2_stream* s) { } #endif +grpc_chttp2_stream::Reffer::Reffer(grpc_chttp2_stream* s) { + /* We reserve one 'active stream' that's dropped when the stream is + read-closed. The others are for Chttp2IncomingByteStreams that are + actively reading */ + GRPC_CHTTP2_STREAM_REF(s, "chttp2"); + GRPC_CHTTP2_REF_TRANSPORT(s->t, "stream"); +} + grpc_chttp2_stream::grpc_chttp2_stream(grpc_chttp2_transport* t, grpc_stream_refcount* refcount, const void* server_data, gpr_arena* arena) - : t(t), refcount(refcount), metadata_buffer{{arena}, {arena}} { - /* We reserve one 'active stream' that's dropped when the stream is - read-closed. The others are for Chttp2IncomingByteStreams that are - actively reading */ - GRPC_CHTTP2_STREAM_REF(this, "chttp2"); - GRPC_CHTTP2_REF_TRANSPORT(t, "stream"); - + : t(t), + refcount(refcount), + reffer(this), + metadata_buffer{{arena}, {arena}} { if (server_data) { id = static_cast((uintptr_t)server_data); *t->accepting_stream = this; diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index 760324c0c95..e4fd5928f2c 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -510,6 +510,12 @@ struct grpc_chttp2_stream { void* context; grpc_chttp2_transport* t; grpc_stream_refcount* refcount; + // Reffer is a 0-len structure, simply reffing `t` and `refcount` in its ctor + // before initializing the rest of the stream, to avoid cache misses. This + // field MUST be right after `t` and `refcount`. + struct Reffer { + explicit Reffer(grpc_chttp2_stream* s); + } reffer; grpc_closure destroy_stream; grpc_closure* destroy_stream_arg; From c239e0416d54c0a19b55a056fa1c92bbd400cac7 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Sun, 31 Mar 2019 20:18:13 -0400 Subject: [PATCH 146/242] Initialize time as part of basic initialization. `gpr_time_init` must happen in `do_basic_init`, because for normal initialization we may need the precise clock (e.g., if profilers are enabled). Otherwise, we will have an stack overflow. Fixes #18589 --- src/core/lib/surface/init.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/lib/surface/init.cc b/src/core/lib/surface/init.cc index fdb584da68f..b67d4f12252 100644 --- a/src/core/lib/surface/init.cc +++ b/src/core/lib/surface/init.cc @@ -73,6 +73,7 @@ static void do_basic_init(void) { g_shutting_down = false; grpc_register_built_in_plugins(); grpc_cq_global_init(); + gpr_time_init(); g_initializations = 0; } @@ -132,7 +133,6 @@ void grpc_init(void) { } grpc_core::Fork::GlobalInit(); grpc_fork_handlers_auto_register(); - gpr_time_init(); gpr_arena_init(); grpc_stats_init(); grpc_slice_intern_init(); From f1199912e85e8cb7cc03c3b2c1751797cd474316 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Sat, 30 Mar 2019 22:30:18 -0700 Subject: [PATCH 147/242] fix typo in log message --- src/csharp/Grpc.Core/Internal/NativeCallbackDispatcher.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/csharp/Grpc.Core/Internal/NativeCallbackDispatcher.cs b/src/csharp/Grpc.Core/Internal/NativeCallbackDispatcher.cs index d5146e816e2..0777d7933e6 100644 --- a/src/csharp/Grpc.Core/Internal/NativeCallbackDispatcher.cs +++ b/src/csharp/Grpc.Core/Internal/NativeCallbackDispatcher.cs @@ -63,7 +63,7 @@ namespace Grpc.Core.Internal catch (Exception e) { // eat the exception, we must not throw when inside callback from native code. - Logger.Error(e, "Caught exception inside callback from native callback."); + Logger.Error(e, "Caught exception inside callback from native code."); return 0; } } From c835fedd4d42d7799a9a0c89b284db9c9a66a886 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 21 Mar 2019 12:07:08 -0700 Subject: [PATCH 148/242] Modify verifyPeerCallback logic to use NativeCallbackDispatcher --- src/csharp/Grpc.Core/ChannelCredentials.cs | 63 ++++++++----- .../Internal/ChannelCredentialsSafeHandle.cs | 12 +-- .../Internal/NativeMethods.Generated.cs | 6 +- .../SslCredentialsTest.cs | 92 ++++++++++--------- src/csharp/ext/grpc_csharp_ext.c | 53 +++++------ .../Grpc.Core/Internal/native_methods.include | 2 +- 6 files changed, 122 insertions(+), 106 deletions(-) diff --git a/src/csharp/Grpc.Core/ChannelCredentials.cs b/src/csharp/Grpc.Core/ChannelCredentials.cs index 103a594bb06..2ecd3875e84 100644 --- a/src/csharp/Grpc.Core/ChannelCredentials.cs +++ b/src/csharp/Grpc.Core/ChannelCredentials.cs @@ -127,8 +127,6 @@ namespace Grpc.Core readonly string rootCertificates; readonly KeyCertificatePair keyCertificatePair; readonly VerifyPeerCallback verifyPeerCallback; - readonly VerifyPeerCallbackInternal verifyPeerCallbackInternal; - readonly GCHandle gcHandle; /// /// Creates client-side SSL credentials loaded from @@ -168,12 +166,7 @@ namespace Grpc.Core { this.rootCertificates = rootCertificates; this.keyCertificatePair = keyCertificatePair; - if (verifyPeerCallback != null) - { - this.verifyPeerCallback = verifyPeerCallback; - this.verifyPeerCallbackInternal = this.VerifyPeerCallbackHandler; - gcHandle = GCHandle.Alloc(verifyPeerCallbackInternal); - } + this.verifyPeerCallback = verifyPeerCallback; } /// @@ -207,29 +200,53 @@ namespace Grpc.Core internal override ChannelCredentialsSafeHandle CreateNativeCredentials() { - return ChannelCredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair, this.verifyPeerCallbackInternal); + IntPtr verifyPeerCallbackTag = IntPtr.Zero; + if (verifyPeerCallback != null) + { + verifyPeerCallbackTag = new VerifyPeerCallbackRegistration(verifyPeerCallback).CallbackRegistration.Tag; + } + return ChannelCredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair, verifyPeerCallbackTag); } - private int VerifyPeerCallbackHandler(IntPtr host, IntPtr pem, IntPtr userData, bool isDestroy) + private class VerifyPeerCallbackRegistration { - if (isDestroy) + readonly VerifyPeerCallback verifyPeerCallback; + readonly NativeCallbackRegistration callbackRegistration; + + public VerifyPeerCallbackRegistration(VerifyPeerCallback verifyPeerCallback) { - this.gcHandle.Free(); - return 0; + this.verifyPeerCallback = verifyPeerCallback; + this.callbackRegistration = NativeCallbackDispatcher.RegisterCallback(HandleUniversalCallback); } - try - { - var context = new VerifyPeerContext(Marshal.PtrToStringAnsi(host), Marshal.PtrToStringAnsi(pem)); + public NativeCallbackRegistration CallbackRegistration => callbackRegistration; - return this.verifyPeerCallback(context) ? 0 : 1; - } - catch (Exception e) + private int HandleUniversalCallback(IntPtr arg0, IntPtr arg1, IntPtr arg2, IntPtr arg3, IntPtr arg4, IntPtr arg5) { - // eat the exception, we must not throw when inside callback from native code. - Logger.Error(e, "Exception occurred while invoking verify peer callback handler."); - // Return validation failure in case of exception. - return 1; + return VerifyPeerCallbackHandler(arg0, arg1, arg2 != IntPtr.Zero); + } + + private int VerifyPeerCallbackHandler(IntPtr host, IntPtr pem, bool isDestroy) + { + if (isDestroy) + { + this.callbackRegistration.Dispose(); + return 0; + } + + try + { + var context = new VerifyPeerContext(Marshal.PtrToStringAnsi(host), Marshal.PtrToStringAnsi(pem)); + + return this.verifyPeerCallback(context) ? 0 : 1; + } + catch (Exception e) + { + // eat the exception, we must not throw when inside callback from native code. + Logger.Error(e, "Exception occurred while invoking verify peer callback handler."); + // Return validation failure in case of exception. + return 1; + } } } } diff --git a/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs index 5e336673153..d4f50344b23 100644 --- a/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs @@ -20,12 +20,6 @@ using System.Threading.Tasks; namespace Grpc.Core.Internal { - internal delegate int VerifyPeerCallbackInternal( - IntPtr targetHost, - IntPtr targetPem, - IntPtr userData, - bool isDestroy); - /// /// grpc_channel_credentials from grpc/grpc_security.h /// @@ -44,15 +38,15 @@ namespace Grpc.Core.Internal return creds; } - public static ChannelCredentialsSafeHandle CreateSslCredentials(string pemRootCerts, KeyCertificatePair keyCertPair, VerifyPeerCallbackInternal verifyPeerCallback) + public static ChannelCredentialsSafeHandle CreateSslCredentials(string pemRootCerts, KeyCertificatePair keyCertPair, IntPtr verifyPeerCallbackTag) { if (keyCertPair != null) { - return Native.grpcsharp_ssl_credentials_create(pemRootCerts, keyCertPair.CertificateChain, keyCertPair.PrivateKey, verifyPeerCallback); + return Native.grpcsharp_ssl_credentials_create(pemRootCerts, keyCertPair.CertificateChain, keyCertPair.PrivateKey, verifyPeerCallbackTag); } else { - return Native.grpcsharp_ssl_credentials_create(pemRootCerts, null, null, verifyPeerCallback); + return Native.grpcsharp_ssl_credentials_create(pemRootCerts, null, null, verifyPeerCallbackTag); } } diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs index e09b9813f79..a1387aff562 100644 --- a/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs +++ b/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs @@ -482,7 +482,7 @@ namespace Grpc.Core.Internal public delegate void grpcsharp_channel_args_set_integer_delegate(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); public delegate void grpcsharp_channel_args_destroy_delegate(IntPtr args); public delegate void grpcsharp_override_default_ssl_roots_delegate(string pemRootCerts); - public delegate ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create_delegate(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, VerifyPeerCallbackInternal verifyPeerCallback); + public delegate ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create_delegate(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag); public delegate ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create_delegate(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); public delegate void grpcsharp_channel_credentials_release_delegate(IntPtr credentials); public delegate ChannelSafeHandle grpcsharp_insecure_channel_create_delegate(string target, ChannelArgsSafeHandle channelArgs); @@ -676,7 +676,7 @@ namespace Grpc.Core.Internal public static extern void grpcsharp_override_default_ssl_roots(string pemRootCerts); [DllImport(ImportName)] - public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, VerifyPeerCallbackInternal verifyPeerCallback); + public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag); [DllImport(ImportName)] public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); @@ -972,7 +972,7 @@ namespace Grpc.Core.Internal public static extern void grpcsharp_override_default_ssl_roots(string pemRootCerts); [DllImport(ImportName)] - public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, VerifyPeerCallbackInternal verifyPeerCallback); + public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag); [DllImport(ImportName)] public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); diff --git a/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs index 818ac6d1adc..4c1189320fa 100644 --- a/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs +++ b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs @@ -44,23 +44,18 @@ namespace Grpc.IntegrationTesting string rootCert; KeyCertificatePair keyCertPair; - string certChain; - List options; - bool isHostEqual; - bool isPemEqual; public void InitClientAndServer(bool clientAddKeyCertPair, - SslClientCertificateRequestType clientCertRequestType) + SslClientCertificateRequestType clientCertRequestType, + VerifyPeerCallback verifyPeerCallback = null) { rootCert = File.ReadAllText(TestCredentials.ClientCertAuthorityPath); - certChain = File.ReadAllText(TestCredentials.ServerCertChainPath); - certChain = certChain.Replace("\r", string.Empty); keyCertPair = new KeyCertificatePair( - certChain, + File.ReadAllText(TestCredentials.ServerCertChainPath), File.ReadAllText(TestCredentials.ServerPrivateKeyPath)); var serverCredentials = new SslServerCredentials(new[] { keyCertPair }, rootCert, clientCertRequestType); - var clientCredentials = clientAddKeyCertPair ? new SslCredentials(rootCert, keyCertPair, context => this.VerifyPeerCallback(context, true)) : new SslCredentials(rootCert); + var clientCredentials = new SslCredentials(rootCert, clientAddKeyCertPair ? keyCertPair : null, verifyPeerCallback); // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) @@ -70,7 +65,7 @@ namespace Grpc.IntegrationTesting }; server.Start(); - options = new List + var options = new List { new ChannelOption(ChannelOptions.SslTargetNameOverride, TestCredentials.DefaultHostOverride) }; @@ -194,6 +189,52 @@ namespace Grpc.IntegrationTesting Assert.Throws(typeof(ArgumentNullException), () => new SslServerCredentials(keyCertPairs, null, SslClientCertificateRequestType.RequestAndRequireAndVerify)); } + [Test] + public async Task VerifyPeerCallback_Accepted() + { + string targetNameFromCallback = null; + string peerPemFromCallback = null; + InitClientAndServer( + clientAddKeyCertPair: false, + clientCertRequestType: SslClientCertificateRequestType.DontRequest, + verifyPeerCallback: (ctx) => + { + targetNameFromCallback = ctx.TargetName; + peerPemFromCallback = ctx.PeerPem; + return true; + }); + await CheckAccepted(expectPeerAuthenticated: false); + Assert.AreEqual(TestCredentials.DefaultHostOverride, targetNameFromCallback); + var expectedServerPem = File.ReadAllText(TestCredentials.ServerCertChainPath).Replace("\r", ""); + Assert.AreEqual(expectedServerPem, peerPemFromCallback); + } + + [Test] + public void VerifyPeerCallback_CallbackThrows_Rejected() + { + InitClientAndServer( + clientAddKeyCertPair: false, + clientCertRequestType: SslClientCertificateRequestType.DontRequest, + verifyPeerCallback: (ctx) => + { + throw new Exception("VerifyPeerCallback has thrown on purpose."); + }); + CheckRejected(); + } + + [Test] + public void VerifyPeerCallback_Rejected() + { + InitClientAndServer( + clientAddKeyCertPair: false, + clientCertRequestType: SslClientCertificateRequestType.DontRequest, + verifyPeerCallback: (ctx) => + { + return false; + }); + CheckRejected(); + } + private async Task CheckAccepted(bool expectPeerAuthenticated) { var call = client.UnaryCallAsync(new SimpleRequest { ResponseSize = 10 }); @@ -216,37 +257,6 @@ namespace Grpc.IntegrationTesting Assert.AreEqual(12345, response.AggregatedPayloadSize); } - [Test] - public void VerifyPeerCallbackTest() - { - InitClientAndServer(true, SslClientCertificateRequestType.RequestAndRequireAndVerify); - - // Force GC collection to verify that the VerifyPeerCallback is not collected. If - // it gets collected, this test will hang. - GC.Collect(); - - client.UnaryCall(new SimpleRequest { ResponseSize = 10 }); - Assert.IsTrue(isHostEqual); - Assert.IsTrue(isPemEqual); - } - - [Test] - public void VerifyPeerCallbackFailTest() - { - InitClientAndServer(true, SslClientCertificateRequestType.RequestAndRequireAndVerify); - var clientCredentials = new SslCredentials(rootCert, keyCertPair, context => this.VerifyPeerCallback(context, false)); - var failingChannel = new Channel(Host, server.Ports.Single().BoundPort, clientCredentials, options); - var failingClient = new TestService.TestServiceClient(failingChannel); - Assert.Throws(() => failingClient.UnaryCall(new SimpleRequest { ResponseSize = 10 })); - } - - private bool VerifyPeerCallback(VerifyPeerContext context, bool returnValue) - { - isHostEqual = TestCredentials.DefaultHostOverride == context.TargetHost; - isPemEqual = certChain == context.TargetPem; - return returnValue; - } - private class SslCredentialsTestServiceImpl : TestService.TestServiceBase { public override Task UnaryCall(SimpleRequest request, ServerCallContext context) diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index 5f80d3417a5..4323d40b6d3 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -901,6 +901,21 @@ grpcsharp_server_request_call(grpc_server* server, grpc_completion_queue* cq, &(ctx->request_metadata), cq, cq, ctx); } +/* Native callback dispatcher */ + +typedef int(GPR_CALLTYPE* grpcsharp_native_callback_dispatcher_func)( + void* tag, void* arg0, void* arg1, void* arg2, void* arg3, void* arg4, + void* arg5); + +static grpcsharp_native_callback_dispatcher_func native_callback_dispatcher = + NULL; + +GPR_EXPORT void GPR_CALLTYPE grpcsharp_native_callback_dispatcher_init( + grpcsharp_native_callback_dispatcher_func func) { + GPR_ASSERT(func); + native_callback_dispatcher = func; +} + /* Security */ static char* default_pem_root_certs = NULL; @@ -927,23 +942,18 @@ grpcsharp_override_default_ssl_roots(const char* pem_root_certs) { grpc_set_ssl_roots_override_callback(override_ssl_roots_handler); } -typedef int(GPR_CALLTYPE* grpcsharp_verify_peer_func)(const char* target_host, - const char* target_pem, - void* userdata, - int32_t isDestroy); - static void grpcsharp_verify_peer_destroy_handler(void* userdata) { - grpcsharp_verify_peer_func callback = - (grpcsharp_verify_peer_func)(intptr_t)userdata; - callback(NULL, NULL, NULL, 1); + native_callback_dispatcher(userdata, NULL, + NULL, (void*)1, NULL, + NULL, NULL); } static int grpcsharp_verify_peer_handler(const char* target_host, const char* target_pem, void* userdata) { - grpcsharp_verify_peer_func callback = - (grpcsharp_verify_peer_func)(intptr_t)userdata; - return callback(target_host, target_pem, NULL, 0); + return native_callback_dispatcher(userdata, (void*)target_host, + (void*)target_pem, (void*)0, NULL, + NULL, NULL); } @@ -951,13 +961,13 @@ GPR_EXPORT grpc_channel_credentials* GPR_CALLTYPE grpcsharp_ssl_credentials_create(const char* pem_root_certs, const char* key_cert_pair_cert_chain, const char* key_cert_pair_private_key, - grpcsharp_verify_peer_func verify_peer_func) { + void* verify_peer_callback_tag) { grpc_ssl_pem_key_cert_pair key_cert_pair; verify_peer_options verify_options; verify_peer_options* p_verify_options = NULL; - if (verify_peer_func != NULL) { + if (verify_peer_callback_tag != NULL) { verify_options.verify_peer_callback_userdata = - (void*)(intptr_t)verify_peer_func; + verify_peer_callback_tag; verify_options.verify_peer_destruct = grpcsharp_verify_peer_destroy_handler; verify_options.verify_peer_callback = grpcsharp_verify_peer_handler; @@ -1043,21 +1053,6 @@ grpcsharp_composite_call_credentials_create(grpc_call_credentials* creds1, return grpc_composite_call_credentials_create(creds1, creds2, NULL); } -/* Native callback dispatcher */ - -typedef int(GPR_CALLTYPE* grpcsharp_native_callback_dispatcher_func)( - void* tag, void* arg0, void* arg1, void* arg2, void* arg3, void* arg4, - void* arg5); - -static grpcsharp_native_callback_dispatcher_func native_callback_dispatcher = - NULL; - -GPR_EXPORT void GPR_CALLTYPE grpcsharp_native_callback_dispatcher_init( - grpcsharp_native_callback_dispatcher_func func) { - GPR_ASSERT(func); - native_callback_dispatcher = func; -} - /* Metadata credentials plugin */ GPR_EXPORT void GPR_CALLTYPE grpcsharp_metadata_credentials_notify_from_plugin( diff --git a/templates/src/csharp/Grpc.Core/Internal/native_methods.include b/templates/src/csharp/Grpc.Core/Internal/native_methods.include index 4cb71730529..e8ec4c87b06 100644 --- a/templates/src/csharp/Grpc.Core/Internal/native_methods.include +++ b/templates/src/csharp/Grpc.Core/Internal/native_methods.include @@ -44,7 +44,7 @@ native_method_signatures = [ 'void grpcsharp_channel_args_set_integer(ChannelArgsSafeHandle args, UIntPtr index, string key, int value)', 'void grpcsharp_channel_args_destroy(IntPtr args)', 'void grpcsharp_override_default_ssl_roots(string pemRootCerts)', - 'ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, VerifyPeerCallbackInternal verifyPeerCallback)', + 'ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag)', 'ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds)', 'void grpcsharp_channel_credentials_release(IntPtr credentials)', 'ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs)', From 046cd3533b85425631bf3e3be43da8fb77e5d8b3 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Sun, 31 Mar 2019 19:34:50 -0700 Subject: [PATCH 149/242] add license --- src/csharp/Grpc.Core/VerifyPeerContext.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/csharp/Grpc.Core/VerifyPeerContext.cs b/src/csharp/Grpc.Core/VerifyPeerContext.cs index b48984b093c..52a5fabf7c8 100644 --- a/src/csharp/Grpc.Core/VerifyPeerContext.cs +++ b/src/csharp/Grpc.Core/VerifyPeerContext.cs @@ -1,3 +1,21 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#endregion + namespace Grpc.Core { /// From d297ede96a5cb453e32d40ec22015e67e214942a Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Sun, 31 Mar 2019 19:47:11 -0700 Subject: [PATCH 150/242] honor C core's naming of verify_peer_callback arguments --- src/csharp/Grpc.Core/ChannelCredentials.cs | 4 ++-- src/csharp/Grpc.Core/VerifyPeerContext.cs | 18 +++++++++--------- src/csharp/ext/grpc_csharp_ext.c | 8 ++++---- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/csharp/Grpc.Core/ChannelCredentials.cs b/src/csharp/Grpc.Core/ChannelCredentials.cs index 2ecd3875e84..fbea40d0a4b 100644 --- a/src/csharp/Grpc.Core/ChannelCredentials.cs +++ b/src/csharp/Grpc.Core/ChannelCredentials.cs @@ -226,7 +226,7 @@ namespace Grpc.Core return VerifyPeerCallbackHandler(arg0, arg1, arg2 != IntPtr.Zero); } - private int VerifyPeerCallbackHandler(IntPtr host, IntPtr pem, bool isDestroy) + private int VerifyPeerCallbackHandler(IntPtr targetName, IntPtr peerPem, bool isDestroy) { if (isDestroy) { @@ -236,7 +236,7 @@ namespace Grpc.Core try { - var context = new VerifyPeerContext(Marshal.PtrToStringAnsi(host), Marshal.PtrToStringAnsi(pem)); + var context = new VerifyPeerContext(Marshal.PtrToStringAnsi(targetName), Marshal.PtrToStringAnsi(peerPem)); return this.verifyPeerCallback(context) ? 0 : 1; } diff --git a/src/csharp/Grpc.Core/VerifyPeerContext.cs b/src/csharp/Grpc.Core/VerifyPeerContext.cs index 52a5fabf7c8..b1dc60f8e27 100644 --- a/src/csharp/Grpc.Core/VerifyPeerContext.cs +++ b/src/csharp/Grpc.Core/VerifyPeerContext.cs @@ -27,22 +27,22 @@ namespace Grpc.Core /// /// Initializes a new instance of the class. /// - /// string containing the host name of the peer. - /// string containing PEM encoded certificate of the peer. - internal VerifyPeerContext(string targetHost, string targetPem) + /// The target name of the peer. + /// The PEM encoded certificate of the peer. + internal VerifyPeerContext(string targetName, string peerPem) { - this.TargetHost = targetHost; - this.TargetPem = targetPem; + this.TargetName = targetName; + this.PeerPem = peerPem; } /// - /// String containing the host name of the peer. + /// The target name of the peer. /// - public string TargetHost { get; } + public string TargetName { get; } /// - /// string containing PEM encoded certificate of the peer. + /// The PEM encoded certificate of the peer. /// - public string TargetPem { get; } + public string PeerPem { get; } } } diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index 4323d40b6d3..b3bb7c668ca 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -948,11 +948,11 @@ static void grpcsharp_verify_peer_destroy_handler(void* userdata) { NULL, NULL); } -static int grpcsharp_verify_peer_handler(const char* target_host, - const char* target_pem, +static int grpcsharp_verify_peer_handler(const char* target_name, + const char* peer_pem, void* userdata) { - return native_callback_dispatcher(userdata, (void*)target_host, - (void*)target_pem, (void*)0, NULL, + return native_callback_dispatcher(userdata, (void*)target_name, + (void*)peer_pem, (void*)0, NULL, NULL, NULL); } From c02aec32554a44b2d8180cd461ec1617ba0b113e Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 1 Apr 2019 00:13:54 -0400 Subject: [PATCH 151/242] clang format code --- src/csharp/ext/grpc_csharp_ext.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index b3bb7c668ca..061a5edc4ab 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -943,20 +943,16 @@ grpcsharp_override_default_ssl_roots(const char* pem_root_certs) { } static void grpcsharp_verify_peer_destroy_handler(void* userdata) { - native_callback_dispatcher(userdata, NULL, - NULL, (void*)1, NULL, - NULL, NULL); + native_callback_dispatcher(userdata, NULL, NULL, (void*)1, NULL, NULL, NULL); } static int grpcsharp_verify_peer_handler(const char* target_name, - const char* peer_pem, - void* userdata) { + const char* peer_pem, void* userdata) { return native_callback_dispatcher(userdata, (void*)target_name, - (void*)peer_pem, (void*)0, NULL, - NULL, NULL); + (void*)peer_pem, (void*)0, NULL, NULL, + NULL); } - GPR_EXPORT grpc_channel_credentials* GPR_CALLTYPE grpcsharp_ssl_credentials_create(const char* pem_root_certs, const char* key_cert_pair_cert_chain, @@ -966,10 +962,8 @@ grpcsharp_ssl_credentials_create(const char* pem_root_certs, verify_peer_options verify_options; verify_peer_options* p_verify_options = NULL; if (verify_peer_callback_tag != NULL) { - verify_options.verify_peer_callback_userdata = - verify_peer_callback_tag; - verify_options.verify_peer_destruct = - grpcsharp_verify_peer_destroy_handler; + verify_options.verify_peer_callback_userdata = verify_peer_callback_tag; + verify_options.verify_peer_destruct = grpcsharp_verify_peer_destroy_handler; verify_options.verify_peer_callback = grpcsharp_verify_peer_handler; p_verify_options = &verify_options; } From 57caf7840766999a1c9e44537730a821cbbacb79 Mon Sep 17 00:00:00 2001 From: Yihua Zhang Date: Mon, 1 Apr 2019 08:48:35 -0700 Subject: [PATCH 152/242] fix ALPN issues. --- .../ssl/ssl_security_connector.cc | 17 ++------ test/core/security/security_connector_test.cc | 43 ++++++++++++++++++- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc b/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc index 8a00bbb82ed..ad492f361aa 100644 --- a/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +++ b/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc @@ -44,24 +44,15 @@ namespace { grpc_error* ssl_check_peer( const char* peer_name, const tsi_peer* peer, grpc_core::RefCountedPtr* auth_context) { -#if TSI_OPENSSL_ALPN_SUPPORT - /* Check the ALPN if ALPN is supported. */ - const tsi_peer_property* p = - tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL); - if (p == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Cannot check peer: missing selected ALPN property."); + grpc_error* error = grpc_ssl_check_alpn(peer); + if (error != GRPC_ERROR_NONE) { + return error; } - if (!grpc_chttp2_is_alpn_version_supported(p->value.data, p->value.length)) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Cannot check peer: invalid ALPN value."); - } -#endif /* TSI_OPENSSL_ALPN_SUPPORT */ /* Check the peer name if specified. */ if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) { char* msg; gpr_asprintf(&msg, "Peer name %s is not in peer certificate", peer_name); - grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); + error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return error; } diff --git a/test/core/security/security_connector_test.cc b/test/core/security/security_connector_test.cc index 2a31763c73c..496f064439c 100644 --- a/test/core/security/security_connector_test.cc +++ b/test/core/security/security_connector_test.cc @@ -36,6 +36,10 @@ #include "src/core/tsi/transport_security.h" #include "test/core/util/test_config.h" +#ifndef TSI_OPENSSL_ALPN_SUPPORT +#define TSI_OPENSSL_ALPN_SUPPORT 1 +#endif + static int check_transport_security_type(const grpc_auth_context* ctx) { grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name( ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME); @@ -432,6 +436,43 @@ static void test_default_ssl_roots(void) { gpr_free(roots_env_var_file_path); } +static void test_peer_alpn_check(void) { +#if TSI_OPENSSL_ALPN_SUPPORT + tsi_peer peer; + const char* alpn = "grpc"; + const char* wrong_alpn = "wrong"; + // peer does not have a TSI_SSL_ALPN_SELECTED_PROTOCOL property. + GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property("wrong peer property name", + alpn, strlen(alpn), + &peer.properties[0]) == TSI_OK); + grpc_error* error = grpc_ssl_check_alpn(&peer); + GPR_ASSERT(error != GRPC_ERROR_NONE); + tsi_peer_destruct(&peer); + GRPC_ERROR_UNREF(error); + // peer has a TSI_SSL_ALPN_SELECTED_PROTOCOL property but with an incorrect + // property value. + GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property(TSI_SSL_ALPN_SELECTED_PROTOCOL, + wrong_alpn, strlen(wrong_alpn), + &peer.properties[0]) == TSI_OK); + error = grpc_ssl_check_alpn(&peer); + GPR_ASSERT(error != GRPC_ERROR_NONE); + tsi_peer_destruct(&peer); + GRPC_ERROR_UNREF(error); + // peer has a TSI_SSL_ALPN_SELECTED_PROTOCOL property with a correct property + // value. + GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property(TSI_SSL_ALPN_SELECTED_PROTOCOL, + alpn, strlen(alpn), + &peer.properties[0]) == TSI_OK); + GPR_ASSERT(grpc_ssl_check_alpn(&peer) == GRPC_ERROR_NONE); + tsi_peer_destruct(&peer); +#else + GPR_ASSERT(grpc_ssl_check_alpn(nullptr) == GRPC_ERROR_NONE); +#endif +} + int main(int argc, char** argv) { grpc::testing::TestEnvironment env(argc, argv); grpc_init(); @@ -443,7 +484,7 @@ int main(int argc, char** argv) { test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context(); test_ipv6_address_san(); test_default_ssl_roots(); - + test_peer_alpn_check(); grpc_shutdown(); return 0; } From 6ddee61f7567ed000867cdc3238101c087877c99 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 1 Apr 2019 13:31:36 -0700 Subject: [PATCH 153/242] Upgrade linux RBE tests to bazel 0.22 --- tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh b/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh index 863b43a1728..1882fe213fa 100755 --- a/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh +++ b/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh @@ -23,7 +23,7 @@ cp ${KOKORO_GFILE_DIR}/GrpcTesting-d0eeee2db331.json ${KOKORO_KEYSTORE_DIR}/4321 # Download bazel temp_dir="$(mktemp -d)" -wget -q https://github.com/bazelbuild/bazel/releases/download/0.20.0/bazel-0.20.0-linux-x86_64 -O "${temp_dir}/bazel" +wget -q https://github.com/bazelbuild/bazel/releases/download/0.22.0/bazel-0.22.0-linux-x86_64 -O "${temp_dir}/bazel" chmod 755 "${temp_dir}/bazel" export PATH="${temp_dir}:${PATH}" # This should show ${temp_dir}/bazel From 8e092b45fa2a45c4507d6703987e03ebf1740196 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Mon, 1 Apr 2019 13:23:44 -0700 Subject: [PATCH 154/242] Move ProtoServerReflectionPlugin from grpc to grpc_impl namespace --- BUILD | 1 + CMakeLists.txt | 1 + Makefile | 1 + build.yaml | 1 + .../ext/proto_server_reflection_plugin.h | 31 +++-------- .../ext/proto_server_reflection_plugin_impl.h | 54 +++++++++++++++++++ src/cpp/ext/proto_server_reflection_plugin.cc | 4 +- .../generated/sources_and_headers.json | 2 + 8 files changed, 69 insertions(+), 26 deletions(-) create mode 100644 include/grpcpp/ext/proto_server_reflection_plugin_impl.h diff --git a/BUILD b/BUILD index 7d71b9df9eb..ae1679d02db 100644 --- a/BUILD +++ b/BUILD @@ -2203,6 +2203,7 @@ grpc_cc_library( public_hdrs = [ "include/grpc++/ext/proto_server_reflection_plugin.h", "include/grpcpp/ext/proto_server_reflection_plugin.h", + "include/grpcpp/ext/proto_server_reflection_plugin_impl.h", ], deps = [ ":grpc++", diff --git a/CMakeLists.txt b/CMakeLists.txt index b80c2c4b1f6..e5965ad23eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3962,6 +3962,7 @@ target_link_libraries(grpc++_reflection foreach(_hdr include/grpc++/ext/proto_server_reflection_plugin.h include/grpcpp/ext/proto_server_reflection_plugin.h + include/grpcpp/ext/proto_server_reflection_plugin_impl.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) diff --git a/Makefile b/Makefile index 873a0e27a19..45cbf21b446 100644 --- a/Makefile +++ b/Makefile @@ -6296,6 +6296,7 @@ LIBGRPC++_REFLECTION_SRC = \ PUBLIC_HEADERS_CXX += \ include/grpc++/ext/proto_server_reflection_plugin.h \ include/grpcpp/ext/proto_server_reflection_plugin.h \ + include/grpcpp/ext/proto_server_reflection_plugin_impl.h \ LIBGRPC++_REFLECTION_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_REFLECTION_SRC)))) diff --git a/build.yaml b/build.yaml index 0a56c6f2802..61f71fe3e9e 100644 --- a/build.yaml +++ b/build.yaml @@ -1741,6 +1741,7 @@ libs: public_headers: - include/grpc++/ext/proto_server_reflection_plugin.h - include/grpcpp/ext/proto_server_reflection_plugin.h + - include/grpcpp/ext/proto_server_reflection_plugin_impl.h headers: - src/cpp/ext/proto_server_reflection.h src: diff --git a/include/grpcpp/ext/proto_server_reflection_plugin.h b/include/grpcpp/ext/proto_server_reflection_plugin.h index 1cfdc1b6ccf..f6f2202ffb3 100644 --- a/include/grpcpp/ext/proto_server_reflection_plugin.h +++ b/include/grpcpp/ext/proto_server_reflection_plugin.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,34 +19,17 @@ #ifndef GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_H #define GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_H -#include -#include - -namespace grpc { -class ServerInitializer; -class ProtoServerReflection; -} // namespace grpc +#include namespace grpc { namespace reflection { -class ProtoServerReflectionPlugin : public ::grpc::ServerBuilderPlugin { - public: - ProtoServerReflectionPlugin(); - ::grpc::string name() override; - void InitServer(::grpc::ServerInitializer* si) override; - void Finish(::grpc::ServerInitializer* si) override; - void ChangeArguments(const ::grpc::string& name, void* value) override; - bool has_async_methods() const override; - bool has_sync_methods() const override; +typedef ::grpc_impl::reflection::ProtoServerReflectionPlugin + ProtoServerReflectionPlugin; - private: - std::shared_ptr reflection_service_; -}; - -/// Add proto reflection plugin to \a ServerBuilder. -/// This function should be called at the static initialization time. -void InitProtoReflectionServerBuilderPlugin(); +static inline void InitProtoReflectionServerBuilderPlugin() { + ::grpc_impl::reflection::InitProtoReflectionServerBuilderPlugin(); +} } // namespace reflection } // namespace grpc diff --git a/include/grpcpp/ext/proto_server_reflection_plugin_impl.h b/include/grpcpp/ext/proto_server_reflection_plugin_impl.h new file mode 100644 index 00000000000..b7e68c0d8c8 --- /dev/null +++ b/include/grpcpp/ext/proto_server_reflection_plugin_impl.h @@ -0,0 +1,54 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_IMPL_H +#define GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_IMPL_H + +#include +#include + +namespace grpc { +class ServerInitializer; +class ProtoServerReflection; +} // namespace grpc + +namespace grpc_impl { +namespace reflection { + +class ProtoServerReflectionPlugin : public ::grpc::ServerBuilderPlugin { + public: + ProtoServerReflectionPlugin(); + ::grpc::string name() override; + void InitServer(::grpc::ServerInitializer* si) override; + void Finish(::grpc::ServerInitializer* si) override; + void ChangeArguments(const ::grpc::string& name, void* value) override; + bool has_async_methods() const override; + bool has_sync_methods() const override; + + private: + std::shared_ptr reflection_service_; +}; + +/// Add proto reflection plugin to \a ServerBuilder. +/// This function should be called at the static initialization time. +void InitProtoReflectionServerBuilderPlugin(); + +} // namespace reflection +} // namespace grpc_impl + +#endif // GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_IMPL_H diff --git a/src/cpp/ext/proto_server_reflection_plugin.cc b/src/cpp/ext/proto_server_reflection_plugin.cc index ee3ac3fee88..0ac4cb80c64 100644 --- a/src/cpp/ext/proto_server_reflection_plugin.cc +++ b/src/cpp/ext/proto_server_reflection_plugin.cc @@ -23,7 +23,7 @@ #include "src/cpp/ext/proto_server_reflection.h" -namespace grpc { +namespace grpc_impl { namespace reflection { ProtoServerReflectionPlugin::ProtoServerReflectionPlugin() @@ -79,4 +79,4 @@ struct StaticProtoReflectionPluginInitializer { } static_proto_reflection_plugin_initializer; } // namespace reflection -} // namespace grpc +} // namespace grpc_impl diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 8503ece32e4..1b633328abd 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -6629,6 +6629,7 @@ "headers": [ "include/grpc++/ext/proto_server_reflection_plugin.h", "include/grpcpp/ext/proto_server_reflection_plugin.h", + "include/grpcpp/ext/proto_server_reflection_plugin_impl.h", "src/cpp/ext/proto_server_reflection.h" ], "is_filegroup": false, @@ -6637,6 +6638,7 @@ "src": [ "include/grpc++/ext/proto_server_reflection_plugin.h", "include/grpcpp/ext/proto_server_reflection_plugin.h", + "include/grpcpp/ext/proto_server_reflection_plugin_impl.h", "src/cpp/ext/proto_server_reflection.cc", "src/cpp/ext/proto_server_reflection.h", "src/cpp/ext/proto_server_reflection_plugin.cc" From 39b40cbccbe8145dba88583bbdac0ff88a111198 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 1 Apr 2019 13:37:35 -0700 Subject: [PATCH 155/242] Add guard to the tv_nsec field of gpr_now return value --- src/core/lib/gpr/time_posix.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/core/lib/gpr/time_posix.cc b/src/core/lib/gpr/time_posix.cc index 1b3e36486fc..b5a47673676 100644 --- a/src/core/lib/gpr/time_posix.cc +++ b/src/core/lib/gpr/time_posix.cc @@ -108,6 +108,9 @@ static gpr_timespec now_impl(gpr_clock_type clock) { now.clock_type = clock; switch (clock) { case GPR_CLOCK_REALTIME: + // gettimeofday(...) function may return with a value whose tv_usec is + // greater than 1e6 on iOS The case is resolved with the guard at end of + // this function. gettimeofday(&now_tv, nullptr); now.tv_sec = now_tv.tv_sec; now.tv_nsec = now_tv.tv_usec * 1000; @@ -124,6 +127,16 @@ static gpr_timespec now_impl(gpr_clock_type clock) { abort(); } + // Guard the tv_nsec field in valid range for all clock types + while (GPR_UNLIKELY(now.tv_nsec >= 1e9)) { + now.tv_sec++; + now.tv_nsec -= 1e9; + } + while (GPR_UNLIKELY(now.tv_nsec < 0)) { + now.tv_sec--; + now.tv_nsec += 1e9; + } + return now; } #endif From 6da82f08bda80c4c167047bd20ef81655c27551b Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 1 Apr 2019 17:14:30 -0400 Subject: [PATCH 156/242] add job to give early warning about incompatible bazel changes --- .../grpc_bazel_rbe_incompatible_changes.sh | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tools/internal_ci/linux/grpc_bazel_rbe_incompatible_changes.sh diff --git a/tools/internal_ci/linux/grpc_bazel_rbe_incompatible_changes.sh b/tools/internal_ci/linux/grpc_bazel_rbe_incompatible_changes.sh new file mode 100644 index 00000000000..9c3712a07da --- /dev/null +++ b/tools/internal_ci/linux/grpc_bazel_rbe_incompatible_changes.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# Copyright 2017 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -ex + +# TODO(jtattermusch): use the latest version of bazel + +# Use --all_incompatible_changes to give an early warning about future +# bazel incompatibilities. +EXTRA_FLAGS="--config=opt --cache_test_results=no --all_incompatible_changes" +github/grpc/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh "${EXTRA_FLAGS}" From ee4e4bead3d604c37484a657e692d61c9527f70b Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Mon, 1 Apr 2019 14:55:29 -0700 Subject: [PATCH 157/242] pick_first: don't go into TRANSIENT_FAILURE upon empty update when in IDLE. --- .../lb_policy/pick_first/pick_first.cc | 26 ++++++++++++++----- test/cpp/end2end/client_lb_end2end_test.cc | 26 +++++++++++++++++++ 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index 86c6b25ac63..3da0b59f279 100644 --- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -188,8 +188,14 @@ void PickFirst::ShutdownLocked() { void PickFirst::ExitIdleLocked() { if (idle_) { idle_ = false; - if (subchannel_list_ != nullptr && - subchannel_list_->num_subchannels() > 0) { + if (subchannel_list_ == nullptr || + subchannel_list_->num_subchannels() == 0) { + grpc_error* error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING("No addresses to connect to"); + channel_control_helper()->UpdateState( + GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error), + UniquePtr(New(error))); + } else { subchannel_list_->subchannel(0) ->CheckConnectivityStateAndStartWatchingLocked(); } @@ -253,13 +259,19 @@ void PickFirst::UpdateLocked(UpdateArgs args) { grpc_channel_args_destroy(new_args); if (subchannel_list->num_subchannels() == 0) { // Empty update or no valid subchannels. Unsubscribe from all current - // subchannels and put the channel in TRANSIENT_FAILURE. + // subchannels. subchannel_list_ = std::move(subchannel_list); // Empty list. selected_ = nullptr; - grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"); - channel_control_helper()->UpdateState( - GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error), - UniquePtr(New(error))); + // If not idle, put the channel in TRANSIENT_FAILURE. + // (If we are idle, then this will happen in ExitIdleLocked() if we + // haven't gotten a non-empty update by the time the application tries + // to start a new call.) + if (!idle_) { + grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"); + channel_control_helper()->UpdateState( + GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error), + UniquePtr(New(error))); + } return; } // If one of the subchannels in the new list is already in state diff --git a/test/cpp/end2end/client_lb_end2end_test.cc b/test/cpp/end2end/client_lb_end2end_test.cc index 4244690d76b..77f9db94acc 100644 --- a/test/cpp/end2end/client_lb_end2end_test.cc +++ b/test/cpp/end2end/client_lb_end2end_test.cc @@ -940,6 +940,32 @@ TEST_F(ClientLbEnd2endTest, PickFirstPendingUpdateAndSelectedSubchannelFails) { WaitForServer(stub, 1, DEBUG_LOCATION, true /* ignore_failure */); } +TEST_F(ClientLbEnd2endTest, PickFirstStaysIdleUponEmptyUpdate) { + // Start server, send RPC, and make sure channel is READY. + const int kNumServers = 1; + StartServers(kNumServers); + auto channel = BuildChannel(""); // pick_first is the default. + auto stub = BuildStub(channel); + SetNextResolution(GetServersPorts()); + CheckRpcSendOk(stub, DEBUG_LOCATION); + EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY); + // Stop server. Channel should go into state IDLE. + servers_[0]->Shutdown(); + EXPECT_TRUE(WaitForChannelNotReady(channel.get())); + EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_IDLE); + // Now send resolver update that includes no addresses. Channel + // should stay in state IDLE. + SetNextResolution({}); + EXPECT_FALSE(channel->WaitForStateChange( + GRPC_CHANNEL_IDLE, grpc_timeout_seconds_to_deadline(3))); + // Now bring the backend back up and send a non-empty resolver update, + // and then try to send an RPC. Channel should go back into state READY. + StartServer(0); + SetNextResolution(GetServersPorts()); + CheckRpcSendOk(stub, DEBUG_LOCATION); + EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY); +} + TEST_F(ClientLbEnd2endTest, RoundRobin) { // Start servers and send one RPC per server. const int kNumServers = 3; From ac7c73605734de136d88b3f5dde8545a468cebe3 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Mon, 1 Apr 2019 14:34:27 -0700 Subject: [PATCH 158/242] Fix BUILD.gn file https://github.com/grpc/grpc/pull/18345 did not add a file to BUILD.gn causing generate_projects.sh to fail causing this error. Fixing it by running the generate_projects.sh script. --- BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/BUILD.gn b/BUILD.gn index 4e0bdb6586c..7ceea3c3b63 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1076,6 +1076,7 @@ config("grpc_config") { "include/grpcpp/impl/server_initializer_impl.h", "include/grpcpp/impl/service_type.h", "include/grpcpp/resource_quota.h", + "include/grpcpp/resource_quota_impl.h", "include/grpcpp/security/auth_context.h", "include/grpcpp/security/auth_metadata_processor.h", "include/grpcpp/security/credentials.h", From 7e6b5db90de63c820e80440502aa1427bcd72ed9 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 1 Apr 2019 15:34:41 -0700 Subject: [PATCH 159/242] Resolve merge issue --- BUILD | 1 - 1 file changed, 1 deletion(-) diff --git a/BUILD b/BUILD index f24e986329f..003914a3c5f 100644 --- a/BUILD +++ b/BUILD @@ -369,7 +369,6 @@ grpc_cc_library( "grpc++_codegen_base", "grpc++_codegen_base_src", "grpc++_codegen_proto", - "grpc_cfstream", ], ) From e69406008fc0c7b7a26c5d0bf79bc7b6efce503b Mon Sep 17 00:00:00 2001 From: Hao Nguyen Date: Mon, 1 Apr 2019 12:30:42 -0700 Subject: [PATCH 160/242] Explicitly set case_insensitive_enum_parsing = true when parsing JSON --- src/cpp/server/channelz/channelz_service.cc | 27 ++++++++++----------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/cpp/server/channelz/channelz_service.cc b/src/cpp/server/channelz/channelz_service.cc index c44a9ac0de6..0409991fe67 100644 --- a/src/cpp/server/channelz/channelz_service.cc +++ b/src/cpp/server/channelz/channelz_service.cc @@ -24,6 +24,12 @@ #include namespace grpc { +grpc::protobuf::util::Status ParseJson(const char* json_str, + grpc::protobuf::Message* message) { + grpc::protobuf::json::JsonParseOptions options; + options.case_insensitive_enum_parsing = true; + return grpc::protobuf::json::JsonStringToMessage(json_str, message, options); +} Status ChannelzService::GetTopChannels( ServerContext* unused, const channelz::v1::GetTopChannelsRequest* request, @@ -33,8 +39,7 @@ Status ChannelzService::GetTopChannels( return Status(StatusCode::INTERNAL, "grpc_channelz_get_top_channels returned null"); } - grpc::protobuf::util::Status s = - grpc::protobuf::json::JsonStringToMessage(json_str, response); + grpc::protobuf::util::Status s = ParseJson(json_str, response); gpr_free(json_str); if (!s.ok()) { return Status(StatusCode::INTERNAL, s.ToString()); @@ -50,8 +55,7 @@ Status ChannelzService::GetServers( return Status(StatusCode::INTERNAL, "grpc_channelz_get_servers returned null"); } - grpc::protobuf::util::Status s = - grpc::protobuf::json::JsonStringToMessage(json_str, response); + grpc::protobuf::util::Status s = ParseJson(json_str, response); gpr_free(json_str); if (!s.ok()) { return Status(StatusCode::INTERNAL, s.ToString()); @@ -67,8 +71,7 @@ Status ChannelzService::GetServer(ServerContext* unused, return Status(StatusCode::INTERNAL, "grpc_channelz_get_server returned null"); } - grpc::protobuf::util::Status s = - grpc::protobuf::json::JsonStringToMessage(json_str, response); + grpc::protobuf::util::Status s = ParseJson(json_str, response); gpr_free(json_str); if (!s.ok()) { return Status(StatusCode::INTERNAL, s.ToString()); @@ -85,8 +88,7 @@ Status ChannelzService::GetServerSockets( return Status(StatusCode::INTERNAL, "grpc_channelz_get_server_sockets returned null"); } - grpc::protobuf::util::Status s = - grpc::protobuf::json::JsonStringToMessage(json_str, response); + grpc::protobuf::util::Status s = ParseJson(json_str, response); gpr_free(json_str); if (!s.ok()) { return Status(StatusCode::INTERNAL, s.ToString()); @@ -101,8 +103,7 @@ Status ChannelzService::GetChannel( if (json_str == nullptr) { return Status(StatusCode::NOT_FOUND, "No object found for that ChannelId"); } - grpc::protobuf::util::Status s = - grpc::protobuf::json::JsonStringToMessage(json_str, response); + grpc::protobuf::util::Status s = ParseJson(json_str, response); gpr_free(json_str); if (!s.ok()) { return Status(StatusCode::INTERNAL, s.ToString()); @@ -118,8 +119,7 @@ Status ChannelzService::GetSubchannel( return Status(StatusCode::NOT_FOUND, "No object found for that SubchannelId"); } - grpc::protobuf::util::Status s = - grpc::protobuf::json::JsonStringToMessage(json_str, response); + grpc::protobuf::util::Status s = ParseJson(json_str, response); gpr_free(json_str); if (!s.ok()) { return Status(StatusCode::INTERNAL, s.ToString()); @@ -134,8 +134,7 @@ Status ChannelzService::GetSocket(ServerContext* unused, if (json_str == nullptr) { return Status(StatusCode::NOT_FOUND, "No object found for that SocketId"); } - grpc::protobuf::util::Status s = - grpc::protobuf::json::JsonStringToMessage(json_str, response); + grpc::protobuf::util::Status s = ParseJson(json_str, response); gpr_free(json_str); if (!s.ok()) { return Status(StatusCode::INTERNAL, s.ToString()); From f9a9639088b258f707ed1616b5044787b65ac698 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 1 Apr 2019 15:58:33 -0700 Subject: [PATCH 161/242] generate projects --- BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/BUILD.gn b/BUILD.gn index 4e0bdb6586c..7ceea3c3b63 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1076,6 +1076,7 @@ config("grpc_config") { "include/grpcpp/impl/server_initializer_impl.h", "include/grpcpp/impl/service_type.h", "include/grpcpp/resource_quota.h", + "include/grpcpp/resource_quota_impl.h", "include/grpcpp/security/auth_context.h", "include/grpcpp/security/auth_metadata_processor.h", "include/grpcpp/security/credentials.h", From 69bbf86d147f988d142914de0da8a0b6eac9afba Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 1 Apr 2019 16:01:49 -0700 Subject: [PATCH 162/242] Add a dummy function to grpc cfstream library --- src/core/lib/iomgr/cfstream_handle.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/core/lib/iomgr/cfstream_handle.cc b/src/core/lib/iomgr/cfstream_handle.cc index cf21c4fc511..2fda160f68a 100644 --- a/src/core/lib/iomgr/cfstream_handle.cc +++ b/src/core/lib/iomgr/cfstream_handle.cc @@ -192,4 +192,11 @@ void CFStreamHandle::Unref(const char* file, int line, const char* reason) { } } +#else + +/* Creating a dummy function so that the grpc_cfstream library will be + * non-empty. + */ +void CFStreamDummy() {} + #endif From cc44a729db8bec1f991be19f49fa86b681b5f49b Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 1 Apr 2019 20:42:02 -0400 Subject: [PATCH 163/242] improve doc comment --- src/csharp/Grpc.Core/ChannelCredentials.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/csharp/Grpc.Core/ChannelCredentials.cs b/src/csharp/Grpc.Core/ChannelCredentials.cs index fbea40d0a4b..dcbe9f3599b 100644 --- a/src/csharp/Grpc.Core/ChannelCredentials.cs +++ b/src/csharp/Grpc.Core/ChannelCredentials.cs @@ -109,8 +109,12 @@ namespace Grpc.Core /// /// Callback invoked with the expected targetHost and the peer's certificate. /// If false is returned by this callback then it is treated as a - /// verification failure. Invocation of the callback is blocking, so any + /// verification failure and the attempted connection will fail. + /// Invocation of the callback is blocking, so any /// implementation should be light-weight. + /// Note that the callback can potentially be invoked multiple times, + /// concurrently from different threads (e.g. when multiple connections + /// are being created for the same credentials). /// /// The associated with the callback /// true if verification succeeded, false otherwise. From c9974ab6c9090bb25e41f80a2f0fb8a12beb9f14 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 1 Apr 2019 20:55:50 -0400 Subject: [PATCH 164/242] refactor grpcsharp_ssl_credentials_create --- src/csharp/ext/grpc_csharp_ext.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index 061a5edc4ab..91d3957dbf0 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -960,25 +960,29 @@ grpcsharp_ssl_credentials_create(const char* pem_root_certs, void* verify_peer_callback_tag) { grpc_ssl_pem_key_cert_pair key_cert_pair; verify_peer_options verify_options; - verify_peer_options* p_verify_options = NULL; - if (verify_peer_callback_tag != NULL) { - verify_options.verify_peer_callback_userdata = verify_peer_callback_tag; - verify_options.verify_peer_destruct = grpcsharp_verify_peer_destroy_handler; - verify_options.verify_peer_callback = grpcsharp_verify_peer_handler; - p_verify_options = &verify_options; - } + grpc_ssl_pem_key_cert_pair* key_cert_pair_ptr = NULL; + verify_peer_options* verify_options_ptr = NULL; if (key_cert_pair_cert_chain || key_cert_pair_private_key) { + memset(&key_cert_pair, 0, sizeof(key_cert_pair)); key_cert_pair.cert_chain = key_cert_pair_cert_chain; key_cert_pair.private_key = key_cert_pair_private_key; - return grpc_ssl_credentials_create(pem_root_certs, &key_cert_pair, - p_verify_options, NULL); + key_cert_pair_ptr = &key_cert_pair; } else { GPR_ASSERT(!key_cert_pair_cert_chain); GPR_ASSERT(!key_cert_pair_private_key); - return grpc_ssl_credentials_create(pem_root_certs, NULL, p_verify_options, - NULL); } + + if (verify_peer_callback_tag != NULL) { + memset(&verify_options, 0, sizeof(verify_peer_options)); + verify_options.verify_peer_callback_userdata = verify_peer_callback_tag; + verify_options.verify_peer_destruct = grpcsharp_verify_peer_destroy_handler; + verify_options.verify_peer_callback = grpcsharp_verify_peer_handler; + verify_options_ptr = &verify_options; + } + + return grpc_ssl_credentials_create(pem_root_certs, key_cert_pair_ptr, + verify_options_ptr, NULL); } GPR_EXPORT void GPR_CALLTYPE From c4b7423ad019bb1d834c35cc3105305d24f3f2c0 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Mon, 1 Apr 2019 17:51:18 -0700 Subject: [PATCH 165/242] Fix errors due to rebase --- include/grpcpp/ext/proto_server_reflection_plugin_impl.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/grpcpp/ext/proto_server_reflection_plugin_impl.h b/include/grpcpp/ext/proto_server_reflection_plugin_impl.h index b7e68c0d8c8..a06fe14cdd7 100644 --- a/include/grpcpp/ext/proto_server_reflection_plugin_impl.h +++ b/include/grpcpp/ext/proto_server_reflection_plugin_impl.h @@ -23,19 +23,20 @@ #include namespace grpc { -class ServerInitializer; class ProtoServerReflection; } // namespace grpc namespace grpc_impl { +class ServerInitializer; + namespace reflection { class ProtoServerReflectionPlugin : public ::grpc::ServerBuilderPlugin { public: ProtoServerReflectionPlugin(); ::grpc::string name() override; - void InitServer(::grpc::ServerInitializer* si) override; - void Finish(::grpc::ServerInitializer* si) override; + void InitServer(::grpc_impl::ServerInitializer* si) override; + void Finish(::grpc_impl::ServerInitializer* si) override; void ChangeArguments(const ::grpc::string& name, void* value) override; bool has_async_methods() const override; bool has_sync_methods() const override; From 43b33ee371cb7f1237c363628f4acf6196216a37 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Mon, 1 Apr 2019 18:59:01 -0700 Subject: [PATCH 166/242] Fix errors from clang scripts --- include/grpcpp/server_builder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h index 5655761d081..bd8fa4621f7 100644 --- a/include/grpcpp/server_builder.h +++ b/include/grpcpp/server_builder.h @@ -39,7 +39,7 @@ namespace grpc_impl { class ServerCredentials; class ResourceQuota; -} +} // namespace grpc_impl namespace grpc { From 1ef874a03f21a2ba138a6763451fb774cd8cef6d Mon Sep 17 00:00:00 2001 From: Doug Fawley Date: Tue, 2 Apr 2019 13:53:21 -0700 Subject: [PATCH 167/242] change from 400 to 415 --- doc/PROTOCOL-HTTP2.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/PROTOCOL-HTTP2.md b/doc/PROTOCOL-HTTP2.md index 6b4d85db30a..e73e682bbe3 100644 --- a/doc/PROTOCOL-HTTP2.md +++ b/doc/PROTOCOL-HTTP2.md @@ -61,7 +61,7 @@ the form shown above. If **Timeout** is omitted a server should assume an infinite timeout. Client implementations are free to send a default minimum timeout based on their deployment requirements. -If **Content-Type** does not begin with "application/grpc", gRPC servers SHOULD respond with HTTP status of 400 (Bad Request). This will prevent other HTTP/2 clients from interpreting a gRPC error response, which uses status 200 (OK), as successful. +If **Content-Type** does not begin with "application/grpc", gRPC servers SHOULD respond with HTTP status of 415 (Unsupported Media Type). This will prevent other HTTP/2 clients from interpreting a gRPC error response, which uses status 200 (OK), as successful. **Custom-Metadata** is an arbitrary set of key-value pairs defined by the application layer. Header names starting with "grpc-" but not listed here are reserved for future GRPC use and should not be used by applications as **Custom-Metadata**. From 89a9e9d1dd000dff80719c460ed73322a388bbfb Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Tue, 2 Apr 2019 14:33:11 -0700 Subject: [PATCH 168/242] code review changes --- .../filters/client_channel/client_channel.cc | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index c856199d560..f638423a9de 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -107,12 +107,14 @@ class ExternalConnectivityWatcher { int size() const; ExternalConnectivityWatcher* Lookup(grpc_closure* on_complete) const; - void Append(ExternalConnectivityWatcher* watcher); - void Remove(ExternalConnectivityWatcher* watcher); + void Add(ExternalConnectivityWatcher* watcher); + void Remove(const ExternalConnectivityWatcher* watcher); private: - // head_ is guarded by its own mutex, since the size of the list needs - // to be grabbed immediately without polling on a CQ. + // head_ is guarded by a mutex, since the size() method needs to + // iterate over the list, and it's called from the C-core API + // function grpc_channel_num_external_connectivity_watchers(), which + // is synchronous and therefore cannot run in the combiner. mutable gpr_mu mu_; ExternalConnectivityWatcher* head_ = nullptr; }; @@ -260,9 +262,9 @@ ExternalConnectivityWatcher* ExternalConnectivityWatcher::WatcherList::Lookup( return w; } -void ExternalConnectivityWatcher::WatcherList::Append( +void ExternalConnectivityWatcher::WatcherList::Add( ExternalConnectivityWatcher* watcher) { - GPR_ASSERT(!Lookup(watcher->on_complete_)); + GPR_ASSERT(Lookup(watcher->on_complete_) == nullptr); MutexLock lock(&mu_); GPR_ASSERT(watcher->next_ == nullptr); watcher->next_ = head_; @@ -270,7 +272,7 @@ void ExternalConnectivityWatcher::WatcherList::Append( } void ExternalConnectivityWatcher::WatcherList::Remove( - ExternalConnectivityWatcher* watcher) { + const ExternalConnectivityWatcher* watcher) { MutexLock lock(&mu_); if (watcher == head_) { head_ = watcher->next_; @@ -333,7 +335,6 @@ void ExternalConnectivityWatcher::WatchConnectivityStateLocked( self->chand_->external_connectivity_watcher_list->Lookup( self->on_complete_); if (found != nullptr) { - GPR_ASSERT(found->on_complete_ == self->on_complete_); grpc_connectivity_state_notify_on_state_change( &found->chand_->state_tracker, nullptr, &found->my_closure_); } @@ -341,7 +342,7 @@ void ExternalConnectivityWatcher::WatchConnectivityStateLocked( return; } // New watcher. - self->chand_->external_connectivity_watcher_list->Append(self); + self->chand_->external_connectivity_watcher_list->Add(self); // This assumes that the closure is scheduled on the ExecCtx scheduler // and that GRPC_CLOSURE_RUN would run the closure immediately. GRPC_CLOSURE_RUN(self->watcher_timer_init_, GRPC_ERROR_NONE); From adf5f872846ce2d7f03193a72fdf04310ebd25ec Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Tue, 2 Apr 2019 15:16:29 -0700 Subject: [PATCH 169/242] more code review changes --- src/core/ext/filters/client_channel/client_channel.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index f638423a9de..34a24e2c712 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -127,7 +127,7 @@ class ExternalConnectivityWatcher { ~ExternalConnectivityWatcher(); private: - static void OnExternalWatchCompleteLocked(void* arg, grpc_error* error); + static void OnWatchCompleteLocked(void* arg, grpc_error* error); static void WatchConnectivityStateLocked(void* arg, grpc_error* ignored); channel_data* chand_; @@ -314,8 +314,8 @@ ExternalConnectivityWatcher::~ExternalConnectivityWatcher() { GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack, "ExternalConnectivityWatcher"); } -void ExternalConnectivityWatcher::OnExternalWatchCompleteLocked( - void* arg, grpc_error* error) { +void ExternalConnectivityWatcher::OnWatchCompleteLocked(void* arg, + grpc_error* error) { ExternalConnectivityWatcher* self = static_cast(arg); grpc_closure* on_complete = self->on_complete_; @@ -346,7 +346,7 @@ void ExternalConnectivityWatcher::WatchConnectivityStateLocked( // This assumes that the closure is scheduled on the ExecCtx scheduler // and that GRPC_CLOSURE_RUN would run the closure immediately. GRPC_CLOSURE_RUN(self->watcher_timer_init_, GRPC_ERROR_NONE); - GRPC_CLOSURE_INIT(&self->my_closure_, OnExternalWatchCompleteLocked, self, + GRPC_CLOSURE_INIT(&self->my_closure_, OnWatchCompleteLocked, self, grpc_combiner_scheduler(self->chand_->combiner)); grpc_connectivity_state_notify_on_state_change( &self->chand_->state_tracker, self->state_, &self->my_closure_); From 81c6081a3e392e5a3bff11285181de2d6693b3ae Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Wed, 3 Apr 2019 01:35:25 +0200 Subject: [PATCH 170/242] Fixing failures. --- src/core/lib/transport/transport.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/core/lib/transport/transport.cc b/src/core/lib/transport/transport.cc index 3fc089676ea..09306110c63 100644 --- a/src/core/lib/transport/transport.cc +++ b/src/core/lib/transport/transport.cc @@ -29,6 +29,7 @@ #include "src/core/lib/gpr/alloc.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/memory.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/slice/slice_internal.h" @@ -243,21 +244,23 @@ void grpc_transport_stream_op_batch_finish_with_failure( GRPC_ERROR_UNREF(error); } -typedef struct { +struct made_transport_op { grpc_closure outer_on_complete; - grpc_closure* inner_on_complete; + grpc_closure* inner_on_complete = nullptr; grpc_transport_op op; -} made_transport_op; + made_transport_op() { + memset(&outer_on_complete, 0, sizeof(outer_on_complete)); + } +}; static void destroy_made_transport_op(void* arg, grpc_error* error) { made_transport_op* op = static_cast(arg); GRPC_CLOSURE_SCHED(op->inner_on_complete, GRPC_ERROR_REF(error)); - gpr_free(op); + grpc_core::Delete(op); } grpc_transport_op* grpc_make_transport_op(grpc_closure* on_complete) { - made_transport_op* op = - static_cast(gpr_malloc(sizeof(*op))); + made_transport_op* op = grpc_core::New(); GRPC_CLOSURE_INIT(&op->outer_on_complete, destroy_made_transport_op, op, grpc_schedule_on_exec_ctx); op->inner_on_complete = on_complete; From cb6a2968fe1ebbb680bb56fe1c5eb844233205d5 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 3 Apr 2019 11:55:04 -0700 Subject: [PATCH 171/242] Make Interceptors work for lame channels --- src/cpp/client/create_channel.cc | 17 ++++++++--------- .../end2end/client_interceptors_end2end_test.cc | 12 ++++++++++++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/cpp/client/create_channel.cc b/src/cpp/client/create_channel.cc index 457daa674c7..4c725e6b145 100644 --- a/src/cpp/client/create_channel.cc +++ b/src/cpp/client/create_channel.cc @@ -68,15 +68,14 @@ std::shared_ptr CreateCustomChannelWithInterceptors( std::vector< std::unique_ptr> interceptor_creators) { - return creds ? creds->CreateChannelWithInterceptors( - target, args, std::move(interceptor_creators)) - : CreateChannelInternal( - "", - grpc_lame_client_channel_create( - nullptr, GRPC_STATUS_INVALID_ARGUMENT, - "Invalid credentials."), - std::vector>()); + return creds + ? creds->CreateChannelWithInterceptors( + target, args, std::move(interceptor_creators)) + : CreateChannelInternal("", + grpc_lame_client_channel_create( + nullptr, GRPC_STATUS_INVALID_ARGUMENT, + "Invalid credentials."), + std::move(interceptor_creators)); } } // namespace experimental diff --git a/test/cpp/end2end/client_interceptors_end2end_test.cc b/test/cpp/end2end/client_interceptors_end2end_test.cc index 421b31ad08a..f1aed093dc4 100644 --- a/test/cpp/end2end/client_interceptors_end2end_test.cc +++ b/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -611,6 +611,18 @@ TEST_F(ClientInterceptorsEnd2endTest, ClientInterceptorLoggingTest) { EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); } +TEST_F(ClientInterceptorsEnd2endTest, + LameChannelClientInterceptorHijackingTest) { + ChannelArguments args; + std::vector> + creators; + creators.push_back(std::unique_ptr( + new HijackingInterceptorFactory())); + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, nullptr, args, std::move(creators)); + MakeCall(channel); +} + TEST_F(ClientInterceptorsEnd2endTest, ClientInterceptorHijackingTest) { ChannelArguments args; DummyInterceptor::Reset(); From 8a698e2cfdb48c6109b93788b5903d23c63a3b1d Mon Sep 17 00:00:00 2001 From: Srini Polavarapu Date: Tue, 2 Apr 2019 12:27:50 -0700 Subject: [PATCH 172/242] release notes generation script --- tools/release/release_notes.py | 369 +++++++++++++++++++++++++++++++++ 1 file changed, 369 insertions(+) create mode 100644 tools/release/release_notes.py diff --git a/tools/release/release_notes.py b/tools/release/release_notes.py new file mode 100644 index 00000000000..46e01843535 --- /dev/null +++ b/tools/release/release_notes.py @@ -0,0 +1,369 @@ +#Copyright 2019 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Generate draft and release notes in Markdown from Github PRs. + +You'll need a github API token to avoid being rate-limited. See +https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/ + +This script collects PRs using "git log X..Y" from local repo where X and Y are +tags or release branch names of previous and current releases respectively. +Typically, notes are generated before the release branch is labelled so Y is +almost always the name of the release branch. X is the previous release branch +if this is not a patch release. Otherwise, it is the previous release tag. +For example, for release v1.17.0, X will be origin/v1.16.x and for release v1.17.3, +X will be v1.17.2. In both cases Y will be origin/v1.17.x. + +""" + +from collections import defaultdict +import base64 +import json + +content_header = """Draft Release Notes For {version} +-- +Final release notes will be generated from the PR titles that have *"release notes:yes"* label. If you have any additional notes please add them below. These will be appended to auto generated release notes. Previous releases notes are [here](https://github.com/grpc/grpc/releases). + +**Also, look at the PRs listed below against your name.** Please apply the missing labels and make necessary corrections (like fixing the title) to the PR in Github. Final release notes will be generated just before the release on {date}. + +Add additional notes not in PRs +-- + +Core +- + + +C++ +- + + +C# +- + + +Objective-C +- + + +PHP +- + + +Python +- + + +Ruby +- + + +""" + +rl_header = """This is the {version} release ([{name}](https://github.com/grpc/grpc/blob/master/doc/g_stands_for.md)) of gRPC Core. + +Please see the notes for the previous releases here: https://github.com/grpc/grpc/releases. Please consult https://grpc.io/ for all information regarding this product. + +This release contains refinements, improvements, and bug fixes, with highlights listed below. + + +""" + +HTML_URL = "https://github.com/grpc/grpc/pull/" +API_URL = 'https://api.github.com/repos/grpc/grpc/pulls/' + + +def get_commit_log(prevRelLabel, relBranch): + """Return the output of 'git log --pretty=online --merges prevRelLabel..relBranch' """ + + import subprocess + print("Running git log --pretty=oneline --merges " + prevRelLabel + ".." + + relBranch) + return subprocess.check_output([ + "git", "log", "--pretty=oneline", "--merges", + "%s..%s" % (prevRelLabel, relBranch) + ]) + + +def get_pr_data(pr_num): + """Get the PR data from github. Return 'error' on exception""" + + try: + from urllib2 import Request, urlopen, HTTPError + except ImportError: + import urllib + from urllib.request import Request, urlopen, HTTPError + url = API_URL + pr_num + req = Request(url) + req.add_header('Authorization', 'token %s' % TOKEN) + try: + f = urlopen(req) + response = json.loads(f.read().decode('utf-8')) + #print(response) + except HTTPError as e: + response = json.loads(e.fp.read().decode('utf-8')) + if 'message' in response: + print(response['message']) + response = "error" + return response + + +def get_pr_titles(gitLogs): + import re + error_count = 0 + match = b"Merge pull request #(\d+)" + prlist = re.findall(match, gitLogs, re.MULTILINE) + print("\nPRs matching 'Merge pull request #':") + print(prlist) + print("\n") + langs_pr = defaultdict(list) + for pr_num in prlist: + pr_num = str(pr_num) + print("---------- getting data for PR " + pr_num) + pr = get_pr_data(pr_num) + if pr == "error": + print("\n***ERROR*** Error in getting data for PR " + pr_num + "\n") + error_count += 1 + continue + rl_no_found = False + rl_yes_found = False + lang_found = False + for label in pr['labels']: + if label['name'] == 'release notes: yes': + rl_yes_found = True + elif label['name'] == 'release notes: no': + rl_no_found = True + elif label['name'].startswith('lang/'): + lang_found = True + lang = label['name'].split('/')[1].lower() + #lang = lang[0].upper() + lang[1:] + body = pr["title"] + if not body.endswith("."): + body = body + "." + if not pr["merged_by"]: + print("\n***ERROR***: No merge_by found for PR " + pr_num + "\n") + error_count += 1 + continue + + prline = "- " + body + " ([#" + pr_num + "](" + HTML_URL + pr_num + "))" + detail = "- " + pr["merged_by"]["login"] + "@ " + prline + prline = prline.encode('ascii', 'ignore') + detail = detail.encode('ascii', 'ignore') + print(detail) + #if no RL label + if not rl_no_found and not rl_yes_found: + print("Release notes label missing for " + pr_num) + langs_pr["nolabel"].append(detail) + elif rl_yes_found and not lang_found: + print("Lang label missing for " + pr_num) + langs_pr["nolang"].append(detail) + elif rl_no_found: + print("'Release notes:no' found for " + pr_num) + langs_pr["notinrel"].append(detail) + elif rl_yes_found: + print("'Release notes:yes' found for " + pr_num + " with lang " + + lang) + langs_pr["inrel"].append(detail) + langs_pr[lang].append(prline) + + return langs_pr, error_count + + +def write_draft(langs_pr, file, version, date): + file.write(content_header.format(version=version, date=date)) + file.write("PRs with missing release notes label - please fix in Github\n") + file.write("---\n") + file.write("\n") + if langs_pr["nolabel"]: + langs_pr["nolabel"].sort() + file.write("\n".join(langs_pr["nolabel"])) + else: + file.write("- None") + file.write("\n") + file.write("\n") + file.write("PRs with missing lang label - please fix in Github\n") + file.write("---\n") + file.write("\n") + if langs_pr["nolang"]: + langs_pr["nolang"].sort() + file.write("\n".join(langs_pr["nolang"])) + else: + file.write("- None") + file.write("\n") + file.write("\n") + file.write( + "PRs going into release notes - please check title and fix in Github. Do not edit here.\n" + ) + file.write("---\n") + file.write("\n") + if langs_pr["inrel"]: + langs_pr["inrel"].sort() + file.write("\n".join(langs_pr["inrel"])) + else: + file.write("- None") + file.write("\n") + file.write("\n") + file.write("PRs not going into release notes\n") + file.write("---\n") + file.write("\n") + if langs_pr["notinrel"]: + langs_pr["notinrel"].sort() + file.write("\n".join(langs_pr["notinrel"])) + else: + file.write("- None") + file.write("\n") + file.write("\n") + + +def write_rel_notes(langs_pr, file, version, name): + file.write(rl_header.format(version=version, name=name)) + if langs_pr["core"]: + file.write("Core\n---\n\n") + file.write("\n".join(langs_pr["core"])) + file.write("\n") + file.write("\n") + if langs_pr["c++"]: + file.write("C++\n---\n\n") + file.write("\n".join(langs_pr["c++"])) + file.write("\n") + file.write("\n") + if langs_pr["c#"]: + file.write("C#\n---\n\n") + file.write("\n".join(langs_pr["c#"])) + file.write("\n") + file.write("\n") + if langs_pr["go"]: + file.write("Go\n---\n\n") + file.write("\n".join(langs_pr["go"])) + file.write("\n") + file.write("\n") + if langs_pr["Java"]: + file.write("Java\n---\n\n") + file.write("\n".join(langs_pr["Java"])) + file.write("\n") + file.write("\n") + if langs_pr["node"]: + file.write("Node\n---\n\n") + file.write("\n".join(langs_pr["node"])) + file.write("\n") + file.write("\n") + if langs_pr["objc"]: + file.write("Objective-C\n---\n\n") + file.write("\n".join(langs_pr["objc"])) + file.write("\n") + file.write("\n") + if langs_pr["php"]: + file.write("PHP\n---\n\n") + file.write("\n".join(langs_pr["php"])) + file.write("\n") + file.write("\n") + if langs_pr["python"]: + file.write("Python\n---\n\n") + file.write("\n".join(langs_pr["python"])) + file.write("\n") + file.write("\n") + if langs_pr["ruby"]: + file.write("Ruby\n---\n\n") + file.write("\n".join(langs_pr["ruby"])) + file.write("\n") + file.write("\n") + if langs_pr["other"]: + file.write("Other\n---\n\n") + file.write("\n".join(langs_pr["other"])) + file.write("\n") + file.write("\n") + + +def build_args_parser(): + import argparse + parser = argparse.ArgumentParser() + parser.add_argument( + 'release_version', type=str, help='New release version e.g. 1.14.0') + parser.add_argument( + 'release_name', type=str, help='New release name e.g. gladiolus') + parser.add_argument( + 'release_date', type=str, help='Release date e.g. 7/30/18') + parser.add_argument( + 'previous_release_label', + type=str, + help='Previous release branch/tag e.g. v1.13.x') + parser.add_argument( + 'release_branch', + type=str, + help='Current release branch e.g. origin/v1.14.x') + parser.add_argument( + 'draft_filename', type=str, help='Name of the draft file e.g. draft.md') + parser.add_argument( + 'release_notes_filename', + type=str, + help='Name of the release notes file e.g. relnotes.md') + parser.add_argument( + '--token', + type=str, + default='', + help='GitHub API token to avoid being rate limited') + return parser + + +def main(): + import os + global TOKEN + + parser = build_args_parser() + args = parser.parse_args() + version, name, date = args.release_version, args.release_name, args.release_date + start, end = args.previous_release_label, args.release_branch + + TOKEN = args.token + if TOKEN == '': + try: + TOKEN = os.environ["GITHUB_TOKEN"] + except: + pass + if TOKEN == '': + print( + "Error: Github API token required. Either include param --token= or set environment variable GITHUB_TOKEN to your github token" + ) + return + + langs_pr, error_count = get_pr_titles(get_commit_log(start, end)) + + draft_file, rel_file = args.draft_filename, args.release_notes_filename + filename = os.path.abspath(draft_file) + if os.path.exists(filename): + file = open(filename, 'r+') + else: + file = open(filename, 'w') + + file.seek(0) + write_draft(langs_pr, file, version, date) + file.truncate() + file.close() + print("\nDraft notes written to " + filename) + + filename = os.path.abspath(rel_file) + if os.path.exists(filename): + file = open(filename, 'r+') + else: + file = open(filename, 'w') + + file.seek(0) + write_rel_notes(langs_pr, file, version, name) + file.truncate() + file.close() + print("\nRelease notes written to " + filename) + if error_count > 0: + print("\n\n*** Errors were encountered. See log. *********\n") + + +if __name__ == "__main__": + main() From ebf4cc1dfa7e9715af795233655777ddfd17e952 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 3 Apr 2019 12:48:27 -0700 Subject: [PATCH 173/242] Avoid crash in pick_first when invoking ExitIdleLocked() after shutdown. --- .../filters/client_channel/lb_policy/pick_first/pick_first.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index 3da0b59f279..332f66808e0 100644 --- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -186,6 +186,7 @@ void PickFirst::ShutdownLocked() { } void PickFirst::ExitIdleLocked() { + if (shutdown_) return; if (idle_) { idle_ = false; if (subchannel_list_ == nullptr || From 4d696c659ed62dc85c811912d0d68881e98b88cc Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Tue, 2 Apr 2019 18:58:53 -0700 Subject: [PATCH 174/242] Reviewer comments --- .../client_channel/client_channel_plugin.cc | 2 + .../filters/client_channel/service_config.cc | 2 + .../filters/client_channel/service_config.h | 73 ++++++++++++++++--- 3 files changed, 67 insertions(+), 10 deletions(-) diff --git a/src/core/ext/filters/client_channel/client_channel_plugin.cc b/src/core/ext/filters/client_channel/client_channel_plugin.cc index 2031ab449f5..3d6fa2edf4b 100644 --- a/src/core/ext/filters/client_channel/client_channel_plugin.cc +++ b/src/core/ext/filters/client_channel/client_channel_plugin.cc @@ -49,6 +49,7 @@ static bool append_filter(grpc_channel_stack_builder* builder, void* arg) { } void grpc_client_channel_init(void) { + grpc_core::ServiceConfig::ResetServiceConfigParsers(); grpc_core::LoadBalancingPolicyRegistry::Builder::InitRegistry(); grpc_core::ResolverRegistry::Builder::InitRegistry(); grpc_core::internal::ServerRetryThrottleMap::Init(); @@ -68,4 +69,5 @@ void grpc_client_channel_shutdown(void) { grpc_core::internal::ServerRetryThrottleMap::Shutdown(); grpc_core::ResolverRegistry::Builder::ShutdownRegistry(); grpc_core::LoadBalancingPolicyRegistry::Builder::ShutdownRegistry(); + grpc_core::ServiceConfig::ResetServiceConfigParsers(); } diff --git a/src/core/ext/filters/client_channel/service_config.cc b/src/core/ext/filters/client_channel/service_config.cc index e2d23010c8a..49b45b0e27f 100644 --- a/src/core/ext/filters/client_channel/service_config.cc +++ b/src/core/ext/filters/client_channel/service_config.cc @@ -34,6 +34,8 @@ namespace grpc_core { int ServiceConfig::registered_parsers_count = 0; +UniquePtr + ServiceConfig::registered_parsers[ServiceConfig::kMaxParsers]; RefCountedPtr ServiceConfig::Create(const char* json) { UniquePtr service_config_json(gpr_strdup(json)); diff --git a/src/core/ext/filters/client_channel/service_config.h b/src/core/ext/filters/client_channel/service_config.h index b211d732d3f..a65af4080c2 100644 --- a/src/core/ext/filters/client_channel/service_config.h +++ b/src/core/ext/filters/client_channel/service_config.h @@ -63,6 +63,24 @@ class ServiceConfigParsedObject { GRPC_ABSTRACT_BASE_CLASS; }; +/// This is the base class that all service config parsers should derive from. +class ServiceConfigParser { + public: + virtual ~ServiceConfigParser() = default; + + virtual UniquePtr ParseGlobalParams( + const grpc_json* json) { + return nullptr; + } + + virtual UniquePtr ParsePerMethodParams( + const grpc_json* json) { + return nullptr; + } + + GRPC_ABSTRACT_BASE_CLASS; +}; + class ServiceConfig : public RefCounted { public: /// Creates a new service config from parsing \a json_string. @@ -105,14 +123,40 @@ class ServiceConfig : public RefCounted { static RefCountedPtr MethodConfigTableLookup( const SliceHashTable>& table, const grpc_slice& path); - /// Retrieves the parsed object at index \a index. - ServiceConfigParsedObject* GetParsedServiceConfigObject(int index) { + /// Retrieves the parsed global service config object at index \a index. + ServiceConfigParsedObject* GetParsedGlobalServiceConfigObject(int index) { GPR_DEBUG_ASSERT(index < registered_parsers_count); - return parsed_service_config_objects[index].get(); + return parsed_global_service_config_objects[index].get(); } - typedef UniquePtr (*ServiceConfigParser)( - const char* service_config_json); + static constexpr int kMaxParsers = 32; + + /// Retrieves the vector of method service config objects for a given path \a + /// path. + const grpc_core::InlinedVector, + kMaxParsers>* + GetMethodServiceConfigObjectsVector(const grpc_slice& path) { + // auto parsed_service_config_objects[index].get(); + const auto* value = parsed_method_service_config_objects_table->Get(path); + // If we didn't find a match for the path, try looking for a wildcard + // entry (i.e., change "/service/method" to "/service/*"). + if (value == nullptr) { + char* path_str = grpc_slice_to_c_string(path); + const char* sep = strrchr(path_str, '/') + 1; + const size_t len = (size_t)(sep - path_str); + char* buf = (char*)gpr_malloc(len + 2); // '*' and NUL + memcpy(buf, path_str, len); + buf[len] = '*'; + buf[len + 1] = '\0'; + grpc_slice wildcard_path = grpc_slice_from_copied_string(buf); + gpr_free(buf); + value = parsed_method_service_config_objects_table->Get(wildcard_path); + grpc_slice_unref_internal(wildcard_path); + gpr_free(path_str); + if (value == nullptr) return nullptr; + } + return value; + } /// Globally register a service config parser. On successful registration, it /// returns the index at which the parser was registered. On failure, -1 is @@ -120,11 +164,18 @@ class ServiceConfig : public RefCounted { /// registered parser. Each parser is responsible for reading the service /// config json and returning a parsed object. This parsed object can later be /// retrieved using the same index that was returned at registration time. - static int RegisterParser(ServiceConfigParser func) { - registered_parsers[registered_parsers_count] = func; + static int RegisterParser(UniquePtr func) { + registered_parsers[registered_parsers_count] = std::move(func); return registered_parsers_count++; } + static void ResetServiceConfigParsers() { + for (auto i = 0; i < kMaxParsers; i++) { + registered_parsers[i].reset(nullptr); + } + registered_parsers_count = 0; + } + private: // So New() can call our private ctor. template @@ -149,16 +200,18 @@ class ServiceConfig : public RefCounted { grpc_json* json, CreateValue create_value, typename SliceHashTable>::Entry* entries, size_t* idx); - static constexpr int kMaxParsers = 32; static int registered_parsers_count; - static ServiceConfigParser registered_parsers[kMaxParsers]; + static UniquePtr registered_parsers[kMaxParsers]; UniquePtr service_config_json_; UniquePtr json_string_; // Underlying storage for json_tree. grpc_json* json_tree_; InlinedVector, kMaxParsers> - parsed_service_config_objects; + parsed_global_service_config_objects; + RefCountedPtr, kMaxParsers>>> + parsed_method_service_config_objects_table; }; // From c871a0bb32aeadf49efd6f454c7ed01b96da8b4c Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 3 Apr 2019 13:34:39 -0700 Subject: [PATCH 175/242] Remove commented code --- src/core/ext/filters/client_channel/service_config.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/ext/filters/client_channel/service_config.h b/src/core/ext/filters/client_channel/service_config.h index a65af4080c2..5caf420ff9d 100644 --- a/src/core/ext/filters/client_channel/service_config.h +++ b/src/core/ext/filters/client_channel/service_config.h @@ -136,7 +136,6 @@ class ServiceConfig : public RefCounted { const grpc_core::InlinedVector, kMaxParsers>* GetMethodServiceConfigObjectsVector(const grpc_slice& path) { - // auto parsed_service_config_objects[index].get(); const auto* value = parsed_method_service_config_objects_table->Get(path); // If we didn't find a match for the path, try looking for a wildcard // entry (i.e., change "/service/method" to "/service/*"). From 39765c1f656312ec4a319847899fbce07e8e234c Mon Sep 17 00:00:00 2001 From: Joe Bolinger Date: Wed, 3 Apr 2019 13:49:27 -0700 Subject: [PATCH 176/242] loosen dependency on googleapis-common-protos-types --- grpc.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grpc.gemspec b/grpc.gemspec index c128d07eaf8..b9d2107ee48 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -30,7 +30,7 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.add_dependency 'google-protobuf', '~> 3.7' - s.add_dependency 'googleapis-common-protos-types', '~> 1.0.0' + s.add_dependency 'googleapis-common-protos-types', '~> 1.0' s.add_development_dependency 'bundler', '~> 1.9' s.add_development_dependency 'facter', '~> 2.4' From 0e7ea67351bfbe30c49a60a97fd9944f9303689a Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 3 Apr 2019 13:59:08 -0700 Subject: [PATCH 177/242] Fix health check client to wait for subchannel call stack destruction before destroying the arena. --- .../client_channel/health/health_check_client.cc | 15 +++++++++++---- .../client_channel/health/health_check_client.h | 5 +++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/core/ext/filters/client_channel/health/health_check_client.cc b/src/core/ext/filters/client_channel/health/health_check_client.cc index e845d63d295..ba8393b0fd6 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.cc +++ b/src/core/ext/filters/client_channel/health/health_check_client.cc @@ -295,9 +295,6 @@ HealthCheckClient::CallState::~CallState() { gpr_log(GPR_INFO, "HealthCheckClient %p: destroying CallState %p", health_check_client_.get(), this); } - // The subchannel call is in the arena, so reset the pointer before we destroy - // the arena. - call_.reset(); for (size_t i = 0; i < GRPC_CONTEXT_COUNT; i++) { if (context_[i].destroy != nullptr) { context_[i].destroy(context_[i].value); @@ -439,12 +436,22 @@ void HealthCheckClient::CallState::StartBatch( GRPC_ERROR_NONE, "start_subchannel_batch"); } +void HealthCheckClient::CallState::AfterCallStackDestruction( + void *arg, grpc_error* error) { + HealthCheckClient::CallState* self = + static_cast(arg); + self->Unref(DEBUG_LOCATION, "cancel"); +} + void HealthCheckClient::CallState::OnCancelComplete(void* arg, grpc_error* error) { HealthCheckClient::CallState* self = static_cast(arg); GRPC_CALL_COMBINER_STOP(&self->call_combiner_, "health_cancel"); - self->Unref(DEBUG_LOCATION, "cancel"); + GRPC_CLOSURE_INIT(&self->after_call_stack_destruction_, + AfterCallStackDestruction, self, grpc_schedule_on_exec_ctx); + self->call_->SetAfterCallStackDestroy(&self->after_call_stack_destruction_); + self->call_.reset(); } void HealthCheckClient::CallState::StartCancel(void* arg, grpc_error* error) { diff --git a/src/core/ext/filters/client_channel/health/health_check_client.h b/src/core/ext/filters/client_channel/health/health_check_client.h index 7af88a54cfc..441d130e864 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.h +++ b/src/core/ext/filters/client_channel/health/health_check_client.h @@ -91,6 +91,8 @@ class HealthCheckClient : public InternallyRefCounted { grpc_error* PullSliceFromRecvMessage(); void DoneReadingRecvMessage(grpc_error* error); + static void AfterCallStackDestruction(void* arg, grpc_error* error); + RefCountedPtr health_check_client_; grpc_polling_entity pollent_; @@ -132,6 +134,9 @@ class HealthCheckClient : public InternallyRefCounted { grpc_metadata_batch recv_trailing_metadata_; grpc_transport_stream_stats collect_stats_; grpc_closure recv_trailing_metadata_ready_; + + // Closure for call stack destruction. + grpc_closure after_call_stack_destruction_; }; void StartCall(); From 80140f53fbdff809de00bde2df3e6180e3ed8cba Mon Sep 17 00:00:00 2001 From: Prashant Jaikumar Date: Wed, 3 Apr 2019 13:39:48 -0700 Subject: [PATCH 178/242] Fix CFStreamTest.NetworkTransition. It looks like CFStream doesn't detect stream errors when the server is listening on 127.0.0.2 and the interface is shutdown. The test started failing after address was changed from 10.0.0.1 to 127.0.0.2 in #18381. This commit changes the server address back to 10.0.0.1. --- test/cpp/end2end/cfstream_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cpp/end2end/cfstream_test.cc b/test/cpp/end2end/cfstream_test.cc index a6ed7c66d84..63d76e96f8b 100644 --- a/test/cpp/end2end/cfstream_test.cc +++ b/test/cpp/end2end/cfstream_test.cc @@ -62,7 +62,7 @@ class CFStreamTest : public ::testing::Test { CFStreamTest() : server_host_("grpctest"), interface_("lo0"), - ipv4_address_("127.0.0.2"), + ipv4_address_("10.0.0.1"), kRequestMessage_("🖖") {} void DNSUp() { From 13f2c19aee6c99eae455dfba40b137780ce3cafe Mon Sep 17 00:00:00 2001 From: Joe Bolinger Date: Wed, 3 Apr 2019 16:35:23 -0700 Subject: [PATCH 179/242] loosen dependecy in gemspec template --- templates/grpc.gemspec.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/grpc.gemspec.template b/templates/grpc.gemspec.template index 0e321717c99..d2b54a9c2f5 100644 --- a/templates/grpc.gemspec.template +++ b/templates/grpc.gemspec.template @@ -32,7 +32,7 @@ s.platform = Gem::Platform::RUBY s.add_dependency 'google-protobuf', '~> 3.7' - s.add_dependency 'googleapis-common-protos-types', '~> 1.0.0' + s.add_dependency 'googleapis-common-protos-types', '~> 1.0' s.add_development_dependency 'bundler', '~> 1.9' s.add_development_dependency 'facter', '~> 2.4' From 9bfd2354ecdd43c8688a26d60d3615a695eea784 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 3 Apr 2019 16:54:31 -0700 Subject: [PATCH 180/242] Add global and method parsing logic --- .../filters/client_channel/service_config.cc | 150 +++++++++++++++++- .../filters/client_channel/service_config.h | 53 +++++-- 2 files changed, 183 insertions(+), 20 deletions(-) diff --git a/src/core/ext/filters/client_channel/service_config.cc b/src/core/ext/filters/client_channel/service_config.cc index 49b45b0e27f..e01eb11fe98 100644 --- a/src/core/ext/filters/client_channel/service_config.cc +++ b/src/core/ext/filters/client_channel/service_config.cc @@ -35,7 +35,7 @@ namespace grpc_core { int ServiceConfig::registered_parsers_count = 0; UniquePtr - ServiceConfig::registered_parsers[ServiceConfig::kMaxParsers]; + ServiceConfig::registered_parsers[ServiceConfigParser::kMaxParsers]; RefCountedPtr ServiceConfig::Create(const char* json) { UniquePtr service_config_json(gpr_strdup(json)); @@ -45,15 +45,155 @@ RefCountedPtr ServiceConfig::Create(const char* json) { gpr_log(GPR_INFO, "failed to parse JSON for service config"); return nullptr; } - return MakeRefCounted(std::move(service_config_json), - std::move(json_string), json_tree); + bool success; + auto return_value = MakeRefCounted( + std::move(service_config_json), std::move(json_string), json_tree, + &success); + + // return return_value; + return success ? return_value : nullptr; } ServiceConfig::ServiceConfig(UniquePtr service_config_json, - UniquePtr json_string, grpc_json* json_tree) + UniquePtr json_string, grpc_json* json_tree, + bool* success) : service_config_json_(std::move(service_config_json)), json_string_(std::move(json_string)), - json_tree_(json_tree) {} + json_tree_(json_tree) { + GPR_DEBUG_ASSERT(success != nullptr); + if (json_tree->type != GRPC_JSON_OBJECT || json_tree->key != nullptr) { + gpr_log(GPR_ERROR, "error"); + *success = false; + return; + } + ParseGlobalParams(json_tree, success); + if (!*success) { + gpr_log(GPR_ERROR, "global error"); + return; + } + ParsePerMethodParams(json_tree, success); + if (!*success) { + gpr_log(GPR_ERROR, "local error"); + return; + } +} + +void ServiceConfig::ParseGlobalParams(const grpc_json* json_tree, + bool* success) { + GPR_DEBUG_ASSERT(success != nullptr); + GPR_DEBUG_ASSERT(json_tree_->type == GRPC_JSON_OBJECT); + GPR_DEBUG_ASSERT(json_tree_->key == nullptr); + for (auto i = 0; i < registered_parsers_count; i++) { + auto parsed_obj = + registered_parsers[i]->ParseGlobalParams(json_tree, success); + if (!*success) { + return; + } + parsed_global_service_config_objects.push_back(parsed_obj); + } + *success = true; +} + +bool ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( + const grpc_json* json, + SliceHashTable>::Entry* entries, + size_t* idx) { + auto objs_vector = MakeRefCounted(); + for (auto i = 0; i < registered_parsers_count; i++) { + bool success; + auto parsed_obj = + registered_parsers[i]->ParsePerMethodParams(json, &success); + if (!success) { + return false; + } + objs_vector->vector.push_back(parsed_obj); + } + // Construct list of paths. + InlinedVector, 10> paths; + for (grpc_json* child = json->child; child != nullptr; child = child->next) { + if (child->key == nullptr) continue; + if (strcmp(child->key, "name") == 0) { + if (child->type != GRPC_JSON_ARRAY) return false; + for (grpc_json* name = child->child; name != nullptr; name = name->next) { + UniquePtr path = ParseJsonMethodName(name); + if (path == nullptr) return false; + paths.push_back(std::move(path)); + } + } + } + if (paths.size() == 0) return false; // No names specified. + // Add entry for each path. + for (size_t i = 0; i < paths.size(); ++i) { + entries[*idx].key = grpc_slice_from_copied_string(paths[i].get()); + entries[*idx].value = objs_vector; // Takes a new ref. + ++*idx; + } + return true; +} + +void ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree, + bool* success) { + GPR_DEBUG_ASSERT(success != nullptr); + GPR_DEBUG_ASSERT(json_tree_->type == GRPC_JSON_OBJECT); + GPR_DEBUG_ASSERT(json_tree_->key == nullptr); + SliceHashTable>::Entry* entries = + nullptr; + size_t num_entries = 0; + for (grpc_json* field = json_tree->child; field != nullptr; + field = field->next) { + if (field->key == nullptr) { + *success = false; + return; + } + if (strcmp(field->key, "methodConfig") == 0) { + if (entries != nullptr) { + GPR_ASSERT(false); + } + if (field->type != GRPC_JSON_ARRAY) { + *success = false; + return; + } + for (grpc_json* method = field->child; method != nullptr; + method = method->next) { + int count = CountNamesInMethodConfig(method); + if (count <= 0) { + *success = false; + return; + } + num_entries += static_cast(count); + } + entries = static_cast< + SliceHashTable>::Entry*>( + gpr_zalloc( + num_entries * + sizeof(SliceHashTable< + RefCountedPtr>::Entry))); + size_t idx = 0; + for (grpc_json* method = field->child; method != nullptr; + method = method->next) { + if (!ParseJsonMethodConfigToServiceConfigObjectsTable(method, entries, + &idx)) { + for (size_t i = 0; i < idx; ++i) { + grpc_slice_unref_internal(entries[i].key); + entries[i].value.reset(); + } + gpr_free(entries); + *success = false; + return; + } + } + GPR_DEBUG_ASSERT(idx == num_entries); + break; + } + } + if (entries != nullptr) { + parsed_method_service_config_objects_table = + SliceHashTable>::Create( + num_entries, entries, nullptr); + gpr_free(entries); + } + *success = true; +} ServiceConfig::~ServiceConfig() { grpc_json_destroy(json_tree_); } diff --git a/src/core/ext/filters/client_channel/service_config.h b/src/core/ext/filters/client_channel/service_config.h index 5caf420ff9d..acf618b3432 100644 --- a/src/core/ext/filters/client_channel/service_config.h +++ b/src/core/ext/filters/client_channel/service_config.h @@ -56,7 +56,7 @@ namespace grpc_core { /// This is the base class that all service config parsers MUST use to store /// parsed service config data. -class ServiceConfigParsedObject { +class ServiceConfigParsedObject : public RefCounted { public: virtual ~ServiceConfigParsedObject() = default; @@ -68,19 +68,35 @@ class ServiceConfigParser { public: virtual ~ServiceConfigParser() = default; - virtual UniquePtr ParseGlobalParams( - const grpc_json* json) { + virtual RefCountedPtr ParseGlobalParams( + const grpc_json* json, bool* success) { + if (success != nullptr) { + *success = true; + } return nullptr; } - virtual UniquePtr ParsePerMethodParams( - const grpc_json* json) { + virtual RefCountedPtr ParsePerMethodParams( + const grpc_json* json, bool* success) { + if (success != nullptr) { + *success = true; + } return nullptr; } + static constexpr int kMaxParsers = 32; + GRPC_ABSTRACT_BASE_CLASS; }; +class ServiceConfigObjectsVector + : public RefCounted { + public: + grpc_core::InlinedVector, + ServiceConfigParser::kMaxParsers> + vector; +}; + class ServiceConfig : public RefCounted { public: /// Creates a new service config from parsing \a json_string. @@ -129,12 +145,9 @@ class ServiceConfig : public RefCounted { return parsed_global_service_config_objects[index].get(); } - static constexpr int kMaxParsers = 32; - /// Retrieves the vector of method service config objects for a given path \a /// path. - const grpc_core::InlinedVector, - kMaxParsers>* + const RefCountedPtr* GetMethodServiceConfigObjectsVector(const grpc_slice& path) { const auto* value = parsed_method_service_config_objects_table->Get(path); // If we didn't find a match for the path, try looking for a wildcard @@ -169,7 +182,7 @@ class ServiceConfig : public RefCounted { } static void ResetServiceConfigParsers() { - for (auto i = 0; i < kMaxParsers; i++) { + for (auto i = 0; i < ServiceConfigParser::kMaxParsers; i++) { registered_parsers[i].reset(nullptr); } registered_parsers_count = 0; @@ -182,7 +195,11 @@ class ServiceConfig : public RefCounted { // Takes ownership of \a json_tree. ServiceConfig(UniquePtr service_config_json, - UniquePtr json_string, grpc_json* json_tree); + UniquePtr json_string, grpc_json* json_tree, + bool* success); + + void ParseGlobalParams(const grpc_json* json_tree, bool* success); + void ParsePerMethodParams(const grpc_json* json_tree, bool* success); // Returns the number of names specified in the method config \a json. static int CountNamesInMethodConfig(grpc_json* json); @@ -199,17 +216,23 @@ class ServiceConfig : public RefCounted { grpc_json* json, CreateValue create_value, typename SliceHashTable>::Entry* entries, size_t* idx); + static bool ParseJsonMethodConfigToServiceConfigObjectsTable( + const grpc_json* json, + SliceHashTable>::Entry* entries, + size_t* idx); + static int registered_parsers_count; - static UniquePtr registered_parsers[kMaxParsers]; + static UniquePtr + registered_parsers[ServiceConfigParser::kMaxParsers]; UniquePtr service_config_json_; UniquePtr json_string_; // Underlying storage for json_tree. grpc_json* json_tree_; - InlinedVector, kMaxParsers> + InlinedVector, + ServiceConfigParser::kMaxParsers> parsed_global_service_config_objects; - RefCountedPtr, kMaxParsers>>> + RefCountedPtr>> parsed_method_service_config_objects_table; }; From 615c95ed5c5516bd59f16e1c22568298148467a7 Mon Sep 17 00:00:00 2001 From: Richard Belleville Date: Wed, 3 Apr 2019 18:13:52 -0700 Subject: [PATCH 181/242] Mitigate #18256 --- WORKSPACE | 54 ++++++++++++++++---------------------- bazel/grpc_python_deps.bzl | 15 +++++++++++ 2 files changed, 37 insertions(+), 32 deletions(-) create mode 100644 bazel/grpc_python_deps.bzl diff --git a/WORKSPACE b/WORKSPACE index 81371bf4187..18f389edd24 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -17,6 +17,26 @@ register_toolchains( "//third_party/toolchains:cc-toolchain-clang-x86_64-default", ) +# TODO(https://github.com/grpc/grpc/issues/18331): Move off of this dependency. +git_repository( + name = "org_pubref_rules_protobuf", + remote = "https://github.com/ghostwriternr/rules_protobuf", + tag = "v0.8.2.1-alpha", +) + +git_repository( + name = "io_bazel_rules_python", + commit = "8b5d0683a7d878b28fffe464779c8a53659fc645", + remote = "https://github.com/bazelbuild/rules_python.git", +) + +load("@io_bazel_rules_python//python:pip.bzl", "pip_repositories", "pip_import") + +pip_import( + name = "grpc_python_dependencies", + requirements = "//:requirements.bazel.txt", +) + http_archive( name = "cython", build_file = "//third_party:cython.BUILD", @@ -27,36 +47,6 @@ http_archive( ], ) -load("//third_party/py:python_configure.bzl", "python_configure") +load("//bazel:grpc_python_deps.bzl", "grpc_python_deps") -python_configure(name = "local_config_python") - -git_repository( - name = "io_bazel_rules_python", - commit = "8b5d0683a7d878b28fffe464779c8a53659fc645", - remote = "https://github.com/bazelbuild/rules_python.git", -) - -load("@io_bazel_rules_python//python:pip.bzl", "pip_repositories", "pip_import") - -pip_repositories() - -pip_import( - name = "grpc_python_dependencies", - requirements = "//:requirements.bazel.txt", -) - -load("@grpc_python_dependencies//:requirements.bzl", "pip_install") - -pip_install() - -# NOTE(https://github.com/pubref/rules_protobuf/pull/196): Switch to upstream repo after this gets merged. -git_repository( - name = "org_pubref_rules_protobuf", - remote = "https://github.com/ghostwriternr/rules_protobuf", - tag = "v0.8.2.1-alpha", -) - -load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_repositories") - -py_proto_repositories() +grpc_python_deps() diff --git a/bazel/grpc_python_deps.bzl b/bazel/grpc_python_deps.bzl new file mode 100644 index 00000000000..2f1fb02aff4 --- /dev/null +++ b/bazel/grpc_python_deps.bzl @@ -0,0 +1,15 @@ +load("//third_party/py:python_configure.bzl", "python_configure") +load("@io_bazel_rules_python//python:pip.bzl", "pip_repositories") +load("@grpc_python_dependencies//:requirements.bzl", "pip_install") +load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_repositories") + +def grpc_python_deps(): + # TODO(https://github.com/grpc/grpc/issues/18256): Remove conditional. + if hasattr(native, "http_archive"): + python_configure(name = "local_config_python") + pip_repositories() + pip_install() + py_proto_repositories() + else: + print("Building python gRPC with bazel 23.0+ is disabled pending resolution of https://github.com/grpc/grpc/issues/18256.") + From f3f6237e6dbaec990c939bc9ce391492e6d71715 Mon Sep 17 00:00:00 2001 From: Richard Belleville Date: Wed, 3 Apr 2019 18:16:24 -0700 Subject: [PATCH 182/242] Wrap long line --- bazel/grpc_python_deps.bzl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bazel/grpc_python_deps.bzl b/bazel/grpc_python_deps.bzl index 2f1fb02aff4..ec3df19e03a 100644 --- a/bazel/grpc_python_deps.bzl +++ b/bazel/grpc_python_deps.bzl @@ -11,5 +11,6 @@ def grpc_python_deps(): pip_install() py_proto_repositories() else: - print("Building python gRPC with bazel 23.0+ is disabled pending resolution of https://github.com/grpc/grpc/issues/18256.") + print("Building Python gRPC with bazel 23.0+ is disabled pending " + + "resolution of https://github.com/grpc/grpc/issues/18256.") From 0c8ef41a5ec2b0a8fbb41d0ec88ae3afb58c23dc Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 3 Apr 2019 18:53:14 -0700 Subject: [PATCH 183/242] Remove smart pointers from global registry --- .../ext/filters/client_channel/service_config.cc | 6 +++--- .../ext/filters/client_channel/service_config.h | 13 ++++--------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/core/ext/filters/client_channel/service_config.cc b/src/core/ext/filters/client_channel/service_config.cc index e01eb11fe98..46f34ac14a1 100644 --- a/src/core/ext/filters/client_channel/service_config.cc +++ b/src/core/ext/filters/client_channel/service_config.cc @@ -34,7 +34,7 @@ namespace grpc_core { int ServiceConfig::registered_parsers_count = 0; -UniquePtr +ServiceConfigParser ServiceConfig::registered_parsers[ServiceConfigParser::kMaxParsers]; RefCountedPtr ServiceConfig::Create(const char* json) { @@ -85,7 +85,7 @@ void ServiceConfig::ParseGlobalParams(const grpc_json* json_tree, GPR_DEBUG_ASSERT(json_tree_->key == nullptr); for (auto i = 0; i < registered_parsers_count; i++) { auto parsed_obj = - registered_parsers[i]->ParseGlobalParams(json_tree, success); + registered_parsers[i].ParseGlobalParams(json_tree, success); if (!*success) { return; } @@ -102,7 +102,7 @@ bool ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( for (auto i = 0; i < registered_parsers_count; i++) { bool success; auto parsed_obj = - registered_parsers[i]->ParsePerMethodParams(json, &success); + registered_parsers[i].ParsePerMethodParams(json, &success); if (!success) { return false; } diff --git a/src/core/ext/filters/client_channel/service_config.h b/src/core/ext/filters/client_channel/service_config.h index acf618b3432..0a2fea9735f 100644 --- a/src/core/ext/filters/client_channel/service_config.h +++ b/src/core/ext/filters/client_channel/service_config.h @@ -176,17 +176,12 @@ class ServiceConfig : public RefCounted { /// registered parser. Each parser is responsible for reading the service /// config json and returning a parsed object. This parsed object can later be /// retrieved using the same index that was returned at registration time. - static int RegisterParser(UniquePtr func) { - registered_parsers[registered_parsers_count] = std::move(func); + static int RegisterParser(const ServiceConfigParser& parser) { + registered_parsers[registered_parsers_count] = parser; return registered_parsers_count++; } - static void ResetServiceConfigParsers() { - for (auto i = 0; i < ServiceConfigParser::kMaxParsers; i++) { - registered_parsers[i].reset(nullptr); - } - registered_parsers_count = 0; - } + static void ResetServiceConfigParsers() { registered_parsers_count = 0; } private: // So New() can call our private ctor. @@ -222,7 +217,7 @@ class ServiceConfig : public RefCounted { size_t* idx); static int registered_parsers_count; - static UniquePtr + static ServiceConfigParser registered_parsers[ServiceConfigParser::kMaxParsers]; UniquePtr service_config_json_; From 0f0e774722f8d00682b6c2d6a05d4aebd22fd972 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 3 Apr 2019 19:02:43 -0700 Subject: [PATCH 184/242] Clean up --- .../filters/client_channel/service_config.cc | 20 +++++++--------- .../filters/client_channel/service_config.h | 24 ++++++++++--------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/core/ext/filters/client_channel/service_config.cc b/src/core/ext/filters/client_channel/service_config.cc index 46f34ac14a1..f47b170d75e 100644 --- a/src/core/ext/filters/client_channel/service_config.cc +++ b/src/core/ext/filters/client_channel/service_config.cc @@ -33,9 +33,9 @@ namespace grpc_core { -int ServiceConfig::registered_parsers_count = 0; +int ServiceConfig::registered_parsers_count_ = 0; ServiceConfigParser - ServiceConfig::registered_parsers[ServiceConfigParser::kMaxParsers]; + ServiceConfig::registered_parsers_[ServiceConfigParser::kMaxParsers]; RefCountedPtr ServiceConfig::Create(const char* json) { UniquePtr service_config_json(gpr_strdup(json)); @@ -50,7 +50,6 @@ RefCountedPtr ServiceConfig::Create(const char* json) { std::move(service_config_json), std::move(json_string), json_tree, &success); - // return return_value; return success ? return_value : nullptr; } @@ -62,18 +61,15 @@ ServiceConfig::ServiceConfig(UniquePtr service_config_json, json_tree_(json_tree) { GPR_DEBUG_ASSERT(success != nullptr); if (json_tree->type != GRPC_JSON_OBJECT || json_tree->key != nullptr) { - gpr_log(GPR_ERROR, "error"); *success = false; return; } ParseGlobalParams(json_tree, success); if (!*success) { - gpr_log(GPR_ERROR, "global error"); return; } ParsePerMethodParams(json_tree, success); if (!*success) { - gpr_log(GPR_ERROR, "local error"); return; } } @@ -83,13 +79,13 @@ void ServiceConfig::ParseGlobalParams(const grpc_json* json_tree, GPR_DEBUG_ASSERT(success != nullptr); GPR_DEBUG_ASSERT(json_tree_->type == GRPC_JSON_OBJECT); GPR_DEBUG_ASSERT(json_tree_->key == nullptr); - for (auto i = 0; i < registered_parsers_count; i++) { + for (auto i = 0; i < registered_parsers_count_; i++) { auto parsed_obj = - registered_parsers[i].ParseGlobalParams(json_tree, success); + registered_parsers_[i].ParseGlobalParams(json_tree, success); if (!*success) { return; } - parsed_global_service_config_objects.push_back(parsed_obj); + parsed_global_service_config_objects_.push_back(parsed_obj); } *success = true; } @@ -99,10 +95,10 @@ bool ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( SliceHashTable>::Entry* entries, size_t* idx) { auto objs_vector = MakeRefCounted(); - for (auto i = 0; i < registered_parsers_count; i++) { + for (auto i = 0; i < registered_parsers_count_; i++) { bool success; auto parsed_obj = - registered_parsers[i].ParsePerMethodParams(json, &success); + registered_parsers_[i].ParsePerMethodParams(json, &success); if (!success) { return false; } @@ -187,7 +183,7 @@ void ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree, } } if (entries != nullptr) { - parsed_method_service_config_objects_table = + parsed_method_service_config_objects_table_ = SliceHashTable>::Create( num_entries, entries, nullptr); gpr_free(entries); diff --git a/src/core/ext/filters/client_channel/service_config.h b/src/core/ext/filters/client_channel/service_config.h index 0a2fea9735f..9752bf7ba27 100644 --- a/src/core/ext/filters/client_channel/service_config.h +++ b/src/core/ext/filters/client_channel/service_config.h @@ -141,15 +141,15 @@ class ServiceConfig : public RefCounted { /// Retrieves the parsed global service config object at index \a index. ServiceConfigParsedObject* GetParsedGlobalServiceConfigObject(int index) { - GPR_DEBUG_ASSERT(index < registered_parsers_count); - return parsed_global_service_config_objects[index].get(); + GPR_DEBUG_ASSERT(index < registered_parsers_count_); + return parsed_global_service_config_objects_[index].get(); } /// Retrieves the vector of method service config objects for a given path \a /// path. const RefCountedPtr* GetMethodServiceConfigObjectsVector(const grpc_slice& path) { - const auto* value = parsed_method_service_config_objects_table->Get(path); + const auto* value = parsed_method_service_config_objects_table_->Get(path); // If we didn't find a match for the path, try looking for a wildcard // entry (i.e., change "/service/method" to "/service/*"). if (value == nullptr) { @@ -162,7 +162,7 @@ class ServiceConfig : public RefCounted { buf[len + 1] = '\0'; grpc_slice wildcard_path = grpc_slice_from_copied_string(buf); gpr_free(buf); - value = parsed_method_service_config_objects_table->Get(wildcard_path); + value = parsed_method_service_config_objects_table_->Get(wildcard_path); grpc_slice_unref_internal(wildcard_path); gpr_free(path_str); if (value == nullptr) return nullptr; @@ -177,11 +177,12 @@ class ServiceConfig : public RefCounted { /// config json and returning a parsed object. This parsed object can later be /// retrieved using the same index that was returned at registration time. static int RegisterParser(const ServiceConfigParser& parser) { - registered_parsers[registered_parsers_count] = parser; - return registered_parsers_count++; + registered_parsers_[registered_parsers_count_] = parser; + return registered_parsers_count_++; } - static void ResetServiceConfigParsers() { registered_parsers_count = 0; } + /// Should be called on initialization and shutdown. + static void ResetServiceConfigParsers() { registered_parsers_count_ = 0; } private: // So New() can call our private ctor. @@ -193,6 +194,7 @@ class ServiceConfig : public RefCounted { UniquePtr json_string, grpc_json* json_tree, bool* success); + // Helper functions to parse the service config void ParseGlobalParams(const grpc_json* json_tree, bool* success); void ParsePerMethodParams(const grpc_json* json_tree, bool* success); @@ -216,9 +218,9 @@ class ServiceConfig : public RefCounted { SliceHashTable>::Entry* entries, size_t* idx); - static int registered_parsers_count; + static int registered_parsers_count_; static ServiceConfigParser - registered_parsers[ServiceConfigParser::kMaxParsers]; + registered_parsers_[ServiceConfigParser::kMaxParsers]; UniquePtr service_config_json_; UniquePtr json_string_; // Underlying storage for json_tree. @@ -226,9 +228,9 @@ class ServiceConfig : public RefCounted { InlinedVector, ServiceConfigParser::kMaxParsers> - parsed_global_service_config_objects; + parsed_global_service_config_objects_; RefCountedPtr>> - parsed_method_service_config_objects_table; + parsed_method_service_config_objects_table_; }; // From cba5c089ebf4b52cf0f75535e2e8698d2fcacc8c Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 4 Apr 2019 10:18:53 +0200 Subject: [PATCH 185/242] Upgrade linux RBE tests to bazel 0.23.2 --- tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh b/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh index 1882fe213fa..dd34eac7b38 100755 --- a/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh +++ b/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh @@ -23,7 +23,7 @@ cp ${KOKORO_GFILE_DIR}/GrpcTesting-d0eeee2db331.json ${KOKORO_KEYSTORE_DIR}/4321 # Download bazel temp_dir="$(mktemp -d)" -wget -q https://github.com/bazelbuild/bazel/releases/download/0.22.0/bazel-0.22.0-linux-x86_64 -O "${temp_dir}/bazel" +wget -q https://github.com/bazelbuild/bazel/releases/download/0.23.2/bazel-0.23.2-linux-x86_64 -O "${temp_dir}/bazel" chmod 755 "${temp_dir}/bazel" export PATH="${temp_dir}:${PATH}" # This should show ${temp_dir}/bazel From 4a19b2f45f0c3cc66963e241f4a5507671b67b59 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Thu, 4 Apr 2019 07:25:41 -0700 Subject: [PATCH 186/242] Add atomic to ensure we don't cancel twice. Also convert existing seen_response_ to new atomic API. --- .../client_channel/health/health_check_client.cc | 11 ++++++----- .../client_channel/health/health_check_client.h | 7 +++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/core/ext/filters/client_channel/health/health_check_client.cc b/src/core/ext/filters/client_channel/health/health_check_client.cc index ba8393b0fd6..993582a01e7 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.cc +++ b/src/core/ext/filters/client_channel/health/health_check_client.cc @@ -287,7 +287,6 @@ HealthCheckClient::CallState::CallState( ->GetInitialCallSizeEstimate(0))), payload_(context_) { grpc_call_combiner_init(&call_combiner_); - gpr_atm_rel_store(&seen_response_, static_cast(0)); } HealthCheckClient::CallState::~CallState() { @@ -437,7 +436,7 @@ void HealthCheckClient::CallState::StartBatch( } void HealthCheckClient::CallState::AfterCallStackDestruction( - void *arg, grpc_error* error) { + void* arg, grpc_error* error) { HealthCheckClient::CallState* self = static_cast(arg); self->Unref(DEBUG_LOCATION, "cancel"); @@ -465,7 +464,9 @@ void HealthCheckClient::CallState::StartCancel(void* arg, grpc_error* error) { } void HealthCheckClient::CallState::Cancel() { - if (call_ != nullptr) { + bool expected = false; + if (cancelled_.CompareExchangeStrong(&expected, true, MemoryOrder::ACQ_REL, + MemoryOrder::ACQUIRE)) { Ref(DEBUG_LOCATION, "cancel").release(); GRPC_CALL_COMBINER_START( &call_combiner_, @@ -508,7 +509,7 @@ void HealthCheckClient::CallState::DoneReadingRecvMessage(grpc_error* error) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("backend unhealthy"); } health_check_client_->SetHealthStatus(state, error); - gpr_atm_rel_store(&seen_response_, static_cast(1)); + seen_response_.Store(true, MemoryOrder::RELEASE); grpc_slice_buffer_destroy_internal(&recv_message_buffer_); // Start another recv_message batch. // This re-uses the ref we're holding. @@ -642,7 +643,7 @@ void HealthCheckClient::CallState::CallEnded(bool retry) { health_check_client_->call_state_.reset(); if (retry) { GPR_ASSERT(!health_check_client_->shutting_down_); - if (static_cast(gpr_atm_acq_load(&seen_response_))) { + if (seen_response_.Load(MemoryOrder::ACQUIRE)) { // If the call fails after we've gotten a successful response, reset // the backoff and restart the call immediately. health_check_client_->retry_backoff_.Reset(); diff --git a/src/core/ext/filters/client_channel/health/health_check_client.h b/src/core/ext/filters/client_channel/health/health_check_client.h index 441d130e864..1fa4487c403 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.h +++ b/src/core/ext/filters/client_channel/health/health_check_client.h @@ -22,13 +22,13 @@ #include #include -#include #include #include "src/core/ext/filters/client_channel/client_channel_channelz.h" #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/gpr/arena.h" +#include "src/core/lib/gprpp/atomic.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/call_combiner.h" @@ -128,13 +128,16 @@ class HealthCheckClient : public InternallyRefCounted { OrphanablePtr recv_message_; grpc_closure recv_message_ready_; grpc_slice_buffer recv_message_buffer_; - gpr_atm seen_response_; + Atomic seen_response_{false}; // recv_trailing_metadata grpc_metadata_batch recv_trailing_metadata_; grpc_transport_stream_stats collect_stats_; grpc_closure recv_trailing_metadata_ready_; + // True if the cancel_stream batch has been started. + Atomic cancelled_{false}; + // Closure for call stack destruction. grpc_closure after_call_stack_destruction_; }; From 9222d4f3c23a7067f563bc3c223bd086bb9dee4c Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Thu, 4 Apr 2019 10:03:26 -0700 Subject: [PATCH 187/242] Fix clang issues --- include/grpcpp/server_builder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h index 182fdebeec9..0976b09bb8c 100644 --- a/include/grpcpp/server_builder.h +++ b/include/grpcpp/server_builder.h @@ -39,7 +39,7 @@ namespace grpc_impl { class Server; class ResourceQuota; -} // namespace grpc_impl +} // namespace grpc_impl namespace grpc { class AsyncGenericService; From 6287a60b5be0a3f86cbb2acf3c094e74443b2511 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Thu, 4 Apr 2019 10:11:52 -0700 Subject: [PATCH 188/242] Fix script errors --- BUILD.gn | 1 + CMakeLists.txt | 3 +++ Makefile | 3 +++ build.yaml | 1 + gRPC-C++.podspec | 1 + tools/doxygen/Doxyfile.c++ | 1 + tools/doxygen/Doxyfile.c++.internal | 1 + tools/run_tests/generated/sources_and_headers.json | 2 ++ 8 files changed, 13 insertions(+) diff --git a/BUILD.gn b/BUILD.gn index 5b0677023dd..0e9eb7fc95c 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1083,6 +1083,7 @@ config("grpc_config") { "include/grpcpp/security/auth_metadata_processor_impl.h", "include/grpcpp/security/credentials.h", "include/grpcpp/security/server_credentials.h", + "include/grpcpp/security/server_credentials_impl.h", "include/grpcpp/server.h", "include/grpcpp/server_builder.h", "include/grpcpp/server_context.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 50d69f90388..f4da2e83761 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3031,6 +3031,7 @@ foreach(_hdr include/grpcpp/security/auth_metadata_processor_impl.h include/grpcpp/security/credentials.h include/grpcpp/security/server_credentials.h + include/grpcpp/security/server_credentials_impl.h include/grpcpp/server.h include/grpcpp/server_builder.h include/grpcpp/server_context.h @@ -3630,6 +3631,7 @@ foreach(_hdr include/grpcpp/security/auth_metadata_processor_impl.h include/grpcpp/security/credentials.h include/grpcpp/security/server_credentials.h + include/grpcpp/security/server_credentials_impl.h include/grpcpp/server.h include/grpcpp/server_builder.h include/grpcpp/server_context.h @@ -4602,6 +4604,7 @@ foreach(_hdr include/grpcpp/security/auth_metadata_processor_impl.h include/grpcpp/security/credentials.h include/grpcpp/security/server_credentials.h + include/grpcpp/security/server_credentials_impl.h include/grpcpp/server.h include/grpcpp/server_builder.h include/grpcpp/server_context.h diff --git a/Makefile b/Makefile index 3ecbf182393..c2e57c2556e 100644 --- a/Makefile +++ b/Makefile @@ -5362,6 +5362,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/security/auth_metadata_processor_impl.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ + include/grpcpp/security/server_credentials_impl.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ @@ -5969,6 +5970,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/security/auth_metadata_processor_impl.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ + include/grpcpp/security/server_credentials_impl.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ @@ -6890,6 +6892,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/security/auth_metadata_processor_impl.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ + include/grpcpp/security/server_credentials_impl.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ diff --git a/build.yaml b/build.yaml index d5ce77c2844..0ddb8154669 100644 --- a/build.yaml +++ b/build.yaml @@ -1377,6 +1377,7 @@ filegroups: - include/grpcpp/security/auth_metadata_processor_impl.h - include/grpcpp/security/credentials.h - include/grpcpp/security/server_credentials.h + - include/grpcpp/security/server_credentials_impl.h - include/grpcpp/server.h - include/grpcpp/server_builder.h - include/grpcpp/server_context.h diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 602c66b93d9..b52124d0e0f 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -116,6 +116,7 @@ Pod::Spec.new do |s| 'include/grpcpp/security/auth_metadata_processor_impl.h', 'include/grpcpp/security/credentials.h', 'include/grpcpp/security/server_credentials.h', + 'include/grpcpp/security/server_credentials_impl.h', 'include/grpcpp/server.h', 'include/grpcpp/server_builder.h', 'include/grpcpp/server_context.h', diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 7dbb63813c2..f15219dd15e 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -1006,6 +1006,7 @@ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/auth_metadata_processor_impl.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ +include/grpcpp/security/server_credentials_impl.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index c7d29b228ab..c0a9d4c9bcf 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -1008,6 +1008,7 @@ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/auth_metadata_processor_impl.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ +include/grpcpp/security/server_credentials_impl.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 7a5d92abdaa..3fd9cc88375 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -10124,6 +10124,7 @@ "include/grpcpp/security/auth_metadata_processor_impl.h", "include/grpcpp/security/credentials.h", "include/grpcpp/security/server_credentials.h", + "include/grpcpp/security/server_credentials_impl.h", "include/grpcpp/server.h", "include/grpcpp/server_builder.h", "include/grpcpp/server_context.h", @@ -10241,6 +10242,7 @@ "include/grpcpp/security/auth_metadata_processor_impl.h", "include/grpcpp/security/credentials.h", "include/grpcpp/security/server_credentials.h", + "include/grpcpp/security/server_credentials_impl.h", "include/grpcpp/server.h", "include/grpcpp/server_builder.h", "include/grpcpp/server_context.h", From a93ff7d61752f08f2bea11fc8f31d51f0a8a812b Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Thu, 4 Apr 2019 10:14:26 -0700 Subject: [PATCH 189/242] Fix script errors --- include/grpcpp/impl/server_builder_plugin.h | 2 +- include/grpcpp/server_builder_impl.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/grpcpp/impl/server_builder_plugin.h b/include/grpcpp/impl/server_builder_plugin.h index ec5fd09fe45..dd600a839d7 100644 --- a/include/grpcpp/impl/server_builder_plugin.h +++ b/include/grpcpp/impl/server_builder_plugin.h @@ -27,7 +27,7 @@ namespace grpc_impl { class ServerBuilder; class ServerInitializer; -} +} // namespace grpc_impl namespace grpc { class ChannelArguments; diff --git a/include/grpcpp/server_builder_impl.h b/include/grpcpp/server_builder_impl.h index 9f7872b54da..2653a7ee881 100644 --- a/include/grpcpp/server_builder_impl.h +++ b/include/grpcpp/server_builder_impl.h @@ -38,7 +38,7 @@ struct grpc_resource_quota; namespace grpc_impl { class ResourceQuota; -} // namespace grpc_impl +} // namespace grpc_impl namespace grpc { class AsyncGenericService; @@ -194,7 +194,8 @@ class ServerBuilder { grpc_compression_algorithm algorithm); /// Set the attached buffer pool for this server - ServerBuilder& SetResourceQuota(const grpc_impl::ResourceQuota& resource_quota); + ServerBuilder& SetResourceQuota( + const grpc_impl::ResourceQuota& resource_quota); ServerBuilder& SetOption(std::unique_ptr option); From c28f16e481993b27e996a7959a6c48385788976f Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 4 Apr 2019 12:26:26 -0700 Subject: [PATCH 190/242] Reviewer comments --- .../client_channel/client_channel_plugin.cc | 4 +- .../resolver/dns/c_ares/dns_resolver_ares.cc | 3 +- .../client_channel/resolver_result_parsing.cc | 2 +- .../filters/client_channel/service_config.cc | 165 +++++++++++------- .../filters/client_channel/service_config.h | 104 +++++------ .../ext/filters/client_channel/subchannel.cc | 2 +- .../message_size/message_size_filter.cc | 2 +- 7 files changed, 153 insertions(+), 129 deletions(-) diff --git a/src/core/ext/filters/client_channel/client_channel_plugin.cc b/src/core/ext/filters/client_channel/client_channel_plugin.cc index 3d6fa2edf4b..8e76c4cbb15 100644 --- a/src/core/ext/filters/client_channel/client_channel_plugin.cc +++ b/src/core/ext/filters/client_channel/client_channel_plugin.cc @@ -49,7 +49,7 @@ static bool append_filter(grpc_channel_stack_builder* builder, void* arg) { } void grpc_client_channel_init(void) { - grpc_core::ServiceConfig::ResetServiceConfigParsers(); + grpc_core::ServiceConfig::Init(); grpc_core::LoadBalancingPolicyRegistry::Builder::InitRegistry(); grpc_core::ResolverRegistry::Builder::InitRegistry(); grpc_core::internal::ServerRetryThrottleMap::Init(); @@ -69,5 +69,5 @@ void grpc_client_channel_shutdown(void) { grpc_core::internal::ServerRetryThrottleMap::Shutdown(); grpc_core::ResolverRegistry::Builder::ShutdownRegistry(); grpc_core::LoadBalancingPolicyRegistry::Builder::ShutdownRegistry(); - grpc_core::ServiceConfig::ResetServiceConfigParsers(); + grpc_core::ServiceConfig::Shutdown(); } diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc index 7de1c221a13..7ce706724ee 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc @@ -308,7 +308,8 @@ void AresDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) { if (service_config_string != nullptr) { GRPC_CARES_TRACE_LOG("resolver:%p selected service config choice: %s", r, service_config_string); - result.service_config = ServiceConfig::Create(service_config_string); + result.service_config = + ServiceConfig::Create(service_config_string, nullptr); } gpr_free(service_config_string); } diff --git a/src/core/ext/filters/client_channel/resolver_result_parsing.cc b/src/core/ext/filters/client_channel/resolver_result_parsing.cc index daac4f0ff6a..f523ffe1610 100644 --- a/src/core/ext/filters/client_channel/resolver_result_parsing.cc +++ b/src/core/ext/filters/client_channel/resolver_result_parsing.cc @@ -52,7 +52,7 @@ ProcessedResolverResult::ProcessedResolverResult( const char* service_config_json = grpc_channel_arg_get_string( grpc_channel_args_find(resolver_result->args, GRPC_ARG_SERVICE_CONFIG)); if (service_config_json != nullptr) { - service_config_ = ServiceConfig::Create(service_config_json); + service_config_ = ServiceConfig::Create(service_config_json, nullptr); } } else { // Add the service config JSON to channel args so that it's diff --git a/src/core/ext/filters/client_channel/service_config.cc b/src/core/ext/filters/client_channel/service_config.cc index f47b170d75e..fbeb578a08b 100644 --- a/src/core/ext/filters/client_channel/service_config.cc +++ b/src/core/ext/filters/client_channel/service_config.cc @@ -33,11 +33,11 @@ namespace grpc_core { -int ServiceConfig::registered_parsers_count_ = 0; -ServiceConfigParser - ServiceConfig::registered_parsers_[ServiceConfigParser::kMaxParsers]; +ServiceConfig::ServiceConfigParserList* ServiceConfig::registered_parsers_ = + nullptr; -RefCountedPtr ServiceConfig::Create(const char* json) { +RefCountedPtr ServiceConfig::Create(const char* json, + grpc_error** error) { UniquePtr service_config_json(gpr_strdup(json)); UniquePtr json_string(gpr_strdup(json)); grpc_json* json_tree = grpc_json_parse_string(json_string.get()); @@ -45,137 +45,153 @@ RefCountedPtr ServiceConfig::Create(const char* json) { gpr_log(GPR_INFO, "failed to parse JSON for service config"); return nullptr; } - bool success; + + grpc_error* create_error; auto return_value = MakeRefCounted( std::move(service_config_json), std::move(json_string), json_tree, - &success); - - return success ? return_value : nullptr; + &create_error); + if (create_error != GRPC_ERROR_NONE) { + if (error != nullptr) { + *error = create_error; + } else { + GRPC_ERROR_UNREF(create_error); + } + return nullptr; + } + if (error != nullptr) { + *error = GRPC_ERROR_NONE; + } + return return_value; } ServiceConfig::ServiceConfig(UniquePtr service_config_json, UniquePtr json_string, grpc_json* json_tree, - bool* success) + grpc_error** error) : service_config_json_(std::move(service_config_json)), json_string_(std::move(json_string)), json_tree_(json_tree) { - GPR_DEBUG_ASSERT(success != nullptr); if (json_tree->type != GRPC_JSON_OBJECT || json_tree->key != nullptr) { - *success = false; + if (error != nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Malformed service Config JSON object"); + } return; } - ParseGlobalParams(json_tree, success); - if (!*success) { - return; + grpc_error* parser_error = ParseGlobalParams(json_tree); + if (parser_error != GRPC_ERROR_NONE) { + parser_error = ParsePerMethodParams(json_tree); } - ParsePerMethodParams(json_tree, success); - if (!*success) { - return; + if (error != nullptr) { + *error = parser_error; + } else { + GRPC_ERROR_UNREF(parser_error); } } -void ServiceConfig::ParseGlobalParams(const grpc_json* json_tree, - bool* success) { - GPR_DEBUG_ASSERT(success != nullptr); +grpc_error* ServiceConfig::ParseGlobalParams(const grpc_json* json_tree) { GPR_DEBUG_ASSERT(json_tree_->type == GRPC_JSON_OBJECT); GPR_DEBUG_ASSERT(json_tree_->key == nullptr); - for (auto i = 0; i < registered_parsers_count_; i++) { + for (size_t i = 0; i < registered_parsers_->size(); i++) { + grpc_error* error; auto parsed_obj = - registered_parsers_[i].ParseGlobalParams(json_tree, success); - if (!*success) { - return; + (*registered_parsers_)[i].ParseGlobalParams(json_tree, &error); + if (error != GRPC_ERROR_NONE) { + return error; } - parsed_global_service_config_objects_.push_back(parsed_obj); + parsed_global_service_config_objects_.push_back(std::move(parsed_obj)); } - *success = true; + return GRPC_ERROR_NONE; } -bool ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( +grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( const grpc_json* json, - SliceHashTable>::Entry* entries, + SliceHashTable::Entry* entries, size_t* idx) { - auto objs_vector = MakeRefCounted(); - for (auto i = 0; i < registered_parsers_count_; i++) { - bool success; + auto objs_vector = MakeUnique(); + for (size_t i = 0; i < registered_parsers_->size(); i++) { + grpc_error* error; auto parsed_obj = - registered_parsers_[i].ParsePerMethodParams(json, &success); - if (!success) { - return false; + (*registered_parsers_)[i].ParsePerMethodParams(json, &error); + if (error != GRPC_ERROR_NONE) { + return error; } - objs_vector->vector.push_back(parsed_obj); + objs_vector->push_back(std::move(parsed_obj)); } + const auto* vector_ptr = objs_vector.get(); + service_config_objects_vectors_storage_.push_back(std::move(objs_vector)); // Construct list of paths. InlinedVector, 10> paths; for (grpc_json* child = json->child; child != nullptr; child = child->next) { if (child->key == nullptr) continue; if (strcmp(child->key, "name") == 0) { - if (child->type != GRPC_JSON_ARRAY) return false; + if (child->type != GRPC_JSON_ARRAY) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "name should be of type Array"); + } for (grpc_json* name = child->child; name != nullptr; name = name->next) { UniquePtr path = ParseJsonMethodName(name); - if (path == nullptr) return false; + if (path == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to parse name"); + } paths.push_back(std::move(path)); } } } - if (paths.size() == 0) return false; // No names specified. + if (paths.size() == 0) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "No names specified in methodConfig"); + } // Add entry for each path. for (size_t i = 0; i < paths.size(); ++i) { entries[*idx].key = grpc_slice_from_copied_string(paths[i].get()); - entries[*idx].value = objs_vector; // Takes a new ref. + entries[*idx].value = vector_ptr; // Takes a new ref. ++*idx; } - return true; + return GRPC_ERROR_NONE; } -void ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree, - bool* success) { - GPR_DEBUG_ASSERT(success != nullptr); +grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) { GPR_DEBUG_ASSERT(json_tree_->type == GRPC_JSON_OBJECT); GPR_DEBUG_ASSERT(json_tree_->key == nullptr); - SliceHashTable>::Entry* entries = - nullptr; + SliceHashTable::Entry* entries = nullptr; size_t num_entries = 0; for (grpc_json* field = json_tree->child; field != nullptr; field = field->next) { if (field->key == nullptr) { - *success = false; - return; + return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Illegal key value - NULL"); } if (strcmp(field->key, "methodConfig") == 0) { if (entries != nullptr) { GPR_ASSERT(false); } if (field->type != GRPC_JSON_ARRAY) { - *success = false; - return; + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "methodConfig is not of type Array"); } for (grpc_json* method = field->child; method != nullptr; method = method->next) { int count = CountNamesInMethodConfig(method); if (count <= 0) { - *success = false; - return; + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "No names found in methodConfig"); } num_entries += static_cast(count); } entries = static_cast< - SliceHashTable>::Entry*>( - gpr_zalloc( - num_entries * - sizeof(SliceHashTable< - RefCountedPtr>::Entry))); + SliceHashTable::Entry*>(gpr_zalloc( + num_entries * + sizeof(SliceHashTable::Entry))); size_t idx = 0; for (grpc_json* method = field->child; method != nullptr; method = method->next) { - if (!ParseJsonMethodConfigToServiceConfigObjectsTable(method, entries, - &idx)) { + grpc_error* error = ParseJsonMethodConfigToServiceConfigObjectsTable( + method, entries, &idx); + if (error != GRPC_ERROR_NONE) { for (size_t i = 0; i < idx; ++i) { grpc_slice_unref_internal(entries[i].key); - entries[i].value.reset(); } gpr_free(entries); - *success = false; - return; + return error; } } GPR_DEBUG_ASSERT(idx == num_entries); @@ -184,11 +200,11 @@ void ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree, } if (entries != nullptr) { parsed_method_service_config_objects_table_ = - SliceHashTable>::Create( + SliceHashTable::Create( num_entries, entries, nullptr); gpr_free(entries); } - *success = true; + return GRPC_ERROR_NONE; } ServiceConfig::~ServiceConfig() { grpc_json_destroy(json_tree_); } @@ -248,4 +264,27 @@ UniquePtr ServiceConfig::ParseJsonMethodName(grpc_json* json) { return UniquePtr(path); } +const ServiceConfig::ServiceConfigObjectsVector* const* +ServiceConfig::GetMethodServiceConfigObjectsVector(const grpc_slice& path) { + const auto* value = parsed_method_service_config_objects_table_->Get(path); + // If we didn't find a match for the path, try looking for a wildcard + // entry (i.e., change "/service/method" to "/service/*"). + if (value == nullptr) { + char* path_str = grpc_slice_to_c_string(path); + const char* sep = strrchr(path_str, '/') + 1; + const size_t len = (size_t)(sep - path_str); + char* buf = (char*)gpr_malloc(len + 2); // '*' and NUL + memcpy(buf, path_str, len); + buf[len] = '*'; + buf[len + 1] = '\0'; + grpc_slice wildcard_path = grpc_slice_from_copied_string(buf); + gpr_free(buf); + value = parsed_method_service_config_objects_table_->Get(wildcard_path); + grpc_slice_unref_internal(wildcard_path); + gpr_free(path_str); + if (value == nullptr) return nullptr; + } + return value; +} + } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/service_config.h b/src/core/ext/filters/client_channel/service_config.h index 9752bf7ba27..90f1a2d790c 100644 --- a/src/core/ext/filters/client_channel/service_config.h +++ b/src/core/ext/filters/client_channel/service_config.h @@ -25,6 +25,7 @@ #include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/iomgr/error.h" #include "src/core/lib/json/json.h" #include "src/core/lib/slice/slice_hash_table.h" @@ -56,11 +57,9 @@ namespace grpc_core { /// This is the base class that all service config parsers MUST use to store /// parsed service config data. -class ServiceConfigParsedObject : public RefCounted { +class ServiceConfigParsedObject { public: virtual ~ServiceConfigParsedObject() = default; - - GRPC_ABSTRACT_BASE_CLASS; }; /// This is the base class that all service config parsers should derive from. @@ -68,40 +67,31 @@ class ServiceConfigParser { public: virtual ~ServiceConfigParser() = default; - virtual RefCountedPtr ParseGlobalParams( - const grpc_json* json, bool* success) { - if (success != nullptr) { - *success = true; + virtual UniquePtr ParseGlobalParams( + const grpc_json* json, grpc_error** error) { + if (error != nullptr) { + *error = GRPC_ERROR_NONE; } return nullptr; } - virtual RefCountedPtr ParsePerMethodParams( - const grpc_json* json, bool* success) { - if (success != nullptr) { - *success = true; + virtual UniquePtr ParsePerMethodParams( + const grpc_json* json, grpc_error** error) { + if (error != nullptr) { + *error = GRPC_ERROR_NONE; } return nullptr; } static constexpr int kMaxParsers = 32; - - GRPC_ABSTRACT_BASE_CLASS; -}; - -class ServiceConfigObjectsVector - : public RefCounted { - public: - grpc_core::InlinedVector, - ServiceConfigParser::kMaxParsers> - vector; }; class ServiceConfig : public RefCounted { public: /// Creates a new service config from parsing \a json_string. /// Returns null on parse error. - static RefCountedPtr Create(const char* json); + static RefCountedPtr Create(const char* json, + grpc_error** error); ~ServiceConfig(); @@ -141,34 +131,19 @@ class ServiceConfig : public RefCounted { /// Retrieves the parsed global service config object at index \a index. ServiceConfigParsedObject* GetParsedGlobalServiceConfigObject(int index) { - GPR_DEBUG_ASSERT(index < registered_parsers_count_); + GPR_DEBUG_ASSERT( + index < static_cast(parsed_global_service_config_objects_.size())); return parsed_global_service_config_objects_[index].get(); } + static constexpr int kMaxParsers = 32; + typedef InlinedVector, kMaxParsers> + ServiceConfigObjectsVector; + /// Retrieves the vector of method service config objects for a given path \a /// path. - const RefCountedPtr* - GetMethodServiceConfigObjectsVector(const grpc_slice& path) { - const auto* value = parsed_method_service_config_objects_table_->Get(path); - // If we didn't find a match for the path, try looking for a wildcard - // entry (i.e., change "/service/method" to "/service/*"). - if (value == nullptr) { - char* path_str = grpc_slice_to_c_string(path); - const char* sep = strrchr(path_str, '/') + 1; - const size_t len = (size_t)(sep - path_str); - char* buf = (char*)gpr_malloc(len + 2); // '*' and NUL - memcpy(buf, path_str, len); - buf[len] = '*'; - buf[len + 1] = '\0'; - grpc_slice wildcard_path = grpc_slice_from_copied_string(buf); - gpr_free(buf); - value = parsed_method_service_config_objects_table_->Get(wildcard_path); - grpc_slice_unref_internal(wildcard_path); - gpr_free(path_str); - if (value == nullptr) return nullptr; - } - return value; - } + const ServiceConfigObjectsVector* const* GetMethodServiceConfigObjectsVector( + const grpc_slice& path); /// Globally register a service config parser. On successful registration, it /// returns the index at which the parser was registered. On failure, -1 is @@ -177,12 +152,22 @@ class ServiceConfig : public RefCounted { /// config json and returning a parsed object. This parsed object can later be /// retrieved using the same index that was returned at registration time. static int RegisterParser(const ServiceConfigParser& parser) { - registered_parsers_[registered_parsers_count_] = parser; - return registered_parsers_count_++; + registered_parsers_->push_back(parser); + return registered_parsers_->size() - 1; } - /// Should be called on initialization and shutdown. - static void ResetServiceConfigParsers() { registered_parsers_count_ = 0; } + typedef InlinedVector + ServiceConfigParserList; + + static void Init() { + GPR_ASSERT(registered_parsers_ == nullptr); + registered_parsers_ = New(); + } + + static void Shutdown() { + Delete(registered_parsers_); + registered_parsers_ = nullptr; + } private: // So New() can call our private ctor. @@ -192,11 +177,11 @@ class ServiceConfig : public RefCounted { // Takes ownership of \a json_tree. ServiceConfig(UniquePtr service_config_json, UniquePtr json_string, grpc_json* json_tree, - bool* success); + grpc_error** error); // Helper functions to parse the service config - void ParseGlobalParams(const grpc_json* json_tree, bool* success); - void ParsePerMethodParams(const grpc_json* json_tree, bool* success); + grpc_error* ParseGlobalParams(const grpc_json* json_tree); + grpc_error* ParsePerMethodParams(const grpc_json* json_tree); // Returns the number of names specified in the method config \a json. static int CountNamesInMethodConfig(grpc_json* json); @@ -213,24 +198,23 @@ class ServiceConfig : public RefCounted { grpc_json* json, CreateValue create_value, typename SliceHashTable>::Entry* entries, size_t* idx); - static bool ParseJsonMethodConfigToServiceConfigObjectsTable( + grpc_error* ParseJsonMethodConfigToServiceConfigObjectsTable( const grpc_json* json, - SliceHashTable>::Entry* entries, + SliceHashTable::Entry* entries, size_t* idx); - static int registered_parsers_count_; - static ServiceConfigParser - registered_parsers_[ServiceConfigParser::kMaxParsers]; + static ServiceConfigParserList* registered_parsers_; UniquePtr service_config_json_; UniquePtr json_string_; // Underlying storage for json_tree. grpc_json* json_tree_; - InlinedVector, - ServiceConfigParser::kMaxParsers> + InlinedVector, kMaxParsers> parsed_global_service_config_objects_; - RefCountedPtr>> + RefCountedPtr> parsed_method_service_config_objects_table_; + InlinedVector, kMaxParsers> + service_config_objects_vectors_storage_; }; // diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 8bb0c4c3498..d66779e6192 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -591,7 +591,7 @@ Subchannel::Subchannel(SubchannelKey* key, grpc_connector* connector, grpc_channel_args_find(args_, GRPC_ARG_SERVICE_CONFIG)); if (service_config_json != nullptr) { RefCountedPtr service_config = - ServiceConfig::Create(service_config_json); + ServiceConfig::Create(service_config_json, nullptr); if (service_config != nullptr) { HealthCheckParams params; service_config->ParseGlobalParams(HealthCheckParams::Parse, ¶ms); diff --git a/src/core/ext/filters/message_size/message_size_filter.cc b/src/core/ext/filters/message_size/message_size_filter.cc index 8a422ddca54..8c2a32cc618 100644 --- a/src/core/ext/filters/message_size/message_size_filter.cc +++ b/src/core/ext/filters/message_size/message_size_filter.cc @@ -320,7 +320,7 @@ static grpc_error* init_channel_elem(grpc_channel_element* elem, const char* service_config_str = grpc_channel_arg_get_string(channel_arg); if (service_config_str != nullptr) { grpc_core::RefCountedPtr service_config = - grpc_core::ServiceConfig::Create(service_config_str); + grpc_core::ServiceConfig::Create(service_config_str, nullptr); if (service_config != nullptr) { chand->method_limit_table = service_config->CreateMethodConfigTable( grpc_core::MessageSizeLimits::CreateFromJson); From 190609d332e4b413a4e1ffd93b66ca99ebe6927b Mon Sep 17 00:00:00 2001 From: Srini Polavarapu Date: Thu, 4 Apr 2019 13:01:47 -0700 Subject: [PATCH 191/242] add v1.19.0 to interop matrix for cxx, python, csharp --- tools/interop_matrix/client_matrix.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/interop_matrix/client_matrix.py b/tools/interop_matrix/client_matrix.py index 654dfd6faef..013b9d0f1ee 100644 --- a/tools/interop_matrix/client_matrix.py +++ b/tools/interop_matrix/client_matrix.py @@ -99,6 +99,7 @@ LANG_RELEASE_MATRIX = { ('v1.16.0', ReleaseInfo()), ('v1.17.1', ReleaseInfo()), ('v1.18.0', ReleaseInfo()), + ('v1.19.0', ReleaseInfo()), ]), 'go': OrderedDict([ @@ -164,6 +165,7 @@ LANG_RELEASE_MATRIX = { ('v1.16.0', ReleaseInfo(testcases_file='python__v1.11.1')), ('v1.17.1', ReleaseInfo(testcases_file='python__v1.11.1')), ('v1.18.0', ReleaseInfo()), + ('v1.19.0', ReleaseInfo()), ]), 'node': OrderedDict([ @@ -210,6 +212,9 @@ LANG_RELEASE_MATRIX = { ReleaseInfo(patch=[ 'tools/dockerfile/interoptest/grpc_interop_ruby/build_interop.sh', ])), + # TODO: https://github.com/grpc/grpc/issues/18262. + # If you are not encountering the error in above issue + # go ahead and upload the docker image for new releases. ]), 'php': OrderedDict([ @@ -231,6 +236,8 @@ LANG_RELEASE_MATRIX = { ('v1.16.0', ReleaseInfo()), ('v1.17.1', ReleaseInfo()), ('v1.18.0', ReleaseInfo()), + # TODO:https://github.com/grpc/grpc/issues/18264 + # Error in above issues needs to be resolved. ]), 'csharp': OrderedDict([ @@ -258,5 +265,6 @@ LANG_RELEASE_MATRIX = { ('v1.16.0', ReleaseInfo(testcases_file='csharp__v1.3.9')), ('v1.17.1', ReleaseInfo(testcases_file='csharp__v1.3.9')), ('v1.18.0', ReleaseInfo()), + ('v1.19.0', ReleaseInfo()), ]), } From fbe3b3575fcb8f16327e16b36b2dfcc2d5e82018 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 4 Apr 2019 16:05:43 -0700 Subject: [PATCH 192/242] Cleanup and continue parsing service config even if parser errors are received --- .../filters/client_channel/service_config.cc | 87 ++++++++----------- .../filters/client_channel/service_config.h | 36 ++++---- 2 files changed, 56 insertions(+), 67 deletions(-) diff --git a/src/core/ext/filters/client_channel/service_config.cc b/src/core/ext/filters/client_channel/service_config.cc index fbeb578a08b..b03bbb127ef 100644 --- a/src/core/ext/filters/client_channel/service_config.cc +++ b/src/core/ext/filters/client_channel/service_config.cc @@ -33,19 +33,19 @@ namespace grpc_core { -ServiceConfig::ServiceConfigParserList* ServiceConfig::registered_parsers_ = - nullptr; - +ServiceConfig::ServiceConfigParserList* ServiceConfig::registered_parsers_; RefCountedPtr ServiceConfig::Create(const char* json, grpc_error** error) { UniquePtr service_config_json(gpr_strdup(json)); UniquePtr json_string(gpr_strdup(json)); grpc_json* json_tree = grpc_json_parse_string(json_string.get()); if (json_tree == nullptr) { - gpr_log(GPR_INFO, "failed to parse JSON for service config"); + if (error != nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "failed to parse JSON for service config"); + } return nullptr; } - grpc_error* create_error; auto return_value = MakeRefCounted( std::move(service_config_json), std::move(json_string), json_tree, @@ -70,37 +70,28 @@ ServiceConfig::ServiceConfig(UniquePtr service_config_json, : service_config_json_(std::move(service_config_json)), json_string_(std::move(json_string)), json_tree_(json_tree) { + GPR_DEBUG_ASSERT(error != nullptr); if (json_tree->type != GRPC_JSON_OBJECT || json_tree->key != nullptr) { - if (error != nullptr) { - *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Malformed service Config JSON object"); - } + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Malformed service Config JSON object"); return; } - grpc_error* parser_error = ParseGlobalParams(json_tree); - if (parser_error != GRPC_ERROR_NONE) { - parser_error = ParsePerMethodParams(json_tree); - } - if (error != nullptr) { - *error = parser_error; - } else { - GRPC_ERROR_UNREF(parser_error); - } + *error = ParseGlobalParams(json_tree); + *error = grpc_error_add_child(*error, ParsePerMethodParams(json_tree)); } grpc_error* ServiceConfig::ParseGlobalParams(const grpc_json* json_tree) { GPR_DEBUG_ASSERT(json_tree_->type == GRPC_JSON_OBJECT); GPR_DEBUG_ASSERT(json_tree_->key == nullptr); + grpc_error* error = GRPC_ERROR_NONE; for (size_t i = 0; i < registered_parsers_->size(); i++) { - grpc_error* error; + grpc_error* parser_error = GRPC_ERROR_NONE; auto parsed_obj = - (*registered_parsers_)[i].ParseGlobalParams(json_tree, &error); - if (error != GRPC_ERROR_NONE) { - return error; - } + (*registered_parsers_)[i].ParseGlobalParams(json_tree, &parser_error); + error = grpc_error_add_child(error, parser_error); parsed_global_service_config_objects_.push_back(std::move(parsed_obj)); } - return GRPC_ERROR_NONE; + return error; } grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( @@ -108,13 +99,12 @@ grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( SliceHashTable::Entry* entries, size_t* idx) { auto objs_vector = MakeUnique(); + grpc_error* error = GRPC_ERROR_NONE; for (size_t i = 0; i < registered_parsers_->size(); i++) { - grpc_error* error; + grpc_error* parser_error = GRPC_ERROR_NONE; auto parsed_obj = (*registered_parsers_)[i].ParsePerMethodParams(json, &error); - if (error != GRPC_ERROR_NONE) { - return error; - } + error = grpc_error_add_child(error, parser_error); objs_vector->push_back(std::move(parsed_obj)); } const auto* vector_ptr = objs_vector.get(); @@ -125,8 +115,8 @@ grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( if (child->key == nullptr) continue; if (strcmp(child->key, "name") == 0) { if (child->type != GRPC_JSON_ARRAY) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "name should be of type Array"); + return grpc_error_add_child(error, GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "name should be of type Array")); } for (grpc_json* name = child->child; name != nullptr; name = name->next) { UniquePtr path = ParseJsonMethodName(name); @@ -138,8 +128,9 @@ grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( } } if (paths.size() == 0) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "No names specified in methodConfig"); + return grpc_error_add_child(error, + GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "No names specified in methodConfig")); } // Add entry for each path. for (size_t i = 0; i < paths.size(); ++i) { @@ -147,7 +138,7 @@ grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( entries[*idx].value = vector_ptr; // Takes a new ref. ++*idx; } - return GRPC_ERROR_NONE; + return error; } grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) { @@ -155,25 +146,30 @@ grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) { GPR_DEBUG_ASSERT(json_tree_->key == nullptr); SliceHashTable::Entry* entries = nullptr; size_t num_entries = 0; + grpc_error* error = GRPC_ERROR_NONE; for (grpc_json* field = json_tree->child; field != nullptr; field = field->next) { if (field->key == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Illegal key value - NULL"); + error = grpc_error_add_child(error, GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Illegal key value - NULL")); + continue; } if (strcmp(field->key, "methodConfig") == 0) { if (entries != nullptr) { GPR_ASSERT(false); } if (field->type != GRPC_JSON_ARRAY) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "methodConfig is not of type Array"); + return grpc_error_add_child(error, + GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "methodConfig is not of type Array")); } for (grpc_json* method = field->child; method != nullptr; method = method->next) { int count = CountNamesInMethodConfig(method); if (count <= 0) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "No names found in methodConfig"); + error = grpc_error_add_child(error, + GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "No names found in methodConfig")); } num_entries += static_cast(count); } @@ -184,17 +180,10 @@ grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) { size_t idx = 0; for (grpc_json* method = field->child; method != nullptr; method = method->next) { - grpc_error* error = ParseJsonMethodConfigToServiceConfigObjectsTable( - method, entries, &idx); - if (error != GRPC_ERROR_NONE) { - for (size_t i = 0; i < idx; ++i) { - grpc_slice_unref_internal(entries[i].key); - } - gpr_free(entries); - return error; - } + error = grpc_error_add_child( + error, ParseJsonMethodConfigToServiceConfigObjectsTable( + method, entries, &idx)); } - GPR_DEBUG_ASSERT(idx == num_entries); break; } } @@ -204,7 +193,7 @@ grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) { num_entries, entries, nullptr); gpr_free(entries); } - return GRPC_ERROR_NONE; + return error; } ServiceConfig::~ServiceConfig() { grpc_json_destroy(json_tree_); } diff --git a/src/core/ext/filters/client_channel/service_config.h b/src/core/ext/filters/client_channel/service_config.h index 90f1a2d790c..e371af2746e 100644 --- a/src/core/ext/filters/client_channel/service_config.h +++ b/src/core/ext/filters/client_channel/service_config.h @@ -60,6 +60,8 @@ namespace grpc_core { class ServiceConfigParsedObject { public: virtual ~ServiceConfigParsedObject() = default; + + GRPC_ABSTRACT_BASE_CLASS; }; /// This is the base class that all service config parsers should derive from. @@ -69,25 +71,28 @@ class ServiceConfigParser { virtual UniquePtr ParseGlobalParams( const grpc_json* json, grpc_error** error) { - if (error != nullptr) { - *error = GRPC_ERROR_NONE; - } + GPR_DEBUG_ASSERT(error != nullptr); + *error = GRPC_ERROR_NONE; return nullptr; } virtual UniquePtr ParsePerMethodParams( const grpc_json* json, grpc_error** error) { - if (error != nullptr) { - *error = GRPC_ERROR_NONE; - } + GPR_DEBUG_ASSERT(error != nullptr); + *error = GRPC_ERROR_NONE; return nullptr; } - static constexpr int kMaxParsers = 32; + GRPC_ABSTRACT_BASE_CLASS; }; class ServiceConfig : public RefCounted { public: + static constexpr int kNumPreallocatedParsers = 4; + typedef InlinedVector, + kNumPreallocatedParsers> + ServiceConfigObjectsVector; + /// Creates a new service config from parsing \a json_string. /// Returns null on parse error. static RefCountedPtr Create(const char* json, @@ -136,10 +141,6 @@ class ServiceConfig : public RefCounted { return parsed_global_service_config_objects_[index].get(); } - static constexpr int kMaxParsers = 32; - typedef InlinedVector, kMaxParsers> - ServiceConfigObjectsVector; - /// Retrieves the vector of method service config objects for a given path \a /// path. const ServiceConfigObjectsVector* const* GetMethodServiceConfigObjectsVector( @@ -151,14 +152,11 @@ class ServiceConfig : public RefCounted { /// registered parser. Each parser is responsible for reading the service /// config json and returning a parsed object. This parsed object can later be /// retrieved using the same index that was returned at registration time. - static int RegisterParser(const ServiceConfigParser& parser) { - registered_parsers_->push_back(parser); + static int RegisterParser(ServiceConfigParser parser) { + registered_parsers_->push_back(std::move(parser)); return registered_parsers_->size() - 1; } - typedef InlinedVector - ServiceConfigParserList; - static void Init() { GPR_ASSERT(registered_parsers_ == nullptr); registered_parsers_ = New(); @@ -170,6 +168,8 @@ class ServiceConfig : public RefCounted { } private: + typedef InlinedVector + ServiceConfigParserList; // So New() can call our private ctor. template friend T* New(Args&&... args); @@ -209,11 +209,11 @@ class ServiceConfig : public RefCounted { UniquePtr json_string_; // Underlying storage for json_tree. grpc_json* json_tree_; - InlinedVector, kMaxParsers> + InlinedVector, kNumPreallocatedParsers> parsed_global_service_config_objects_; RefCountedPtr> parsed_method_service_config_objects_table_; - InlinedVector, kMaxParsers> + InlinedVector, 32> service_config_objects_vectors_storage_; }; From 4ae20ad9726b6a38b3db3e485c2cd99520077785 Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Tue, 26 Mar 2019 10:45:02 -0700 Subject: [PATCH 193/242] Fix count in xds/grpclb test --- test/cpp/end2end/grpclb_end2end_test.cc | 152 ++++++++++++------------ test/cpp/end2end/xds_end2end_test.cc | 4 + 2 files changed, 77 insertions(+), 79 deletions(-) diff --git a/test/cpp/end2end/grpclb_end2end_test.cc b/test/cpp/end2end/grpclb_end2end_test.cc index 3afcd0c578f..a08d6aa2ee1 100644 --- a/test/cpp/end2end/grpclb_end2end_test.cc +++ b/test/cpp/end2end/grpclb_end2end_test.cc @@ -207,67 +207,74 @@ class BalancerServiceImpl : public BalancerService { client_load_reporting_interval_seconds) {} Status BalanceLoad(ServerContext* context, Stream* stream) override { - // Balancer shouldn't receive the call credentials metadata. - EXPECT_EQ(context->client_metadata().find(g_kCallCredsMdKey), - context->client_metadata().end()); gpr_log(GPR_INFO, "LB[%p]: BalanceLoad", this); - LoadBalanceRequest request; - std::vector responses_and_delays; - - if (!stream->Read(&request)) { - goto done; - } - IncreaseRequestCount(); - gpr_log(GPR_INFO, "LB[%p]: received initial message '%s'", this, - request.DebugString().c_str()); - - // TODO(juanlishen): Initial response should always be the first response. - if (client_load_reporting_interval_seconds_ > 0) { - LoadBalanceResponse initial_response; - initial_response.mutable_initial_response() - ->mutable_client_stats_report_interval() - ->set_seconds(client_load_reporting_interval_seconds_); - stream->Write(initial_response); - } - { std::unique_lock lock(mu_); - responses_and_delays = responses_and_delays_; - } - for (const auto& response_and_delay : responses_and_delays) { - SendResponse(stream, response_and_delay.first, response_and_delay.second); + if (serverlist_done_) goto done; } { - std::unique_lock lock(mu_); - serverlist_cond_.wait(lock, [this] { return serverlist_done_; }); - } + // Balancer shouldn't receive the call credentials metadata. + EXPECT_EQ(context->client_metadata().find(g_kCallCredsMdKey), + context->client_metadata().end()); + LoadBalanceRequest request; + std::vector responses_and_delays; - if (client_load_reporting_interval_seconds_ > 0) { - request.Clear(); - if (stream->Read(&request)) { - gpr_log(GPR_INFO, "LB[%p]: received client load report message '%s'", - this, request.DebugString().c_str()); - GPR_ASSERT(request.has_client_stats()); - // We need to acquire the lock here in order to prevent the notify_one - // below from firing before its corresponding wait is executed. - std::lock_guard lock(mu_); - client_stats_.num_calls_started += - request.client_stats().num_calls_started(); - client_stats_.num_calls_finished += - request.client_stats().num_calls_finished(); - client_stats_.num_calls_finished_with_client_failed_to_send += - request.client_stats() - .num_calls_finished_with_client_failed_to_send(); - client_stats_.num_calls_finished_known_received += - request.client_stats().num_calls_finished_known_received(); - for (const auto& drop_token_count : - request.client_stats().calls_finished_with_drop()) { - client_stats_ - .drop_token_counts[drop_token_count.load_balance_token()] += - drop_token_count.num_calls(); + if (!stream->Read(&request)) { + goto done; + } + IncreaseRequestCount(); + gpr_log(GPR_INFO, "LB[%p]: received initial message '%s'", this, + request.DebugString().c_str()); + + // TODO(juanlishen): Initial response should always be the first response. + if (client_load_reporting_interval_seconds_ > 0) { + LoadBalanceResponse initial_response; + initial_response.mutable_initial_response() + ->mutable_client_stats_report_interval() + ->set_seconds(client_load_reporting_interval_seconds_); + stream->Write(initial_response); + } + + { + std::unique_lock lock(mu_); + responses_and_delays = responses_and_delays_; + } + for (const auto& response_and_delay : responses_and_delays) { + SendResponse(stream, response_and_delay.first, + response_and_delay.second); + } + { + std::unique_lock lock(mu_); + serverlist_cond_.wait(lock, [this] { return serverlist_done_; }); + } + + if (client_load_reporting_interval_seconds_ > 0) { + request.Clear(); + if (stream->Read(&request)) { + gpr_log(GPR_INFO, "LB[%p]: received client load report message '%s'", + this, request.DebugString().c_str()); + GPR_ASSERT(request.has_client_stats()); + // We need to acquire the lock here in order to prevent the notify_one + // below from firing before its corresponding wait is executed. + std::lock_guard lock(mu_); + client_stats_.num_calls_started += + request.client_stats().num_calls_started(); + client_stats_.num_calls_finished += + request.client_stats().num_calls_finished(); + client_stats_.num_calls_finished_with_client_failed_to_send += + request.client_stats() + .num_calls_finished_with_client_failed_to_send(); + client_stats_.num_calls_finished_known_received += + request.client_stats().num_calls_finished_known_received(); + for (const auto& drop_token_count : + request.client_stats().calls_finished_with_drop()) { + client_stats_ + .drop_token_counts[drop_token_count.load_balance_token()] += + drop_token_count.num_calls(); + } + load_report_ready_ = true; + load_report_cond_.notify_one(); } - load_report_ready_ = true; - load_report_cond_.notify_one(); } } done: @@ -1365,7 +1372,7 @@ class UpdatesTest : public GrpclbEnd2endTest { UpdatesTest() : GrpclbEnd2endTest(4, 3, 0) {} }; -TEST_F(UpdatesTest, UpdateBalancers) { +TEST_F(UpdatesTest, UpdateBalancersButKeepUsingOriginalBalancer) { SetNextResolutionAllBalancers(); const std::vector first_backend{GetBackendPorts()[0]}; const std::vector second_backend{GetBackendPorts()[1]}; @@ -1385,9 +1392,6 @@ TEST_F(UpdatesTest, UpdateBalancers) { // All 10 requests should have gone to the first backend. EXPECT_EQ(10U, backends_[0]->service_.request_count()); - balancers_[0]->service_.NotifyDoneWithServerlists(); - balancers_[1]->service_.NotifyDoneWithServerlists(); - balancers_[2]->service_.NotifyDoneWithServerlists(); // Balancer 0 got a single request. EXPECT_EQ(1U, balancers_[0]->service_.request_count()); // and sent a single response. @@ -1403,25 +1407,21 @@ TEST_F(UpdatesTest, UpdateBalancers) { SetNextResolution(addresses); gpr_log(GPR_INFO, "========= UPDATE 1 DONE =========="); - // Wait until update has been processed, as signaled by the second backend - // receiving a request. EXPECT_EQ(0U, backends_[1]->service_.request_count()); - WaitForBackend(1); + gpr_timespec deadline = gpr_time_add( + gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(10000, GPR_TIMESPAN)); + // Send 10 seconds worth of RPCs + do { + CheckRpcSendOk(); + } while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0); + // The current LB call is still working, so grpclb continued using it to the + // first balancer, which doesn't assign the second backend. + EXPECT_EQ(0U, backends_[1]->service_.request_count()); - backends_[1]->service_.ResetCounters(); - gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH =========="); - CheckRpcSendOk(10); - gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH =========="); - // All 10 requests should have gone to the second backend. - EXPECT_EQ(10U, backends_[1]->service_.request_count()); - - balancers_[0]->service_.NotifyDoneWithServerlists(); - balancers_[1]->service_.NotifyDoneWithServerlists(); - balancers_[2]->service_.NotifyDoneWithServerlists(); EXPECT_EQ(1U, balancers_[0]->service_.request_count()); EXPECT_EQ(1U, balancers_[0]->service_.response_count()); - EXPECT_EQ(1U, balancers_[1]->service_.request_count()); - EXPECT_EQ(1U, balancers_[1]->service_.response_count()); + EXPECT_EQ(0U, balancers_[1]->service_.request_count()); + EXPECT_EQ(0U, balancers_[1]->service_.response_count()); EXPECT_EQ(0U, balancers_[2]->service_.request_count()); EXPECT_EQ(0U, balancers_[2]->service_.response_count()); } @@ -1532,9 +1532,6 @@ TEST_F(UpdatesTest, UpdateBalancersDeadUpdate) { EXPECT_EQ(20U, backends_[0]->service_.request_count()); EXPECT_EQ(0U, backends_[1]->service_.request_count()); - balancers_[0]->service_.NotifyDoneWithServerlists(); - balancers_[1]->service_.NotifyDoneWithServerlists(); - balancers_[2]->service_.NotifyDoneWithServerlists(); // Balancer 0 got a single request. EXPECT_EQ(1U, balancers_[0]->service_.request_count()); // and sent a single response. @@ -1564,9 +1561,6 @@ TEST_F(UpdatesTest, UpdateBalancersDeadUpdate) { // All 10 requests should have gone to the second backend. EXPECT_EQ(10U, backends_[1]->service_.request_count()); - balancers_[0]->service_.NotifyDoneWithServerlists(); - balancers_[1]->service_.NotifyDoneWithServerlists(); - balancers_[2]->service_.NotifyDoneWithServerlists(); EXPECT_EQ(1U, balancers_[0]->service_.request_count()); EXPECT_EQ(1U, balancers_[0]->service_.response_count()); // The second balancer, published as part of the first update, may end up diff --git a/test/cpp/end2end/xds_end2end_test.cc b/test/cpp/end2end/xds_end2end_test.cc index 8657ba78d90..6d3ede141f4 100644 --- a/test/cpp/end2end/xds_end2end_test.cc +++ b/test/cpp/end2end/xds_end2end_test.cc @@ -207,6 +207,10 @@ class BalancerServiceImpl : public BalancerService { Status BalanceLoad(ServerContext* context, Stream* stream) override { // TODO(juanlishen): Clean up the scoping. gpr_log(GPR_INFO, "LB[%p]: BalanceLoad", this); + { + std::unique_lock lock(mu_); + if (serverlist_done_) goto done; + } { // Balancer shouldn't receive the call credentials metadata. EXPECT_EQ(context->client_metadata().find(g_kCallCredsMdKey), From d74e4079c535bc6b9348394cb820bfb03b8531f7 Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Thu, 4 Apr 2019 15:38:51 -0700 Subject: [PATCH 194/242] upgrade bazel to 0.23.2 for docker legacy bazel builds excluded Python tests from Bazel legacy C/C++ Kokoro CI jobs disabled building examples due to existance of python --- templates/tools/dockerfile/bazel.include | 6 +++--- tools/dockerfile/test/bazel/Dockerfile | 6 +++--- tools/dockerfile/test/sanity/Dockerfile | 6 +++--- tools/internal_ci/linux/grpc_bazel_build_in_docker.sh | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/templates/tools/dockerfile/bazel.include b/templates/tools/dockerfile/bazel.include index 62d68607453..8888e938f43 100644 --- a/templates/tools/dockerfile/bazel.include +++ b/templates/tools/dockerfile/bazel.include @@ -2,6 +2,6 @@ # Bazel installation RUN apt-get update && apt-get install -y wget && apt-get clean -RUN wget https://github.com/bazelbuild/bazel/releases/download/0.20.0/bazel-0.20.0-installer-linux-x86_64.sh && ${'\\'} - bash ./bazel-0.20.0-installer-linux-x86_64.sh && ${'\\'} - rm bazel-0.20.0-installer-linux-x86_64.sh +RUN wget https://github.com/bazelbuild/bazel/releases/download/0.23.2/bazel-0.23.2-installer-linux-x86_64.sh && ${'\\'} + bash ./bazel-0.23.2-installer-linux-x86_64.sh && ${'\\'} + rm bazel-0.23.2-installer-linux-x86_64.sh diff --git a/tools/dockerfile/test/bazel/Dockerfile b/tools/dockerfile/test/bazel/Dockerfile index 7dee0051176..2536fe299cb 100644 --- a/tools/dockerfile/test/bazel/Dockerfile +++ b/tools/dockerfile/test/bazel/Dockerfile @@ -52,9 +52,9 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 t # Bazel installation RUN apt-get update && apt-get install -y wget && apt-get clean -RUN wget https://github.com/bazelbuild/bazel/releases/download/0.20.0/bazel-0.20.0-installer-linux-x86_64.sh && \ - bash ./bazel-0.20.0-installer-linux-x86_64.sh && \ - rm bazel-0.20.0-installer-linux-x86_64.sh +RUN wget https://github.com/bazelbuild/bazel/releases/download/0.23.2/bazel-0.23.2-installer-linux-x86_64.sh && \ + bash ./bazel-0.23.2-installer-linux-x86_64.sh && \ + rm bazel-0.23.2-installer-linux-x86_64.sh RUN mkdir -p /var/local/jenkins diff --git a/tools/dockerfile/test/sanity/Dockerfile b/tools/dockerfile/test/sanity/Dockerfile index 7a6fbfee7f4..765bd7267a4 100644 --- a/tools/dockerfile/test/sanity/Dockerfile +++ b/tools/dockerfile/test/sanity/Dockerfile @@ -98,9 +98,9 @@ ENV CLANG_TIDY=clang-tidy # Bazel installation RUN apt-get update && apt-get install -y wget && apt-get clean -RUN wget https://github.com/bazelbuild/bazel/releases/download/0.20.0/bazel-0.20.0-installer-linux-x86_64.sh && \ - bash ./bazel-0.20.0-installer-linux-x86_64.sh && \ - rm bazel-0.20.0-installer-linux-x86_64.sh +RUN wget https://github.com/bazelbuild/bazel/releases/download/0.23.2/bazel-0.23.2-installer-linux-x86_64.sh && \ + bash ./bazel-0.23.2-installer-linux-x86_64.sh && \ + rm bazel-0.23.2-installer-linux-x86_64.sh # Define the default command. diff --git a/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh b/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh index 24598f43f02..343ca17793d 100755 --- a/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh +++ b/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh @@ -24,4 +24,4 @@ git clone /var/local/jenkins/grpc /var/local/git/grpc && git submodule update --init --reference /var/local/jenkins/grpc/${name} \ ${name}') cd /var/local/git/grpc -bazel build --spawn_strategy=standalone --genrule_strategy=standalone :all test/... examples/... +bazel build --spawn_strategy=standalone --genrule_strategy=standalone :all test/... From 977e4b1450d9910ccc51f2f8de51e2e00349c969 Mon Sep 17 00:00:00 2001 From: Eric Anderson Date: Thu, 4 Apr 2019 18:23:00 -0700 Subject: [PATCH 195/242] grpc_interop_java: Remove unnecessary cruft from container This reduces the container size from 1.4 GB to 640 MB. 129 MB is jessie, 489 MB jdk, and 22 MB grpc-java. When we swap from jessie to stretch, we could swap to openjdk:8-jdk-slim-stretch which would make the entire image 265 MB. Python was never needed; it was added by mistake in 0589e533. Pre-downloading gradle artifacts isn't helpful these days, because we build on a clean machine. Git isn't needed as cp is sufficient. libapr1 has not been required by tcnative for a long time, and we even use tcnative-boringssl-static since at least 1.0, which also doesn't need it. The final cleanup is to remove source and downloaded artifacts when done compiling. --- .../Dockerfile.include | 9 +---- .../java_deps.include | 13 +++---- .../dockerfile/java_build_interop.sh.include | 16 ++++++--- .../interoptest/grpc_interop_java/Dockerfile | 35 +++---------------- .../grpc_interop_java/build_interop.sh | 16 ++++++--- .../grpc_interop_java_oracle8/Dockerfile | 35 +++---------------- .../build_interop.sh | 16 ++++++--- 7 files changed, 51 insertions(+), 89 deletions(-) diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile.include b/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile.include index e80b51778c6..7307e29f0a0 100644 --- a/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile.include +++ b/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile.include @@ -15,13 +15,6 @@ <%include file="../../debian_jessie_header.include"/> <%include file="java_deps.include"/> -<%include file="../../python_deps.include"/> - -# Trigger download of as many Gradle artifacts as possible. -RUN git clone --recursive --depth 1 https://github.com/grpc/grpc-java.git && ${'\\'} - cd grpc-java && ${'\\'} - ./gradlew :grpc-interop-testing:installDist -PskipCodegen=true && ${'\\'} - rm -r "$(pwd)" # Define the default command. -CMD ["bash"] \ No newline at end of file +CMD ["bash"] diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/java_deps.include b/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/java_deps.include index 40d70e06d1a..c05b5642393 100644 --- a/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/java_deps.include +++ b/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/java_deps.include @@ -1,16 +1,11 @@ -# Install JDK 8 and Git +# Install JDK 8 # RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | /usr/bin/debconf-set-selections && ${'\\'} echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee /etc/apt/sources.list.d/webupd8team-java.list && ${'\\'} echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee -a /etc/apt/sources.list.d/webupd8team-java.list && ${'\\'} - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886 - -RUN apt-get update && apt-get -y install ${'\\'} - git ${'\\'} - libapr1 ${'\\'} - oracle-java8-installer ${'\\'} - && ${'\\'} - apt-get clean && rm -r /var/cache/oracle-jdk8-installer/ + apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886 && ${'\\'} + apt-get update && apt-get -y install oracle-java8-installer && ${'\\'} + apt-get clean && rm -r /var/cache/oracle-jdk8-installer/ ENV JAVA_HOME /usr/lib/jvm/java-8-oracle ENV PATH $PATH:$JAVA_HOME/bin diff --git a/templates/tools/dockerfile/java_build_interop.sh.include b/templates/tools/dockerfile/java_build_interop.sh.include index 16d5fb65cf1..e30b53e3f2a 100755 --- a/templates/tools/dockerfile/java_build_interop.sh.include +++ b/templates/tools/dockerfile/java_build_interop.sh.include @@ -16,16 +16,24 @@ # Builds Java interop server and client in a base image. set -e -mkdir -p /var/local/git -git clone --recursive --depth 1 /var/local/jenkins/grpc-java /var/local/git/grpc-java +cp -r /var/local/jenkins/grpc-java /tmp/grpc-java # copy service account keys if available cp -r /var/local/jenkins/service_account $HOME || true -cd /var/local/git/grpc-java - +pushd /tmp/grpc-java ./gradlew :grpc-interop-testing:installDist -PskipCodegen=true +mkdir -p /var/local/git/grpc-java/ +cp -r --parents -t /var/local/git/grpc-java/ ${'\\'} + interop-testing/build/install/ ${'\\'} + run-test-client.sh ${'\\'} + run-test-server.sh + +popd +rm -r /tmp/grpc-java +rm -r "$HOME/.gradle" + # enable extra java logging mkdir -p /var/local/grpc_java_logging echo "handlers = java.util.logging.ConsoleHandler diff --git a/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile index d16830688ca..217175159df 100644 --- a/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile +++ b/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile @@ -16,45 +16,20 @@ FROM debian:jessie RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list -# Install JDK 8 and Git +# Install JDK 8 # RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | /usr/bin/debconf-set-selections && \ echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee /etc/apt/sources.list.d/webupd8team-java.list && \ echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee -a /etc/apt/sources.list.d/webupd8team-java.list && \ - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886 - -RUN apt-get update && apt-get -y install \ - git \ - libapr1 \ - oracle-java8-installer \ - && \ - apt-get clean && rm -r /var/cache/oracle-jdk8-installer/ + apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886 && \ + apt-get update && apt-get -y install oracle-java8-installer && \ + apt-get clean && rm -r /var/cache/oracle-jdk8-installer/ ENV JAVA_HOME /usr/lib/jvm/java-8-oracle ENV PATH $PATH:$JAVA_HOME/bin -#==================== -# Python dependencies - -# Install dependencies - -RUN apt-get update && apt-get install -y \ - python-all-dev \ - python3-all-dev \ - python-pip - -# Install Python packages from PyPI -RUN pip install --upgrade pip==10.0.1 -RUN pip install virtualenv -RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0 - - -# Trigger download of as many Gradle artifacts as possible. -RUN git clone --recursive --depth 1 https://github.com/grpc/grpc-java.git && \ - cd grpc-java && \ - ./gradlew :grpc-interop-testing:installDist -PskipCodegen=true && \ - rm -r "$(pwd)" # Define the default command. CMD ["bash"] + diff --git a/tools/dockerfile/interoptest/grpc_interop_java/build_interop.sh b/tools/dockerfile/interoptest/grpc_interop_java/build_interop.sh index 0e36c193c91..8e1154679d7 100644 --- a/tools/dockerfile/interoptest/grpc_interop_java/build_interop.sh +++ b/tools/dockerfile/interoptest/grpc_interop_java/build_interop.sh @@ -16,16 +16,24 @@ # Builds Java interop server and client in a base image. set -e -mkdir -p /var/local/git -git clone --recursive --depth 1 /var/local/jenkins/grpc-java /var/local/git/grpc-java +cp -r /var/local/jenkins/grpc-java /tmp/grpc-java # copy service account keys if available cp -r /var/local/jenkins/service_account $HOME || true -cd /var/local/git/grpc-java - +pushd /tmp/grpc-java ./gradlew :grpc-interop-testing:installDist -PskipCodegen=true +mkdir -p /var/local/git/grpc-java/ +cp -r --parents -t /var/local/git/grpc-java/ \ + interop-testing/build/install/ \ + run-test-client.sh \ + run-test-server.sh + +popd +rm -r /tmp/grpc-java +rm -r "$HOME/.gradle" + # enable extra java logging mkdir -p /var/local/grpc_java_logging echo "handlers = java.util.logging.ConsoleHandler diff --git a/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile index d16830688ca..217175159df 100644 --- a/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile +++ b/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile @@ -16,45 +16,20 @@ FROM debian:jessie RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list -# Install JDK 8 and Git +# Install JDK 8 # RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | /usr/bin/debconf-set-selections && \ echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee /etc/apt/sources.list.d/webupd8team-java.list && \ echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee -a /etc/apt/sources.list.d/webupd8team-java.list && \ - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886 - -RUN apt-get update && apt-get -y install \ - git \ - libapr1 \ - oracle-java8-installer \ - && \ - apt-get clean && rm -r /var/cache/oracle-jdk8-installer/ + apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886 && \ + apt-get update && apt-get -y install oracle-java8-installer && \ + apt-get clean && rm -r /var/cache/oracle-jdk8-installer/ ENV JAVA_HOME /usr/lib/jvm/java-8-oracle ENV PATH $PATH:$JAVA_HOME/bin -#==================== -# Python dependencies - -# Install dependencies - -RUN apt-get update && apt-get install -y \ - python-all-dev \ - python3-all-dev \ - python-pip - -# Install Python packages from PyPI -RUN pip install --upgrade pip==10.0.1 -RUN pip install virtualenv -RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0 - - -# Trigger download of as many Gradle artifacts as possible. -RUN git clone --recursive --depth 1 https://github.com/grpc/grpc-java.git && \ - cd grpc-java && \ - ./gradlew :grpc-interop-testing:installDist -PskipCodegen=true && \ - rm -r "$(pwd)" # Define the default command. CMD ["bash"] + diff --git a/tools/dockerfile/interoptest/grpc_interop_java_oracle8/build_interop.sh b/tools/dockerfile/interoptest/grpc_interop_java_oracle8/build_interop.sh index 4c5ba4b7a3a..77d322882f7 100644 --- a/tools/dockerfile/interoptest/grpc_interop_java_oracle8/build_interop.sh +++ b/tools/dockerfile/interoptest/grpc_interop_java_oracle8/build_interop.sh @@ -16,16 +16,24 @@ # Builds Java interop server and client in a base image. set -e -mkdir -p /var/local/git -git clone --recursive --depth 1 /var/local/jenkins/grpc-java /var/local/git/grpc-java +cp -r /var/local/jenkins/grpc-java /tmp/grpc-java # copy service account keys if available cp -r /var/local/jenkins/service_account $HOME || true -cd /var/local/git/grpc-java - +pushd /tmp/grpc-java ./gradlew :grpc-interop-testing:installDist -PskipCodegen=true +mkdir -p /var/local/git/grpc-java/ +cp -r --parents -t /var/local/git/grpc-java/ \ + interop-testing/build/install/ \ + run-test-client.sh \ + run-test-server.sh + +popd +rm -r /tmp/grpc-java +rm -r "$HOME/.gradle" + # enable extra java logging mkdir -p /var/local/grpc_java_logging echo "handlers = java.util.logging.ConsoleHandler From 390078b7a8a82b15de1c52a22e3e2d98b5843f24 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 4 Apr 2019 18:55:10 -0700 Subject: [PATCH 196/242] Add tests for new service config mechanism --- CMakeLists.txt | 40 ++++ Makefile | 48 ++++ build.yaml | 13 ++ .../filters/client_channel/service_config.cc | 4 +- .../filters/client_channel/service_config.h | 6 +- test/core/client_channel/BUILD | 14 ++ .../client_channel/service_config_test.cc | 221 ++++++++++++++++++ .../generated/sources_and_headers.json | 18 ++ tools/run_tests/generated/tests.json | 24 ++ 9 files changed, 382 insertions(+), 6 deletions(-) create mode 100644 test/core/client_channel/service_config_test.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index e7857d5d84e..7554de69936 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -698,6 +698,7 @@ add_dependencies(buildtests_cxx server_crash_test_client) add_dependencies(buildtests_cxx server_early_return_test) add_dependencies(buildtests_cxx server_interceptors_end2end_test) add_dependencies(buildtests_cxx server_request_call_test) +add_dependencies(buildtests_cxx service_config_test) add_dependencies(buildtests_cxx shutdown_test) add_dependencies(buildtests_cxx slice_hash_table_test) add_dependencies(buildtests_cxx slice_weak_hash_table_test) @@ -15679,6 +15680,45 @@ target_link_libraries(server_request_call_test ) +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + +add_executable(service_config_test + test/core/client_channel/service_config_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + + +target_include_directories(service_config_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR} + PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR} + PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR} + PRIVATE ${_gRPC_CARES_INCLUDE_DIR} + PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} + PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(service_config_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc++ + grpc + gpr + ${_gRPC_GFLAGS_LIBRARIES} +) + + endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) diff --git a/Makefile b/Makefile index c0b277f0fb1..a1c8118b8ab 100644 --- a/Makefile +++ b/Makefile @@ -1261,6 +1261,7 @@ server_crash_test_client: $(BINDIR)/$(CONFIG)/server_crash_test_client server_early_return_test: $(BINDIR)/$(CONFIG)/server_early_return_test server_interceptors_end2end_test: $(BINDIR)/$(CONFIG)/server_interceptors_end2end_test server_request_call_test: $(BINDIR)/$(CONFIG)/server_request_call_test +service_config_test: $(BINDIR)/$(CONFIG)/service_config_test shutdown_test: $(BINDIR)/$(CONFIG)/shutdown_test slice_hash_table_test: $(BINDIR)/$(CONFIG)/slice_hash_table_test slice_weak_hash_table_test: $(BINDIR)/$(CONFIG)/slice_weak_hash_table_test @@ -1725,6 +1726,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/server_early_return_test \ $(BINDIR)/$(CONFIG)/server_interceptors_end2end_test \ $(BINDIR)/$(CONFIG)/server_request_call_test \ + $(BINDIR)/$(CONFIG)/service_config_test \ $(BINDIR)/$(CONFIG)/shutdown_test \ $(BINDIR)/$(CONFIG)/slice_hash_table_test \ $(BINDIR)/$(CONFIG)/slice_weak_hash_table_test \ @@ -1866,6 +1868,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/server_early_return_test \ $(BINDIR)/$(CONFIG)/server_interceptors_end2end_test \ $(BINDIR)/$(CONFIG)/server_request_call_test \ + $(BINDIR)/$(CONFIG)/service_config_test \ $(BINDIR)/$(CONFIG)/shutdown_test \ $(BINDIR)/$(CONFIG)/slice_hash_table_test \ $(BINDIR)/$(CONFIG)/slice_weak_hash_table_test \ @@ -2377,6 +2380,8 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/server_interceptors_end2end_test || ( echo test server_interceptors_end2end_test failed ; exit 1 ) $(E) "[RUN] Testing server_request_call_test" $(Q) $(BINDIR)/$(CONFIG)/server_request_call_test || ( echo test server_request_call_test failed ; exit 1 ) + $(E) "[RUN] Testing service_config_test" + $(Q) $(BINDIR)/$(CONFIG)/service_config_test || ( echo test service_config_test failed ; exit 1 ) $(E) "[RUN] Testing shutdown_test" $(Q) $(BINDIR)/$(CONFIG)/shutdown_test || ( echo test shutdown_test failed ; exit 1 ) $(E) "[RUN] Testing slice_hash_table_test" @@ -18601,6 +18606,49 @@ endif $(OBJDIR)/$(CONFIG)/test/cpp/server/server_request_call_test.o: $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc +SERVICE_CONFIG_TEST_SRC = \ + test/core/client_channel/service_config_test.cc \ + +SERVICE_CONFIG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVICE_CONFIG_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/service_config_test: openssl_dep_error + +else + + + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/service_config_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/service_config_test: $(PROTOBUF_DEP) $(SERVICE_CONFIG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(SERVICE_CONFIG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/service_config_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/test/core/client_channel/service_config_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_service_config_test: $(SERVICE_CONFIG_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(SERVICE_CONFIG_TEST_OBJS:.o=.dep) +endif +endif + + SHUTDOWN_TEST_SRC = \ test/cpp/end2end/shutdown_test.cc \ diff --git a/build.yaml b/build.yaml index c1271be9131..4272cdbcdf4 100644 --- a/build.yaml +++ b/build.yaml @@ -5441,6 +5441,19 @@ targets: - grpc++_unsecure - grpc_unsecure - gpr +- name: service_config_test + gtest: true + build: test + language: c++ + src: + - test/core/client_channel/service_config_test.cc + deps: + - grpc_test_util + - grpc++ + - grpc + - gpr + uses: + - grpc++_test - name: shutdown_test gtest: true build: test diff --git a/src/core/ext/filters/client_channel/service_config.cc b/src/core/ext/filters/client_channel/service_config.cc index b03bbb127ef..30b5981da84 100644 --- a/src/core/ext/filters/client_channel/service_config.cc +++ b/src/core/ext/filters/client_channel/service_config.cc @@ -87,7 +87,7 @@ grpc_error* ServiceConfig::ParseGlobalParams(const grpc_json* json_tree) { for (size_t i = 0; i < registered_parsers_->size(); i++) { grpc_error* parser_error = GRPC_ERROR_NONE; auto parsed_obj = - (*registered_parsers_)[i].ParseGlobalParams(json_tree, &parser_error); + (*registered_parsers_)[i]->ParseGlobalParams(json_tree, &parser_error); error = grpc_error_add_child(error, parser_error); parsed_global_service_config_objects_.push_back(std::move(parsed_obj)); } @@ -103,7 +103,7 @@ grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( for (size_t i = 0; i < registered_parsers_->size(); i++) { grpc_error* parser_error = GRPC_ERROR_NONE; auto parsed_obj = - (*registered_parsers_)[i].ParsePerMethodParams(json, &error); + (*registered_parsers_)[i]->ParsePerMethodParams(json, &error); error = grpc_error_add_child(error, parser_error); objs_vector->push_back(std::move(parsed_obj)); } diff --git a/src/core/ext/filters/client_channel/service_config.h b/src/core/ext/filters/client_channel/service_config.h index e371af2746e..3eb3bd54644 100644 --- a/src/core/ext/filters/client_channel/service_config.h +++ b/src/core/ext/filters/client_channel/service_config.h @@ -72,14 +72,12 @@ class ServiceConfigParser { virtual UniquePtr ParseGlobalParams( const grpc_json* json, grpc_error** error) { GPR_DEBUG_ASSERT(error != nullptr); - *error = GRPC_ERROR_NONE; return nullptr; } virtual UniquePtr ParsePerMethodParams( const grpc_json* json, grpc_error** error) { GPR_DEBUG_ASSERT(error != nullptr); - *error = GRPC_ERROR_NONE; return nullptr; } @@ -152,7 +150,7 @@ class ServiceConfig : public RefCounted { /// registered parser. Each parser is responsible for reading the service /// config json and returning a parsed object. This parsed object can later be /// retrieved using the same index that was returned at registration time. - static int RegisterParser(ServiceConfigParser parser) { + static int RegisterParser(UniquePtr parser) { registered_parsers_->push_back(std::move(parser)); return registered_parsers_->size() - 1; } @@ -168,7 +166,7 @@ class ServiceConfig : public RefCounted { } private: - typedef InlinedVector + typedef InlinedVector, kNumPreallocatedParsers> ServiceConfigParserList; // So New() can call our private ctor. template diff --git a/test/core/client_channel/BUILD b/test/core/client_channel/BUILD index 57e5191af4c..f88a51adbf6 100644 --- a/test/core/client_channel/BUILD +++ b/test/core/client_channel/BUILD @@ -78,3 +78,17 @@ grpc_cc_test( "//test/core/util:grpc_test_util", ], ) + +grpc_cc_test( + name = "service_config_test", + srcs = ["service_config_test.cc"], + external_deps = [ + "gtest", + ], + language = "C++", + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:grpc_test_util", + ], +) diff --git a/test/core/client_channel/service_config_test.cc b/test/core/client_channel/service_config_test.cc new file mode 100644 index 00000000000..d8cb3532cb5 --- /dev/null +++ b/test/core/client_channel/service_config_test.cc @@ -0,0 +1,221 @@ +/* + * + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include "src/core/ext/filters/client_channel/service_config.h" +#include "src/core/lib/gpr/string.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +namespace grpc_core { +namespace testing { + +class TestParsedObject1 : public ServiceConfigParsedObject { + public: + TestParsedObject1(int value) : value_(value) {} + + int value() const { return value_; } + + private: + int value_; +}; + +class TestParser1 : public ServiceConfigParser { + public: + UniquePtr ParseGlobalParams( + const grpc_json* json, grpc_error** error) override { + GPR_DEBUG_ASSERT(error != nullptr); + for (grpc_json* field = json->child; field != nullptr; + field = field->next) { + if (strcmp(field->key, "global_param") == 0) { + if (field->type != GRPC_JSON_NUMBER) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "global_param value type should be a number"); + return nullptr; + } + int value = gpr_parse_nonnegative_int(field->value); + if (value == -1) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "global_param value type should be non-negative"); + return nullptr; + } + return UniquePtr( + New(value)); + } + } + return nullptr; + } +}; + +class TestParser2 : public ServiceConfigParser { + public: + UniquePtr ParsePerMethodParams( + const grpc_json* json, grpc_error** error) override { + GPR_DEBUG_ASSERT(error != nullptr); + for (grpc_json* field = json->child; field != nullptr; + field = field->next) { + if (field->key == nullptr || strcmp(field->key, "name") == 0) { + continue; + } + if (strcmp(field->key, "method_param") == 0) { + if (field->type != GRPC_JSON_NUMBER) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "method_param value type should be a number"); + return nullptr; + } + int value = gpr_parse_nonnegative_int(field->value); + if (value == -1) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "method_param value type should be non-negative"); + return nullptr; + } + return UniquePtr( + New(value)); + } + } + return nullptr; + } +}; + +class ServiceConfigTest : public ::testing::Test { + protected: + void SetUp() override { + ServiceConfig::Shutdown(); + ServiceConfig::Init(); + EXPECT_TRUE(ServiceConfig::RegisterParser( + UniquePtr(New())) == 0); + EXPECT_TRUE(ServiceConfig::RegisterParser( + UniquePtr(New())) == 1); + } +}; + +TEST_F(ServiceConfigTest, ErrorCheck1) { + const char* test_json = ""; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + EXPECT_TRUE(error != GRPC_ERROR_NONE); +} + +TEST_F(ServiceConfigTest, BasicTest1) { + const char* test_json = "{}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + EXPECT_TRUE(error == GRPC_ERROR_NONE); +} + +TEST_F(ServiceConfigTest, ErrorNoNames) { + const char* test_json = "{\"methodConfig\": [{\"blah\":1}]}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + EXPECT_TRUE(error != GRPC_ERROR_NONE); +} + +TEST_F(ServiceConfigTest, ErrorNoNamesWithMultipleMethodConfigs) { + const char* test_json = + "{\"methodConfig\": [{}, {\"name\":[{\"service\":\"TestServ\"}]}]}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + EXPECT_TRUE(error != GRPC_ERROR_NONE); +} + +TEST_F(ServiceConfigTest, ValidMethodConfig) { + const char* test_json = + "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}]}]}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + EXPECT_TRUE(error == GRPC_ERROR_NONE); +} + +TEST_F(ServiceConfigTest, Parser1BasicTest1) { + const char* test_json = "{\"global_param\":5}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + EXPECT_TRUE(error == GRPC_ERROR_NONE); + EXPECT_TRUE((static_cast( + svc_cfg->GetParsedGlobalServiceConfigObject(0))) + ->value() == 5); +} + +TEST_F(ServiceConfigTest, Parser1BasicTest2) { + const char* test_json = "{\"global_param\":1000}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + EXPECT_TRUE(error == GRPC_ERROR_NONE); + EXPECT_TRUE((static_cast( + svc_cfg->GetParsedGlobalServiceConfigObject(0))) + ->value() == 1000); +} + +TEST_F(ServiceConfigTest, Parser1ErrorInvalidType) { + const char* test_json = "{\"global_param\":\"5\"}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + EXPECT_TRUE(error != GRPC_ERROR_NONE); +} + +TEST_F(ServiceConfigTest, Parser1ErrorInvalidValue) { + const char* test_json = "{\"global_param\":-5}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + EXPECT_TRUE(error != GRPC_ERROR_NONE); +} + +TEST_F(ServiceConfigTest, Parser2BasicTest) { + const char* test_json = + "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], " + "\"method_param\":5}]}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + EXPECT_TRUE(error == GRPC_ERROR_NONE); +} + +TEST_F(ServiceConfigTest, Parser2ErrorInvalidType) { + const char* test_json = + "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], " + "\"method_param\":\"5\"}]}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + EXPECT_TRUE(error != GRPC_ERROR_NONE); +} + +TEST_F(ServiceConfigTest, Parser2ErrorInvalidValue) { + const char* test_json = + "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], " + "\"method_param\":-5}]}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + EXPECT_TRUE(error != GRPC_ERROR_NONE); +} + +} // namespace testing +} // namespace grpc_core + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + grpc_init(); + ::testing::InitGoogleTest(&argc, argv); + int ret = RUN_ALL_TESTS(); + grpc_shutdown(); + return ret; +} diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index cd88082f884..09b7ff2a70a 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -4723,6 +4723,24 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "grpc", + "grpc++", + "grpc++_test", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c++", + "name": "service_config_test", + "src": [ + "test/core/client_channel/service_config_test.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index cf0e574b09d..a25897735a7 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -5349,6 +5349,30 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "service_config_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, From e3290aa0fee675a61d8698e40475a649486dc5b6 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 2 Apr 2019 18:18:50 -0700 Subject: [PATCH 197/242] split up CallCredentials.cs into multiple files --- src/csharp/Grpc.Core/CallCredentials.cs | 69 ------------------ .../Internal/CompositeCallCredentials.cs | 72 +++++++++++++++++++ .../Grpc.Core/Internal/MetadataCredentials.cs | 51 +++++++++++++ 3 files changed, 123 insertions(+), 69 deletions(-) create mode 100644 src/csharp/Grpc.Core/Internal/CompositeCallCredentials.cs create mode 100644 src/csharp/Grpc.Core/Internal/MetadataCredentials.cs diff --git a/src/csharp/Grpc.Core/CallCredentials.cs b/src/csharp/Grpc.Core/CallCredentials.cs index c1bd95b9e22..bac75038070 100644 --- a/src/csharp/Grpc.Core/CallCredentials.cs +++ b/src/csharp/Grpc.Core/CallCredentials.cs @@ -57,73 +57,4 @@ namespace Grpc.Core /// The native credentials. internal abstract CallCredentialsSafeHandle ToNativeCredentials(); } - - /// - /// Client-side credentials that delegate metadata based auth to an interceptor. - /// The interceptor is automatically invoked for each remote call that uses MetadataCredentials. - /// - internal sealed class MetadataCredentials : CallCredentials - { - readonly AsyncAuthInterceptor interceptor; - - /// - /// Initializes a new instance of MetadataCredentials class. - /// - /// authentication interceptor - public MetadataCredentials(AsyncAuthInterceptor interceptor) - { - this.interceptor = GrpcPreconditions.CheckNotNull(interceptor); - } - - internal override CallCredentialsSafeHandle ToNativeCredentials() - { - NativeMetadataCredentialsPlugin plugin = new NativeMetadataCredentialsPlugin(interceptor); - return plugin.Credentials; - } - } - - /// - /// Credentials that allow composing multiple credentials objects into one object. - /// - internal sealed class CompositeCallCredentials : CallCredentials - { - readonly List credentials; - - /// - /// Initializes a new instance of CompositeCallCredentials class. - /// The resulting credentials object will be composite of all the credentials specified as parameters. - /// - /// credentials to compose - public CompositeCallCredentials(params CallCredentials[] credentials) - { - GrpcPreconditions.CheckArgument(credentials.Length >= 2, "Composite credentials object can only be created from 2 or more credentials."); - this.credentials = new List(credentials); - } - - internal override CallCredentialsSafeHandle ToNativeCredentials() - { - return ToNativeRecursive(0); - } - - // Recursive descent makes managing lifetime of intermediate CredentialSafeHandle instances easier. - // In practice, we won't usually see composites from more than two credentials anyway. - private CallCredentialsSafeHandle ToNativeRecursive(int startIndex) - { - if (startIndex == credentials.Count - 1) - { - return credentials[startIndex].ToNativeCredentials(); - } - - using (var cred1 = credentials[startIndex].ToNativeCredentials()) - using (var cred2 = ToNativeRecursive(startIndex + 1)) - { - var nativeComposite = CallCredentialsSafeHandle.CreateComposite(cred1, cred2); - if (nativeComposite.IsInvalid) - { - throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials."); - } - return nativeComposite; - } - } - } } diff --git a/src/csharp/Grpc.Core/Internal/CompositeCallCredentials.cs b/src/csharp/Grpc.Core/Internal/CompositeCallCredentials.cs new file mode 100644 index 00000000000..43ce8519e5b --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/CompositeCallCredentials.cs @@ -0,0 +1,72 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#endregion + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Credentials that allow composing multiple credentials objects into one object. + /// + internal sealed class CompositeCallCredentials : CallCredentials + { + readonly List credentials; + + /// + /// Initializes a new instance of CompositeCallCredentials class. + /// The resulting credentials object will be composite of all the credentials specified as parameters. + /// + /// credentials to compose + public CompositeCallCredentials(params CallCredentials[] credentials) + { + GrpcPreconditions.CheckArgument(credentials.Length >= 2, "Composite credentials object can only be created from 2 or more credentials."); + this.credentials = new List(credentials); + } + + internal override CallCredentialsSafeHandle ToNativeCredentials() + { + return ToNativeRecursive(0); + } + + // Recursive descent makes managing lifetime of intermediate CredentialSafeHandle instances easier. + // In practice, we won't usually see composites from more than two credentials anyway. + private CallCredentialsSafeHandle ToNativeRecursive(int startIndex) + { + if (startIndex == credentials.Count - 1) + { + return credentials[startIndex].ToNativeCredentials(); + } + + using (var cred1 = credentials[startIndex].ToNativeCredentials()) + using (var cred2 = ToNativeRecursive(startIndex + 1)) + { + var nativeComposite = CallCredentialsSafeHandle.CreateComposite(cred1, cred2); + if (nativeComposite.IsInvalid) + { + throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials."); + } + return nativeComposite; + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/MetadataCredentials.cs b/src/csharp/Grpc.Core/Internal/MetadataCredentials.cs new file mode 100644 index 00000000000..8dd00f072e5 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/MetadataCredentials.cs @@ -0,0 +1,51 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#endregion + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Client-side credentials that delegate metadata based auth to an interceptor. + /// The interceptor is automatically invoked for each remote call that uses MetadataCredentials. + /// + internal sealed class MetadataCredentials : CallCredentials + { + readonly AsyncAuthInterceptor interceptor; + + /// + /// Initializes a new instance of MetadataCredentials class. + /// + /// authentication interceptor + public MetadataCredentials(AsyncAuthInterceptor interceptor) + { + this.interceptor = GrpcPreconditions.CheckNotNull(interceptor); + } + + internal override CallCredentialsSafeHandle ToNativeCredentials() + { + NativeMetadataCredentialsPlugin plugin = new NativeMetadataCredentialsPlugin(interceptor); + return plugin.Credentials; + } + } +} From a1a878b593366780c3caf272d9c4eb6911906f7c Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 5 Apr 2019 04:47:06 +0200 Subject: [PATCH 198/242] make CallCredentials implementation agnostic --- src/csharp/Grpc.Core.Tests/FakeCredentials.cs | 4 +- src/csharp/Grpc.Core/CallCredentials.cs | 44 +++++++++++++--- .../CallCredentialsConfiguratorBase.cs | 38 ++++++++++++++ ... => DefaultCallCredentialsConfigurator.cs} | 49 +++++++++++------- .../Grpc.Core/Internal/MetadataCredentials.cs | 51 ------------------- 5 files changed, 108 insertions(+), 78 deletions(-) create mode 100644 src/csharp/Grpc.Core/CallCredentialsConfiguratorBase.cs rename src/csharp/Grpc.Core/Internal/{CompositeCallCredentials.cs => DefaultCallCredentialsConfigurator.cs} (51%) delete mode 100644 src/csharp/Grpc.Core/Internal/MetadataCredentials.cs diff --git a/src/csharp/Grpc.Core.Tests/FakeCredentials.cs b/src/csharp/Grpc.Core.Tests/FakeCredentials.cs index f23c9e97574..59587b9a510 100644 --- a/src/csharp/Grpc.Core.Tests/FakeCredentials.cs +++ b/src/csharp/Grpc.Core.Tests/FakeCredentials.cs @@ -42,9 +42,9 @@ namespace Grpc.Core.Tests internal class FakeCallCredentials : CallCredentials { - internal override CallCredentialsSafeHandle ToNativeCredentials() + public override void InternalPopulateConfiguration(CallCredentialsConfiguratorBase configurator, object state) { - return null; + // not invoking the configurator on purpose } } } diff --git a/src/csharp/Grpc.Core/CallCredentials.cs b/src/csharp/Grpc.Core/CallCredentials.cs index bac75038070..ebe5f260df4 100644 --- a/src/csharp/Grpc.Core/CallCredentials.cs +++ b/src/csharp/Grpc.Core/CallCredentials.cs @@ -16,9 +16,8 @@ #endregion -using System; using System.Collections.Generic; -using System.Threading.Tasks; +using System.Collections.ObjectModel; using Grpc.Core.Internal; using Grpc.Core.Utils; @@ -38,7 +37,7 @@ namespace Grpc.Core /// The new CompositeCallCredentials public static CallCredentials Compose(params CallCredentials[] credentials) { - return new CompositeCallCredentials(credentials); + return new CompositeCallCredentialsConfiguration(credentials); } /// @@ -48,13 +47,44 @@ namespace Grpc.Core /// authentication interceptor public static CallCredentials FromInterceptor(AsyncAuthInterceptor interceptor) { - return new MetadataCredentials(interceptor); + return new AsyncAuthInterceptorCredentialsConfiguration(interceptor); } /// - /// Creates native object for the credentials. + /// Populates this call credential instances. + /// You never need to invoke this, part of internal implementation. /// - /// The native credentials. - internal abstract CallCredentialsSafeHandle ToNativeCredentials(); + public abstract void InternalPopulateConfiguration(CallCredentialsConfiguratorBase configurator, object state); + + private class CompositeCallCredentialsConfiguration : CallCredentials + { + readonly IReadOnlyList credentials; + + public CompositeCallCredentialsConfiguration(CallCredentials[] credentials) + { + GrpcPreconditions.CheckArgument(credentials.Length >= 2, "Composite credentials object can only be created from 2 or more credentials."); + this.credentials = new List(credentials).AsReadOnly(); + } + + public override void InternalPopulateConfiguration(CallCredentialsConfiguratorBase configurator, object state) + { + configurator.SetCompositeCredentials(state, credentials); + } + } + + internal class AsyncAuthInterceptorCredentialsConfiguration : CallCredentials + { + readonly AsyncAuthInterceptor interceptor; + + public AsyncAuthInterceptorCredentialsConfiguration(AsyncAuthInterceptor interceptor) + { + this.interceptor = GrpcPreconditions.CheckNotNull(interceptor); + } + + public override void InternalPopulateConfiguration(CallCredentialsConfiguratorBase configurator, object state) + { + configurator.SetAsyncAuthInterceptorCredentials(state, interceptor); + } + } } } diff --git a/src/csharp/Grpc.Core/CallCredentialsConfiguratorBase.cs b/src/csharp/Grpc.Core/CallCredentialsConfiguratorBase.cs new file mode 100644 index 00000000000..40a33bbf599 --- /dev/null +++ b/src/csharp/Grpc.Core/CallCredentialsConfiguratorBase.cs @@ -0,0 +1,38 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#endregion + +using System.Collections.Generic; + +namespace Grpc.Core +{ + /// + /// Base class for objects that can consume configuration from CallCredentials objects. + /// + public abstract class CallCredentialsConfiguratorBase + { + /// + /// Consumes configuration for composite call credentials. + /// + public abstract void SetCompositeCredentials(object state, IReadOnlyList credentials); + + /// + /// Consumes configuration for call credentials created from AsyncAuthInterceptor + /// + public abstract void SetAsyncAuthInterceptorCredentials(object state, AsyncAuthInterceptor interceptor); + } +} diff --git a/src/csharp/Grpc.Core/Internal/CompositeCallCredentials.cs b/src/csharp/Grpc.Core/Internal/DefaultCallCredentialsConfigurator.cs similarity index 51% rename from src/csharp/Grpc.Core/Internal/CompositeCallCredentials.cs rename to src/csharp/Grpc.Core/Internal/DefaultCallCredentialsConfigurator.cs index 43ce8519e5b..a2c53a173c5 100644 --- a/src/csharp/Grpc.Core/Internal/CompositeCallCredentials.cs +++ b/src/csharp/Grpc.Core/Internal/DefaultCallCredentialsConfigurator.cs @@ -18,39 +18,38 @@ using System; using System.Collections.Generic; -using System.Threading.Tasks; - -using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core.Internal { /// - /// Credentials that allow composing multiple credentials objects into one object. + /// Creates native call credential objects from instances of CallCredentials. /// - internal sealed class CompositeCallCredentials : CallCredentials + internal class DefaultCallCredentialsConfigurator : CallCredentialsConfiguratorBase { - readonly List credentials; + CallCredentialsSafeHandle nativeCredentials; - /// - /// Initializes a new instance of CompositeCallCredentials class. - /// The resulting credentials object will be composite of all the credentials specified as parameters. - /// - /// credentials to compose - public CompositeCallCredentials(params CallCredentials[] credentials) + public CallCredentialsSafeHandle NativeCredentials => nativeCredentials; + + public override void SetAsyncAuthInterceptorCredentials(object state, AsyncAuthInterceptor interceptor) { - GrpcPreconditions.CheckArgument(credentials.Length >= 2, "Composite credentials object can only be created from 2 or more credentials."); - this.credentials = new List(credentials); + GrpcPreconditions.CheckState(nativeCredentials == null); + + var plugin = new NativeMetadataCredentialsPlugin(interceptor); + nativeCredentials = plugin.Credentials; } - internal override CallCredentialsSafeHandle ToNativeCredentials() + public override void SetCompositeCredentials(object state, IReadOnlyList credentials) { - return ToNativeRecursive(0); + GrpcPreconditions.CheckState(nativeCredentials == null); + + GrpcPreconditions.CheckArgument(credentials.Count >= 2); + nativeCredentials = CompositeToNativeRecursive(credentials, 0); } // Recursive descent makes managing lifetime of intermediate CredentialSafeHandle instances easier. // In practice, we won't usually see composites from more than two credentials anyway. - private CallCredentialsSafeHandle ToNativeRecursive(int startIndex) + private CallCredentialsSafeHandle CompositeToNativeRecursive(IReadOnlyList credentials, int startIndex) { if (startIndex == credentials.Count - 1) { @@ -58,7 +57,7 @@ namespace Grpc.Core.Internal } using (var cred1 = credentials[startIndex].ToNativeCredentials()) - using (var cred2 = ToNativeRecursive(startIndex + 1)) + using (var cred2 = CompositeToNativeRecursive(credentials, startIndex + 1)) { var nativeComposite = CallCredentialsSafeHandle.CreateComposite(cred1, cred2); if (nativeComposite.IsInvalid) @@ -69,4 +68,18 @@ namespace Grpc.Core.Internal } } } + + internal static class CallCredentialsExtensions + { + /// + /// Creates native object for the credentials. + /// + /// The native credentials. + public static CallCredentialsSafeHandle ToNativeCredentials(this CallCredentials credentials) + { + var configurator = new DefaultCallCredentialsConfigurator(); + credentials.InternalPopulateConfiguration(configurator, credentials); + return configurator.NativeCredentials; + } + } } diff --git a/src/csharp/Grpc.Core/Internal/MetadataCredentials.cs b/src/csharp/Grpc.Core/Internal/MetadataCredentials.cs deleted file mode 100644 index 8dd00f072e5..00000000000 --- a/src/csharp/Grpc.Core/Internal/MetadataCredentials.cs +++ /dev/null @@ -1,51 +0,0 @@ -#region Copyright notice and license - -// Copyright 2019 The gRPC Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#endregion - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -using Grpc.Core.Internal; -using Grpc.Core.Utils; - -namespace Grpc.Core.Internal -{ - /// - /// Client-side credentials that delegate metadata based auth to an interceptor. - /// The interceptor is automatically invoked for each remote call that uses MetadataCredentials. - /// - internal sealed class MetadataCredentials : CallCredentials - { - readonly AsyncAuthInterceptor interceptor; - - /// - /// Initializes a new instance of MetadataCredentials class. - /// - /// authentication interceptor - public MetadataCredentials(AsyncAuthInterceptor interceptor) - { - this.interceptor = GrpcPreconditions.CheckNotNull(interceptor); - } - - internal override CallCredentialsSafeHandle ToNativeCredentials() - { - NativeMetadataCredentialsPlugin plugin = new NativeMetadataCredentialsPlugin(interceptor); - return plugin.Credentials; - } - } -} From 0de1cd2d66faa6a2380b46dab5c834663a4f9996 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 5 Apr 2019 05:26:01 +0200 Subject: [PATCH 199/242] Update license header --- src/csharp/Grpc.Core.Api/BindServiceMethodAttribute.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/csharp/Grpc.Core.Api/BindServiceMethodAttribute.cs b/src/csharp/Grpc.Core.Api/BindServiceMethodAttribute.cs index 329b23dadff..2ee0abe1d0a 100644 --- a/src/csharp/Grpc.Core.Api/BindServiceMethodAttribute.cs +++ b/src/csharp/Grpc.Core.Api/BindServiceMethodAttribute.cs @@ -1,5 +1,5 @@ #region Copyright notice and license -// Copyright 2015 gRPC authors. +// Copyright 2019 The gRPC Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. From ca209ae00e77226a2f70dc3b9221928b18af146d Mon Sep 17 00:00:00 2001 From: Moiz Haidry Date: Fri, 5 Apr 2019 09:33:40 -0700 Subject: [PATCH 200/242] Fix typo in server credentials impl header file --- include/grpcpp/security/server_credentials_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/grpcpp/security/server_credentials_impl.h b/include/grpcpp/security/server_credentials_impl.h index e0fddbf1bc8..afe8d22650b 100644 --- a/include/grpcpp/security/server_credentials_impl.h +++ b/include/grpcpp/security/server_credentials_impl.h @@ -51,7 +51,7 @@ class ServerCredentials { /// Tries to bind \a server to the given \a addr (eg, localhost:1234, /// 192.168.1.1:31416, [::1]:27182, etc.) /// - /// \return bound port number on sucess, 0 on failure. + /// \return bound port number on success, 0 on failure. // TODO(dgq): the "port" part seems to be a misnomer. virtual int AddPortToServer(const grpc::string& addr, grpc_server* server) = 0; From 7eb3f28b7fa54de50e4d63960d615d4f430cf12a Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Fri, 5 Apr 2019 10:10:55 -0700 Subject: [PATCH 201/242] added todo statments --- .../internal_ci/linux/grpc_bazel_build_in_docker.sh | 1 + .../linux/grpc_python_bazel_test_in_docker.sh | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh b/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh index 343ca17793d..3dd0167b7c0 100755 --- a/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh +++ b/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh @@ -24,4 +24,5 @@ git clone /var/local/jenkins/grpc /var/local/git/grpc && git submodule update --init --reference /var/local/jenkins/grpc/${name} \ ${name}') cd /var/local/git/grpc +#TODO(yfen): add back examples/... to build targets once python rules issues are resolved bazel build --spawn_strategy=standalone --genrule_strategy=standalone :all test/... diff --git a/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh b/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh index d844cff7f9a..3ca4673ca08 100755 --- a/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh +++ b/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh @@ -23,9 +23,10 @@ git clone /var/local/jenkins/grpc /var/local/git/grpc (cd /var/local/jenkins/grpc/ && git submodule foreach 'cd /var/local/git/grpc \ && git submodule update --init --reference /var/local/jenkins/grpc/${name} \ ${name}') -cd /var/local/git/grpc/test -bazel test --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //src/python/... -bazel test --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //examples/python/... -bazel clean --expunge -bazel test --config=python3 --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //src/python/... -bazel test --config=python3 --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //examples/python/... +#TODO(yfen): temporarily disabled all python bazel tests due to incompatibility with bazel 0.23.2 +#cd /var/local/git/grpc/test +#bazel test --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //src/python/... +#bazel test --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //examples/python/... +#bazel clean --expunge +#bazel test --config=python3 --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //src/python/... +#bazel test --config=python3 --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //examples/python/... From e8c0b2433ac82f21dde122380dfb523859bacbe4 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Fri, 5 Apr 2019 10:20:13 -0700 Subject: [PATCH 202/242] Make script fixes --- BUILD.gn | 1 + CMakeLists.txt | 3 +++ Makefile | 3 +++ build.yaml | 1 + gRPC-C++.podspec | 1 + tools/doxygen/Doxyfile.c++ | 1 + tools/doxygen/Doxyfile.c++.internal | 1 + tools/run_tests/generated/sources_and_headers.json | 2 ++ 8 files changed, 13 insertions(+) diff --git a/BUILD.gn b/BUILD.gn index 8fed27e202e..3fd5154834f 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1088,6 +1088,7 @@ config("grpc_config") { "include/grpcpp/server.h", "include/grpcpp/server_builder.h", "include/grpcpp/server_context.h", + "include/grpcpp/server_impl.h", "include/grpcpp/server_posix.h", "include/grpcpp/server_posix_impl.h", "include/grpcpp/support/async_stream.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index a84523e5c92..a53847588f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3036,6 +3036,7 @@ foreach(_hdr include/grpcpp/server.h include/grpcpp/server_builder.h include/grpcpp/server_context.h + include/grpcpp/server_impl.h include/grpcpp/server_posix.h include/grpcpp/server_posix_impl.h include/grpcpp/support/async_stream.h @@ -3637,6 +3638,7 @@ foreach(_hdr include/grpcpp/server.h include/grpcpp/server_builder.h include/grpcpp/server_context.h + include/grpcpp/server_impl.h include/grpcpp/server_posix.h include/grpcpp/server_posix_impl.h include/grpcpp/support/async_stream.h @@ -4612,6 +4614,7 @@ foreach(_hdr include/grpcpp/server.h include/grpcpp/server_builder.h include/grpcpp/server_context.h + include/grpcpp/server_impl.h include/grpcpp/server_posix.h include/grpcpp/server_posix_impl.h include/grpcpp/support/async_stream.h diff --git a/Makefile b/Makefile index d1158bf31ba..b04ab44b33d 100644 --- a/Makefile +++ b/Makefile @@ -5367,6 +5367,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ + include/grpcpp/server_impl.h \ include/grpcpp/server_posix.h \ include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ @@ -5976,6 +5977,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ + include/grpcpp/server_impl.h \ include/grpcpp/server_posix.h \ include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ @@ -6900,6 +6902,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ + include/grpcpp/server_impl.h \ include/grpcpp/server_posix.h \ include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ diff --git a/build.yaml b/build.yaml index 888b613dc0e..42ae58793e1 100644 --- a/build.yaml +++ b/build.yaml @@ -1382,6 +1382,7 @@ filegroups: - include/grpcpp/server.h - include/grpcpp/server_builder.h - include/grpcpp/server_context.h + - include/grpcpp/server_impl.h - include/grpcpp/server_posix.h - include/grpcpp/server_posix_impl.h - include/grpcpp/support/async_stream.h diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 051397f1e67..2d2ee28850d 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -121,6 +121,7 @@ Pod::Spec.new do |s| 'include/grpcpp/server.h', 'include/grpcpp/server_builder.h', 'include/grpcpp/server_context.h', + 'include/grpcpp/server_impl.h', 'include/grpcpp/server_posix.h', 'include/grpcpp/server_posix_impl.h', 'include/grpcpp/support/async_stream.h', diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index a56d2df8530..114d5e6dfa1 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -1011,6 +1011,7 @@ include/grpcpp/security/server_credentials_impl.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ +include/grpcpp/server_impl.h \ include/grpcpp/server_posix.h \ include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 6bf498307bb..4f6bd406bdf 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -1013,6 +1013,7 @@ include/grpcpp/security/server_credentials_impl.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ +include/grpcpp/server_impl.h \ include/grpcpp/server_posix.h \ include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 71e2b0d2207..898f96ad4b9 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -10131,6 +10131,7 @@ "include/grpcpp/server.h", "include/grpcpp/server_builder.h", "include/grpcpp/server_context.h", + "include/grpcpp/server_impl.h", "include/grpcpp/server_posix.h", "include/grpcpp/server_posix_impl.h", "include/grpcpp/support/async_stream.h", @@ -10250,6 +10251,7 @@ "include/grpcpp/server.h", "include/grpcpp/server_builder.h", "include/grpcpp/server_context.h", + "include/grpcpp/server_impl.h", "include/grpcpp/server_posix.h", "include/grpcpp/server_posix_impl.h", "include/grpcpp/support/async_stream.h", From df89d8e157b05f524bd25a191cba59a134d8c2c3 Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Fri, 5 Apr 2019 11:32:44 -0700 Subject: [PATCH 203/242] bazel RBE Windows build --- BUILD | 1 + WORKSPACE | 2 + test/core/end2end/generate_tests.bzl | 5 + test/core/handshake/BUILD | 4 + test/core/network_benchmarks/BUILD | 1 + test/core/util/BUILD | 1 + third_party/toolchains/BUILD | 30 + third_party/toolchains/bazel_0.23.2/BUILD | 188 ++ .../bazel_0.23.2/cc_toolchain_config.bzl | 1704 +++++++++++++++++ .../bazel_0.23.2/dummy_toolchain.bzl | 23 + .../linux/grpc_bazel_build_in_docker.sh | 2 +- tools/remote_build/windows.bazelrc | 48 + 12 files changed, 2008 insertions(+), 1 deletion(-) create mode 100644 third_party/toolchains/bazel_0.23.2/BUILD create mode 100644 third_party/toolchains/bazel_0.23.2/cc_toolchain_config.bzl create mode 100644 third_party/toolchains/bazel_0.23.2/dummy_toolchain.bzl diff --git a/BUILD b/BUILD index 562a71c2f29..ff500c72a39 100644 --- a/BUILD +++ b/BUILD @@ -2347,6 +2347,7 @@ grpc_cc_library( ":google_api_upb", ":proto_gen_validate_upb", ], + tags = ["no_windows"], ) grpc_cc_library( diff --git a/WORKSPACE b/WORKSPACE index 18f389edd24..d90d7b6751d 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -11,10 +11,12 @@ grpc_test_only_deps() register_execution_platforms( "//third_party/toolchains:rbe_ubuntu1604", "//third_party/toolchains:rbe_ubuntu1604_large", + "//third_party/toolchains:rbe_windows", ) register_toolchains( "//third_party/toolchains:cc-toolchain-clang-x86_64-default", + "//third_party/toolchains/bazel_0.23.2:cc-toolchain-x64_windows", ) # TODO(https://github.com/grpc/grpc/issues/18331): Move off of this dependency. diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index b3c58bf29b4..10b9314a84a 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -385,6 +385,7 @@ def grpc_end2end_tests(): ":proxy", ":local_util", ], + tags = ["no_windows"], ) for f, fopt in END2END_FIXTURES.items(): @@ -398,6 +399,7 @@ def grpc_end2end_tests(): "//:grpc", "//:gpr", ], + tags = ["no_windows"], ) for t, topt in END2END_TESTS.items(): #print(_compatible(fopt, topt), f, t, fopt, topt) @@ -413,6 +415,7 @@ def grpc_end2end_tests(): t, poller, ], + tags = ["no_windows"], ) def grpc_end2end_nosec_tests(): @@ -435,6 +438,7 @@ def grpc_end2end_nosec_tests(): ":proxy", ":local_util", ], + tags = ["no_windows"], ) for f, fopt in END2END_NOSEC_FIXTURES.items(): @@ -450,6 +454,7 @@ def grpc_end2end_nosec_tests(): "//:grpc_unsecure", "//:gpr", ], + tags = ["no_windows"], ) for t, topt in END2END_TESTS.items(): #print(_compatible(fopt, topt), f, t, fopt, topt) diff --git a/test/core/handshake/BUILD b/test/core/handshake/BUILD index b9d2f31515a..0824efb980f 100644 --- a/test/core/handshake/BUILD +++ b/test/core/handshake/BUILD @@ -32,6 +32,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_library( @@ -43,6 +44,7 @@ grpc_cc_library( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -60,6 +62,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -77,6 +80,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( diff --git a/test/core/network_benchmarks/BUILD b/test/core/network_benchmarks/BUILD index fbc611d5fe3..1194e4ad7bb 100644 --- a/test/core/network_benchmarks/BUILD +++ b/test/core/network_benchmarks/BUILD @@ -33,4 +33,5 @@ grpc_cc_binary( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) diff --git a/test/core/util/BUILD b/test/core/util/BUILD index b10d3e4287b..98e69c6ef34 100644 --- a/test/core/util/BUILD +++ b/test/core/util/BUILD @@ -133,6 +133,7 @@ grpc_cc_library( ":grpc_test_util", "//:grpc", ], + tags = ["no_windows"], ) grpc_cc_test( diff --git a/third_party/toolchains/BUILD b/third_party/toolchains/BUILD index 943690a2efd..5ee528d5d46 100644 --- a/third_party/toolchains/BUILD +++ b/third_party/toolchains/BUILD @@ -28,6 +28,36 @@ alias( actual = ":rbe_ubuntu1604_r346485_large", ) +alias( + name = "rbe_windows", + actual = ":rbe_windows_1803", +) + +# RBE Windows +platform( + name = "rbe_windows_1803", + constraint_values = [ + "@bazel_tools//platforms:x86_64", + "@bazel_tools//platforms:windows", + "@bazel_tools//tools/cpp:msvc", + ], + remote_execution_properties = """ + properties: { + name: "container-image" + value:"docker://gcr.io/grpc-testing/rbe_windows_toolchain@sha256:689b177e4a157c431c7077d19d043de27922c37de835031f29c9093b8d5c6370" + } + properties: { + name: "gceMachineType" # Small machines for majority of tests. + value: "n1-highmem-2" + } + properties:{ + name: "OSFamily" + value: "Windows" + } + + """, +) + # RBE Ubuntu16_04 r346485 platform( name = "rbe_ubuntu1604_r346485", diff --git a/third_party/toolchains/bazel_0.23.2/BUILD b/third_party/toolchains/bazel_0.23.2/BUILD new file mode 100644 index 00000000000..5ce4e00c866 --- /dev/null +++ b/third_party/toolchains/bazel_0.23.2/BUILD @@ -0,0 +1,188 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This becomes the BUILD file for @local_config_cc// under Windows. +licenses(["notice"]) # Apache v2 + +package(default_visibility = ["//visibility:public"]) + +load(":cc_toolchain_config.bzl", "cc_toolchain_config") + +cc_library( + name = "malloc", +) + +filegroup( + name = "empty", + srcs = [], +) + +# Hardcoded toolchain, legacy behaviour. +cc_toolchain_suite( + name = "toolchain", + toolchains = { + "armeabi-v7a|compiler": ":cc-compiler-armeabi-v7a", + "x64_windows|msvc-cl": ":cc-compiler-x64_windows", + "x64_windows|msys-gcc": ":cc-compiler-x64_windows_msys", + "x64_windows|mingw-gcc": ":cc-compiler-x64_windows_mingw", + "x64_windows_msys": ":cc-compiler-x64_windows_msys", + "x64_windows": ":cc-compiler-x64_windows", + "armeabi-v7a": ":cc-compiler-armeabi-v7a", + }, +) + +cc_toolchain( + name = "cc-compiler-x64_windows_msys", + all_files = ":empty", + ar_files = ":empty", + as_files = ":empty", + compiler_files = ":empty", + dwp_files = ":empty", + linker_files = ":empty", + objcopy_files = ":empty", + strip_files = ":empty", + supports_param_files = 1, + toolchain_config = ":msys_x64", + toolchain_identifier = "msys_x64", +) + +cc_toolchain_config( + name = "msys_x64", + compiler = "msys-gcc", + cpu = "x64_windows", +) + +toolchain( + name = "cc-toolchain-x64_windows_msys", + exec_compatible_with = [ + "@bazel_tools//platforms:x86_64", + "@bazel_tools//platforms:windows", + "@bazel_tools//tools/cpp:msys", + ], + target_compatible_with = [ + "@bazel_tools//platforms:x86_64", + "@bazel_tools//platforms:windows", + ], + toolchain = ":cc-compiler-x64_windows_msys", + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", +) + +cc_toolchain( + name = "cc-compiler-x64_windows_mingw", + all_files = ":empty", + ar_files = ":empty", + as_files = ":empty", + compiler_files = ":empty", + dwp_files = ":empty", + linker_files = ":empty", + objcopy_files = ":empty", + strip_files = ":empty", + supports_param_files = 0, + toolchain_config = ":msys_x64_mingw", + toolchain_identifier = "msys_x64_mingw", +) + +cc_toolchain_config( + name = "msys_x64_mingw", + compiler = "mingw-gcc", + cpu = "x64_windows", +) + +toolchain( + name = "cc-toolchain-x64_windows_mingw", + exec_compatible_with = [ + "@bazel_tools//platforms:x86_64", + "@bazel_tools//platforms:windows", + "@bazel_tools//tools/cpp:mingw", + ], + target_compatible_with = [ + "@bazel_tools//platforms:x86_64", + "@bazel_tools//platforms:windows", + ], + toolchain = ":cc-compiler-x64_windows_mingw", + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", +) + +cc_toolchain( + name = "cc-compiler-x64_windows", + all_files = ":empty", + ar_files = ":empty", + as_files = ":empty", + compiler_files = ":empty", + dwp_files = ":empty", + linker_files = ":empty", + objcopy_files = ":empty", + strip_files = ":empty", + supports_param_files = 1, + toolchain_config = ":msvc_x64", + toolchain_identifier = "msvc_x64", +) + +cc_toolchain_config( + name = "msvc_x64", + compiler = "msvc-cl", + cpu = "x64_windows", +) + +toolchain( + name = "cc-toolchain-x64_windows", + exec_compatible_with = [ + "@bazel_tools//platforms:x86_64", + "@bazel_tools//platforms:windows", + ], + target_compatible_with = [ + "@bazel_tools//platforms:x86_64", + "@bazel_tools//platforms:windows", + ], + toolchain = ":cc-compiler-x64_windows", + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", +) + +cc_toolchain( + name = "cc-compiler-armeabi-v7a", + all_files = ":empty", + ar_files = ":empty", + as_files = ":empty", + compiler_files = ":empty", + dwp_files = ":empty", + linker_files = ":empty", + objcopy_files = ":empty", + strip_files = ":empty", + supports_param_files = 1, + toolchain_config = ":stub_armeabi-v7a", + toolchain_identifier = "stub_armeabi-v7a", +) + +cc_toolchain_config( + name = "stub_armeabi-v7a", + compiler = "compiler", + cpu = "armeabi-v7a", +) + +toolchain( + name = "cc-toolchain-armeabi-v7a", + exec_compatible_with = [ + ], + target_compatible_with = [ + "@bazel_tools//platforms:arm", + "@bazel_tools//platforms:android", + ], + toolchain = ":cc-compiler-armeabi-v7a", + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", +) + +filegroup( + name = "link_dynamic_library", + srcs = ["link_dynamic_library.sh"], +) diff --git a/third_party/toolchains/bazel_0.23.2/cc_toolchain_config.bzl b/third_party/toolchains/bazel_0.23.2/cc_toolchain_config.bzl new file mode 100644 index 00000000000..790ddcb0947 --- /dev/null +++ b/third_party/toolchains/bazel_0.23.2/cc_toolchain_config.bzl @@ -0,0 +1,1704 @@ +# Copyright 2019 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""A Starlark cc_toolchain configuration rule""" + +load( + "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl", + "action_config", + "artifact_name_pattern", + "env_entry", + "env_set", + "feature", + "feature_set", + "flag_group", + "flag_set", + "make_variable", + "tool", + "tool_path", + "variable_with_value", + "with_feature_set", +) +load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES") + +all_compile_actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.clif_match, + ACTION_NAMES.lto_backend, +] + +all_cpp_compile_actions = [ + ACTION_NAMES.cpp_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.clif_match, +] + +preprocessor_compile_actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.clif_match, +] + +codegen_compile_actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, +] + +all_link_actions = [ + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, +] + +def _windows_msvc_impl(ctx): + toolchain_identifier = "msvc_x64" + host_system_name = "local" + target_system_name = "local" + target_cpu = "x64_windows" + target_libc = "msvcrt" + compiler = "msvc-cl" + abi_version = "local" + abi_libc_version = "local" + cc_target_os = None + builtin_sysroot = None + + cxx_builtin_include_directories = [ + # This is a workaround for https://github.com/bazelbuild/bazel/issues/5087. + "C:\\botcode\\w", + "c:/tools/msys64/usr/", + "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\INCLUDE", + "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.10240.0\\ucrt", + "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\shared", + "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\um", + "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\winrt", + ] + + cpp_link_nodeps_dynamic_library_action = action_config( + action_name = ACTION_NAMES.cpp_link_nodeps_dynamic_library, + implies = [ + "nologo", + "shared_flag", + "linkstamps", + "output_execpath_flags", + "input_param_flags", + "user_link_flags", + "default_link_flags", + "linker_subsystem_flag", + "linker_param_file", + "msvc_env", + "no_stripping", + "has_configured_linker_path", + "def_file", + ], + tools = [tool(path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/link.exe")], + ) + + cpp_link_static_library_action = action_config( + action_name = ACTION_NAMES.cpp_link_static_library, + implies = [ + "nologo", + "archiver_flags", + "input_param_flags", + "linker_param_file", + "msvc_env", + ], + tools = [tool(path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/lib.exe")], + ) + + assemble_action = action_config( + action_name = ACTION_NAMES.assemble, + implies = [ + "compiler_input_flags", + "compiler_output_flags", + "nologo", + "msvc_env", + "sysroot", + ], + tools = [tool(path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/ml64.exe")], + ) + + preprocess_assemble_action = action_config( + action_name = ACTION_NAMES.preprocess_assemble, + implies = [ + "compiler_input_flags", + "compiler_output_flags", + "nologo", + "msvc_env", + "sysroot", + ], + tools = [tool(path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/ml64.exe")], + ) + + c_compile_action = action_config( + action_name = ACTION_NAMES.c_compile, + implies = [ + "compiler_input_flags", + "compiler_output_flags", + "default_compile_flags", + "nologo", + "msvc_env", + "parse_showincludes", + "user_compile_flags", + "sysroot", + "unfiltered_compile_flags", + ], + tools = [tool(path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/cl.exe")], + ) + + cpp_compile_action = action_config( + action_name = ACTION_NAMES.cpp_compile, + implies = [ + "compiler_input_flags", + "compiler_output_flags", + "default_compile_flags", + "nologo", + "msvc_env", + "parse_showincludes", + "user_compile_flags", + "sysroot", + "unfiltered_compile_flags", + ], + tools = [tool(path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/cl.exe")], + ) + + cpp_link_executable_action = action_config( + action_name = ACTION_NAMES.cpp_link_executable, + implies = [ + "nologo", + "linkstamps", + "output_execpath_flags", + "input_param_flags", + "user_link_flags", + "default_link_flags", + "linker_subsystem_flag", + "linker_param_file", + "msvc_env", + "no_stripping", + ], + tools = [tool(path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/link.exe")], + ) + + cpp_link_dynamic_library_action = action_config( + action_name = ACTION_NAMES.cpp_link_dynamic_library, + implies = [ + "nologo", + "shared_flag", + "linkstamps", + "output_execpath_flags", + "input_param_flags", + "user_link_flags", + "default_link_flags", + "linker_subsystem_flag", + "linker_param_file", + "msvc_env", + "no_stripping", + "has_configured_linker_path", + "def_file", + ], + tools = [tool(path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/link.exe")], + ) + + action_configs = [ + assemble_action, + preprocess_assemble_action, + c_compile_action, + cpp_compile_action, + cpp_link_executable_action, + cpp_link_dynamic_library_action, + cpp_link_nodeps_dynamic_library_action, + cpp_link_static_library_action, + ] + + msvc_link_env_feature = feature( + name = "msvc_link_env", + env_sets = [ + env_set( + actions = all_link_actions + + [ACTION_NAMES.cpp_link_static_library], + env_entries = [env_entry(key = "LIB", value = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\LIB\\amd64;C:\\Program Files (x86)\\Windows Kits\\10\\lib\\10.0.10240.0\\ucrt\\x64;C:\\Program Files (x86)\\Windows Kits\\8.1\\lib\\winv6.3\\um\\x64;")], + ), + ], + ) + + shared_flag_feature = feature( + name = "shared_flag", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [flag_group(flags = ["/DLL"])], + ), + ], + ) + + determinism_feature = feature( + name = "determinism", + enabled = True, + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group( + flags = [ + "/wd4117", + "-D__DATE__=\"redacted\"", + "-D__TIMESTAMP__=\"redacted\"", + "-D__TIME__=\"redacted\"", + ], + ), + ], + ), + ], + ) + + sysroot_feature = feature( + name = "sysroot", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [ + flag_group( + flags = ["--sysroot=%{sysroot}"], + iterate_over = "sysroot", + expand_if_available = "sysroot", + ), + ], + ), + ], + ) + + unfiltered_compile_flags_feature = feature( + name = "unfiltered_compile_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ], + flag_groups = [ + flag_group( + flags = ["%{unfiltered_compile_flags}"], + iterate_over = "unfiltered_compile_flags", + expand_if_available = "unfiltered_compile_flags", + ), + ], + ), + ], + ) + + copy_dynamic_libraries_to_binary_feature = feature(name = "copy_dynamic_libraries_to_binary") + + input_param_flags_feature = feature( + name = "input_param_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [ + flag_group( + flags = ["/IMPLIB:%{interface_library_output_path}"], + expand_if_available = "interface_library_output_path", + ), + ], + ), + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["%{libopts}"], + iterate_over = "libopts", + expand_if_available = "libopts", + ), + ], + ), + flag_set( + actions = all_link_actions + + [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + iterate_over = "libraries_to_link", + flag_groups = [ + flag_group( + iterate_over = "libraries_to_link.object_files", + flag_groups = [flag_group(flags = ["%{libraries_to_link.object_files}"])], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "object_file_group", + ), + ), + flag_group( + flag_groups = [flag_group(flags = ["%{libraries_to_link.name}"])], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "object_file", + ), + ), + flag_group( + flag_groups = [flag_group(flags = ["%{libraries_to_link.name}"])], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "interface_library", + ), + ), + flag_group( + flag_groups = [ + flag_group( + flags = ["%{libraries_to_link.name}"], + expand_if_false = "libraries_to_link.is_whole_archive", + ), + flag_group( + flags = ["/WHOLEARCHIVE:%{libraries_to_link.name}"], + expand_if_true = "libraries_to_link.is_whole_archive", + ), + ], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "static_library", + ), + ), + ], + expand_if_available = "libraries_to_link", + ), + ], + ), + ], + ) + + fastbuild_feature = feature( + name = "fastbuild", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/Od", "/Z7"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["/DEBUG:FASTLINK", "/INCREMENTAL:NO"], + ), + ], + ), + ], + implies = ["generate_pdb_file"], + ) + + user_compile_flags_feature = feature( + name = "user_compile_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ], + flag_groups = [ + flag_group( + flags = ["%{user_compile_flags}"], + iterate_over = "user_compile_flags", + expand_if_available = "user_compile_flags", + ), + ], + ), + ], + ) + + archiver_flags_feature = feature( + name = "archiver_flags", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + flags = ["/OUT:%{output_execpath}"], + expand_if_available = "output_execpath", + ), + ], + ), + ], + ) + + default_link_flags_feature = feature( + name = "default_link_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/MACHINE:X64"])], + ), + ], + ) + + static_link_msvcrt_feature = feature(name = "static_link_msvcrt") + + dynamic_link_msvcrt_debug_feature = feature( + name = "dynamic_link_msvcrt_debug", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/MDd"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/DEFAULTLIB:msvcrtd.lib"])], + ), + ], + requires = [feature_set(features = ["dbg"])], + ) + + dbg_feature = feature( + name = "dbg", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/Od", "/Z7"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["/DEBUG:FULL", "/INCREMENTAL:NO"], + ), + ], + ), + ], + implies = ["generate_pdb_file"], + ) + + opt_feature = feature( + name = "opt", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/O2"])], + ), + ], + implies = ["frame_pointer"], + ) + + supports_interface_shared_libraries_feature = feature( + name = "supports_interface_shared_libraries", + enabled = True, + ) + + user_link_flags_feature = feature( + name = "user_link_flags", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["%{user_link_flags}"], + iterate_over = "user_link_flags", + expand_if_available = "user_link_flags", + ), + ], + ), + ], + ) + + default_compile_flags_feature = feature( + name = "default_compile_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = [ + flag_group( + flags = [ + "/DCOMPILER_MSVC", + "/DNOMINMAX", + "/D_WIN32_WINNT=0x0601", + "/D_CRT_SECURE_NO_DEPRECATE", + "/D_CRT_SECURE_NO_WARNINGS", + "/bigobj", + "/Zm500", + "/EHsc", + "/wd4351", + "/wd4291", + "/wd4250", + "/wd4996", + ], + ), + ], + ), + ], + ) + + msvc_compile_env_feature = feature( + name = "msvc_compile_env", + env_sets = [ + env_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ], + env_entries = [env_entry(key = "INCLUDE", value = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\INCLUDE;C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.10240.0\\ucrt;C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\shared;C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\um;C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\winrt;")], + ), + ], + ) + + preprocessor_defines_feature = feature( + name = "preprocessor_defines", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ], + flag_groups = [ + flag_group( + flags = ["/D%{preprocessor_defines}"], + iterate_over = "preprocessor_defines", + ), + ], + ), + ], + ) + + generate_pdb_file_feature = feature( + name = "generate_pdb_file", + requires = [ + feature_set(features = ["dbg"]), + feature_set(features = ["fastbuild"]), + ], + ) + + output_execpath_flags_feature = feature( + name = "output_execpath_flags", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["/OUT:%{output_execpath}"], + expand_if_available = "output_execpath", + ), + ], + ), + ], + ) + + dynamic_link_msvcrt_no_debug_feature = feature( + name = "dynamic_link_msvcrt_no_debug", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/MD"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/DEFAULTLIB:msvcrt.lib"])], + ), + ], + requires = [ + feature_set(features = ["fastbuild"]), + feature_set(features = ["opt"]), + ], + ) + + disable_assertions_feature = feature( + name = "disable_assertions", + enabled = True, + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/DNDEBUG"])], + with_features = [with_feature_set(features = ["opt"])], + ), + ], + ) + + has_configured_linker_path_feature = feature(name = "has_configured_linker_path") + + supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True) + + no_stripping_feature = feature(name = "no_stripping") + + linker_param_file_feature = feature( + name = "linker_param_file", + flag_sets = [ + flag_set( + actions = all_link_actions + + [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + flags = ["@%{linker_param_file}"], + expand_if_available = "linker_param_file", + ), + ], + ), + ], + ) + + ignore_noisy_warnings_feature = feature( + name = "ignore_noisy_warnings", + enabled = True, + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.cpp_link_static_library], + flag_groups = [flag_group(flags = ["/ignore:4221"])], + ), + ], + ) + + no_legacy_features_feature = feature(name = "no_legacy_features") + + parse_showincludes_feature = feature( + name = "parse_showincludes", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_header_parsing, + ], + flag_groups = [flag_group(flags = ["/showIncludes"])], + ), + ], + ) + + static_link_msvcrt_no_debug_feature = feature( + name = "static_link_msvcrt_no_debug", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/MT"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/DEFAULTLIB:libcmt.lib"])], + ), + ], + requires = [ + feature_set(features = ["fastbuild"]), + feature_set(features = ["opt"]), + ], + ) + + treat_warnings_as_errors_feature = feature( + name = "treat_warnings_as_errors", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/WX"])], + ), + ], + ) + + windows_export_all_symbols_feature = feature(name = "windows_export_all_symbols") + + no_windows_export_all_symbols_feature = feature(name = "no_windows_export_all_symbols") + + include_paths_feature = feature( + name = "include_paths", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ], + flag_groups = [ + flag_group( + flags = ["/I%{quote_include_paths}"], + iterate_over = "quote_include_paths", + ), + flag_group( + flags = ["/I%{include_paths}"], + iterate_over = "include_paths", + ), + flag_group( + flags = ["/I%{system_include_paths}"], + iterate_over = "system_include_paths", + ), + ], + ), + ], + ) + + linkstamps_feature = feature( + name = "linkstamps", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["%{linkstamp_paths}"], + iterate_over = "linkstamp_paths", + expand_if_available = "linkstamp_paths", + ), + ], + ), + ], + ) + + targets_windows_feature = feature( + name = "targets_windows", + enabled = True, + implies = ["copy_dynamic_libraries_to_binary"], + ) + + linker_subsystem_flag_feature = feature( + name = "linker_subsystem_flag", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/SUBSYSTEM:CONSOLE"])], + ), + ], + ) + + static_link_msvcrt_debug_feature = feature( + name = "static_link_msvcrt_debug", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/MTd"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/DEFAULTLIB:libcmtd.lib"])], + ), + ], + requires = [feature_set(features = ["dbg"])], + ) + + frame_pointer_feature = feature( + name = "frame_pointer", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/Oy-"])], + ), + ], + ) + + compiler_output_flags_feature = feature( + name = "compiler_output_flags", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.assemble], + flag_groups = [ + flag_group( + flag_groups = [ + flag_group( + flags = ["/Fo%{output_file}", "/Zi"], + expand_if_available = "output_file", + expand_if_not_available = "output_assembly_file", + ), + ], + expand_if_not_available = "output_preprocess_file", + ), + ], + ), + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ], + flag_groups = [ + flag_group( + flag_groups = [ + flag_group( + flags = ["/Fo%{output_file}"], + expand_if_not_available = "output_preprocess_file", + ), + ], + expand_if_available = "output_file", + expand_if_not_available = "output_assembly_file", + ), + flag_group( + flag_groups = [ + flag_group( + flags = ["/Fa%{output_file}"], + expand_if_available = "output_assembly_file", + ), + ], + expand_if_available = "output_file", + ), + flag_group( + flag_groups = [ + flag_group( + flags = ["/P", "/Fi%{output_file}"], + expand_if_available = "output_preprocess_file", + ), + ], + expand_if_available = "output_file", + ), + ], + ), + ], + ) + + nologo_feature = feature( + name = "nologo", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_static_library, + ], + flag_groups = [flag_group(flags = ["/nologo"])], + ), + ], + ) + + smaller_binary_feature = feature( + name = "smaller_binary", + enabled = True, + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/Gy", "/Gw"])], + with_features = [with_feature_set(features = ["opt"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/OPT:ICF", "/OPT:REF"])], + with_features = [with_feature_set(features = ["opt"])], + ), + ], + ) + + compiler_input_flags_feature = feature( + name = "compiler_input_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ], + flag_groups = [ + flag_group( + flags = ["/c", "%{source_file}"], + expand_if_available = "source_file", + ), + ], + ), + ], + ) + + def_file_feature = feature( + name = "def_file", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["/DEF:%{def_file_path}", "/ignore:4070"], + expand_if_available = "def_file_path", + ), + ], + ), + ], + ) + + msvc_env_feature = feature( + name = "msvc_env", + env_sets = [ + env_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_static_library, + ], + env_entries = [ + env_entry(key = "PATH", value = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\BIN\\amd64;C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework64\\;C:\\Program Files (x86)\\Windows Kits\\8.1\\bin\\x64;C:\\Program Files (x86)\\Windows Kits\\8.1\\bin\\x86;;C:\\Windows\\system32"), + env_entry(key = "TMP", value = "C:\\Users\\ContainerAdministrator\\AppData\\Local\\Temp"), + env_entry(key = "TEMP", value = "C:\\Users\\ContainerAdministrator\\AppData\\Local\\Temp"), + ], + ), + ], + implies = ["msvc_compile_env", "msvc_link_env"], + ) + + features = [ + no_legacy_features_feature, + nologo_feature, + has_configured_linker_path_feature, + no_stripping_feature, + targets_windows_feature, + copy_dynamic_libraries_to_binary_feature, + default_compile_flags_feature, + msvc_env_feature, + msvc_compile_env_feature, + msvc_link_env_feature, + include_paths_feature, + preprocessor_defines_feature, + parse_showincludes_feature, + generate_pdb_file_feature, + shared_flag_feature, + linkstamps_feature, + output_execpath_flags_feature, + archiver_flags_feature, + input_param_flags_feature, + linker_subsystem_flag_feature, + user_link_flags_feature, + default_link_flags_feature, + linker_param_file_feature, + static_link_msvcrt_feature, + static_link_msvcrt_no_debug_feature, + dynamic_link_msvcrt_no_debug_feature, + static_link_msvcrt_debug_feature, + dynamic_link_msvcrt_debug_feature, + dbg_feature, + fastbuild_feature, + opt_feature, + frame_pointer_feature, + disable_assertions_feature, + determinism_feature, + treat_warnings_as_errors_feature, + smaller_binary_feature, + ignore_noisy_warnings_feature, + user_compile_flags_feature, + sysroot_feature, + unfiltered_compile_flags_feature, + compiler_output_flags_feature, + compiler_input_flags_feature, + def_file_feature, + windows_export_all_symbols_feature, + no_windows_export_all_symbols_feature, + supports_dynamic_linker_feature, + supports_interface_shared_libraries_feature, + ] + + artifact_name_patterns = [ + artifact_name_pattern( + category_name = "object_file", + prefix = "", + extension = ".obj", + ), + artifact_name_pattern( + category_name = "static_library", + prefix = "", + extension = ".lib", + ), + artifact_name_pattern( + category_name = "alwayslink_static_library", + prefix = "", + extension = ".lo.lib", + ), + artifact_name_pattern( + category_name = "executable", + prefix = "", + extension = ".exe", + ), + artifact_name_pattern( + category_name = "dynamic_library", + prefix = "", + extension = ".dll", + ), + artifact_name_pattern( + category_name = "interface_library", + prefix = "", + extension = ".if.lib", + ), + ] + + make_variables = [] + + tool_paths = [ + tool_path(name = "ar", path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/lib.exe"), + tool_path(name = "ml", path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/ml64.exe"), + tool_path(name = "cpp", path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/cl.exe"), + tool_path(name = "gcc", path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/cl.exe"), + tool_path(name = "gcov", path = "wrapper/bin/msvc_nop.bat"), + tool_path(name = "ld", path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/link.exe"), + tool_path(name = "nm", path = "wrapper/bin/msvc_nop.bat"), + tool_path( + name = "objcopy", + path = "wrapper/bin/msvc_nop.bat", + ), + tool_path( + name = "objdump", + path = "wrapper/bin/msvc_nop.bat", + ), + tool_path( + name = "strip", + path = "wrapper/bin/msvc_nop.bat", + ), + ] + + return cc_common.create_cc_toolchain_config_info( + ctx = ctx, + features = features, + action_configs = action_configs, + artifact_name_patterns = artifact_name_patterns, + cxx_builtin_include_directories = cxx_builtin_include_directories, + toolchain_identifier = toolchain_identifier, + host_system_name = host_system_name, + target_system_name = target_system_name, + target_cpu = target_cpu, + target_libc = target_libc, + compiler = compiler, + abi_version = abi_version, + abi_libc_version = abi_libc_version, + tool_paths = tool_paths, + make_variables = make_variables, + builtin_sysroot = builtin_sysroot, + cc_target_os = None, + ) + +def _windows_msys_mingw_impl(ctx): + toolchain_identifier = "msys_x64_mingw" + host_system_name = "local" + target_system_name = "local" + target_cpu = "x64_windows" + target_libc = "mingw" + compiler = "mingw-gcc" + abi_version = "local" + abi_libc_version = "local" + cc_target_os = None + builtin_sysroot = None + action_configs = [] + + targets_windows_feature = feature( + name = "targets_windows", + implies = ["copy_dynamic_libraries_to_binary"], + enabled = True, + ) + + copy_dynamic_libraries_to_binary_feature = feature(name = "copy_dynamic_libraries_to_binary") + + gcc_env_feature = feature( + name = "gcc_env", + enabled = True, + env_sets = [ + env_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_static_library, + ], + env_entries = [ + env_entry(key = "PATH", value = "c:/tools/msys64/mingw64/bin"), + ], + ), + ], + ) + + msys_mingw_flags = [ + "-std=gnu++0x", + ] + msys_mingw_link_flags = [ + "-lstdc++", + ] + + default_compile_flags_feature = feature( + name = "default_compile_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + ), + flag_set( + actions = [ + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = ([flag_group(flags = msys_mingw_flags)] if msys_mingw_flags else []), + ), + ], + ) + + default_link_flags_feature = feature( + name = "default_link_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = ([flag_group(flags = msys_mingw_link_flags)] if msys_mingw_link_flags else []), + ), + ], + ) + + supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True) + + features = [ + targets_windows_feature, + copy_dynamic_libraries_to_binary_feature, + gcc_env_feature, + default_compile_flags_feature, + default_link_flags_feature, + supports_dynamic_linker_feature, + ] + + cxx_builtin_include_directories = [ + # This is a workaround for https://github.com/bazelbuild/bazel/issues/5087. + "C:\\botcode\\w", + "c:/tools/msys64/mingw64/", + "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\INCLUDE", + "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.10240.0\\ucrt", + "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\shared", + "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\um", + "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\winrt", + ] + + artifact_name_patterns = [ + artifact_name_pattern( + category_name = "executable", + prefix = "", + extension = ".exe", + ), + ] + + make_variables = [] + tool_paths = [ + tool_path(name = "ar", path = "c:/tools/msys64/mingw64/bin/ar"), + tool_path(name = "compat-ld", path = "c:/tools/msys64/mingw64/bin/ld"), + tool_path(name = "cpp", path = "c:/tools/msys64/mingw64/bin/cpp"), + tool_path(name = "dwp", path = "c:/tools/msys64/mingw64/bin/dwp"), + tool_path(name = "gcc", path = "c:/tools/msys64/mingw64/bin/gcc"), + tool_path(name = "gcov", path = "c:/tools/msys64/mingw64/bin/gcov"), + tool_path(name = "ld", path = "c:/tools/msys64/mingw64/bin/ld"), + tool_path(name = "nm", path = "c:/tools/msys64/mingw64/bin/nm"), + tool_path(name = "objcopy", path = "c:/tools/msys64/mingw64/bin/objcopy"), + tool_path(name = "objdump", path = "c:/tools/msys64/mingw64/bin/objdump"), + tool_path(name = "strip", path = "c:/tools/msys64/mingw64/bin/strip"), + ] + + return cc_common.create_cc_toolchain_config_info( + ctx = ctx, + features = features, + action_configs = action_configs, + artifact_name_patterns = artifact_name_patterns, + cxx_builtin_include_directories = cxx_builtin_include_directories, + toolchain_identifier = toolchain_identifier, + host_system_name = host_system_name, + target_system_name = target_system_name, + target_cpu = target_cpu, + target_libc = target_libc, + compiler = compiler, + abi_version = abi_version, + abi_libc_version = abi_libc_version, + tool_paths = tool_paths, + make_variables = make_variables, + builtin_sysroot = builtin_sysroot, + cc_target_os = cc_target_os, + ) + +def _armeabi_impl(ctx): + toolchain_identifier = "stub_armeabi-v7a" + host_system_name = "armeabi-v7a" + target_system_name = "armeabi-v7a" + target_cpu = "armeabi-v7a" + target_libc = "armeabi-v7a" + compiler = "compiler" + abi_version = "armeabi-v7a" + abi_libc_version = "armeabi-v7a" + cc_target_os = None + builtin_sysroot = None + action_configs = [] + + supports_pic_feature = feature(name = "supports_pic", enabled = True) + supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True) + features = [supports_dynamic_linker_feature, supports_pic_feature] + + cxx_builtin_include_directories = [ + # This is a workaround for https://github.com/bazelbuild/bazel/issues/5087. + "C:\\botcode\\w", + ] + artifact_name_patterns = [] + make_variables = [] + + tool_paths = [ + tool_path(name = "ar", path = "/bin/false"), + tool_path(name = "compat-ld", path = "/bin/false"), + tool_path(name = "cpp", path = "/bin/false"), + tool_path(name = "dwp", path = "/bin/false"), + tool_path(name = "gcc", path = "/bin/false"), + tool_path(name = "gcov", path = "/bin/false"), + tool_path(name = "ld", path = "/bin/false"), + tool_path(name = "nm", path = "/bin/false"), + tool_path(name = "objcopy", path = "/bin/false"), + tool_path(name = "objdump", path = "/bin/false"), + tool_path(name = "strip", path = "/bin/false"), + ] + + return cc_common.create_cc_toolchain_config_info( + ctx = ctx, + features = features, + action_configs = action_configs, + artifact_name_patterns = artifact_name_patterns, + cxx_builtin_include_directories = cxx_builtin_include_directories, + toolchain_identifier = toolchain_identifier, + host_system_name = host_system_name, + target_system_name = target_system_name, + target_cpu = target_cpu, + target_libc = target_libc, + compiler = compiler, + abi_version = abi_version, + abi_libc_version = abi_libc_version, + tool_paths = tool_paths, + make_variables = make_variables, + builtin_sysroot = builtin_sysroot, + cc_target_os = cc_target_os, + ) + +def _impl(ctx): + if ctx.attr.cpu == "armeabi-v7a": + return _armeabi_impl(ctx) + elif ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "msvc-cl": + return _windows_msvc_impl(ctx) + elif ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "mingw-gcc": + return _windows_msys_mingw_impl(ctx) + + tool_paths = [ + tool_path(name = "ar", path = "c:/tools/msys64/usr/bin/ar"), + tool_path(name = "compat-ld", path = "c:/tools/msys64/usr/bin/ld"), + tool_path(name = "cpp", path = "c:/tools/msys64/usr/bin/cpp"), + tool_path(name = "dwp", path = "c:/tools/msys64/usr/bin/dwp"), + tool_path(name = "gcc", path = "c:/tools/msys64/usr/bin/gcc"), + tool_path(name = "gcov", path = "c:/tools/msys64/usr/bin/gcov"), + tool_path(name = "ld", path = "c:/tools/msys64/usr/bin/ld"), + tool_path(name = "nm", path = "c:/tools/msys64/usr/bin/nm"), + tool_path(name = "objcopy", path = "c:/tools/msys64/usr/bin/objcopy"), + tool_path(name = "objdump", path = "c:/tools/msys64/usr/bin/objdump"), + tool_path(name = "strip", path = "c:/tools/msys64/usr/bin/strip"), + ] + + cxx_builtin_include_directories = [ + # This is a workaround for https://github.com/bazelbuild/bazel/issues/5087. + "C:\\botcode\\w", + "c:/tools/msys64/usr/", + "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\INCLUDE", + "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.10240.0\\ucrt", + "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\shared", + "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\um", + "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\winrt", + ] + + action_configs = [] + + compile_flags = [ + ] + + dbg_compile_flags = [ + ] + + opt_compile_flags = [ + ] + + cxx_flags = [ + "-std=gnu++0x", + ] + + link_flags = [ + "-lstdc++", + ] + + opt_link_flags = [ + ] + + unfiltered_compile_flags = [ + ] + + targets_windows_feature = feature( + name = "targets_windows", + implies = ["copy_dynamic_libraries_to_binary"], + enabled = True, + ) + + copy_dynamic_libraries_to_binary_feature = feature(name = "copy_dynamic_libraries_to_binary") + + gcc_env_feature = feature( + name = "gcc_env", + enabled = True, + env_sets = [ + env_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_static_library, + ], + env_entries = [ + env_entry(key = "PATH", value = "c:/tools/msys64/usr/bin"), + ], + ), + ], + ) + + windows_features = [ + targets_windows_feature, + copy_dynamic_libraries_to_binary_feature, + gcc_env_feature, + ] + + supports_pic_feature = feature( + name = "supports_pic", + enabled = True, + ) + supports_start_end_lib_feature = feature( + name = "supports_start_end_lib", + enabled = True, + ) + + default_compile_flags_feature = feature( + name = "default_compile_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = ([flag_group(flags = compile_flags)] if compile_flags else []), + ), + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = ([flag_group(flags = dbg_compile_flags)] if dbg_compile_flags else []), + with_features = [with_feature_set(features = ["dbg"])], + ), + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = ([flag_group(flags = opt_compile_flags)] if opt_compile_flags else []), + with_features = [with_feature_set(features = ["opt"])], + ), + flag_set( + actions = [ + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = ([flag_group(flags = cxx_flags)] if cxx_flags else []), + ), + ], + ) + + default_link_flags_feature = feature( + name = "default_link_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = ([flag_group(flags = link_flags)] if link_flags else []), + ), + flag_set( + actions = all_link_actions, + flag_groups = ([flag_group(flags = opt_link_flags)] if opt_link_flags else []), + with_features = [with_feature_set(features = ["opt"])], + ), + ], + ) + + dbg_feature = feature(name = "dbg") + + opt_feature = feature(name = "opt") + + sysroot_feature = feature( + name = "sysroot", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [ + flag_group( + flags = ["--sysroot=%{sysroot}"], + expand_if_available = "sysroot", + ), + ], + ), + ], + ) + + fdo_optimize_feature = feature( + name = "fdo_optimize", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group( + flags = [ + "-fprofile-use=%{fdo_profile_path}", + "-fprofile-correction", + ], + expand_if_available = "fdo_profile_path", + ), + ], + ), + ], + provides = ["profile"], + ) + + supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True) + + user_compile_flags_feature = feature( + name = "user_compile_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = [ + flag_group( + flags = ["%{user_compile_flags}"], + iterate_over = "user_compile_flags", + expand_if_available = "user_compile_flags", + ), + ], + ), + ], + ) + + unfiltered_compile_flags_feature = feature( + name = "unfiltered_compile_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = ([flag_group(flags = unfiltered_compile_flags)] if unfiltered_compile_flags else []), + ), + ], + ) + + features = windows_features + [ + supports_pic_feature, + default_compile_flags_feature, + default_link_flags_feature, + fdo_optimize_feature, + supports_dynamic_linker_feature, + dbg_feature, + opt_feature, + user_compile_flags_feature, + sysroot_feature, + unfiltered_compile_flags_feature, + ] + + artifact_name_patterns = [ + artifact_name_pattern(category_name = "executable", prefix = "", extension = ".exe"), + ] + + make_variables = [] + + return cc_common.create_cc_toolchain_config_info( + ctx = ctx, + features = features, + action_configs = action_configs, + artifact_name_patterns = artifact_name_patterns, + cxx_builtin_include_directories = cxx_builtin_include_directories, + toolchain_identifier = "msys_x64", + host_system_name = "local", + target_system_name = "local", + target_cpu = "x64_windows", + target_libc = "msys", + compiler = "msys-gcc", + abi_version = "local", + abi_libc_version = "local", + tool_paths = tool_paths, + make_variables = make_variables, + builtin_sysroot = "", + cc_target_os = None, + ) + +cc_toolchain_config = rule( + implementation = _impl, + attrs = { + "cpu": attr.string(mandatory = True), + "compiler": attr.string(), + }, + provides = [CcToolchainConfigInfo], +) diff --git a/third_party/toolchains/bazel_0.23.2/dummy_toolchain.bzl b/third_party/toolchains/bazel_0.23.2/dummy_toolchain.bzl new file mode 100644 index 00000000000..45c0285d232 --- /dev/null +++ b/third_party/toolchains/bazel_0.23.2/dummy_toolchain.bzl @@ -0,0 +1,23 @@ +# pylint: disable=g-bad-file-header +# Copyright 2017 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Skylark rule that stubs a toolchain.""" + +def _dummy_toolchain_impl(ctx): + ctx = ctx # unused argument + toolchain = platform_common.ToolchainInfo() + return [toolchain] + +dummy_toolchain = rule(_dummy_toolchain_impl, attrs = {}) diff --git a/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh b/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh index 3dd0167b7c0..93f6bd65fe6 100755 --- a/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh +++ b/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh @@ -25,4 +25,4 @@ git clone /var/local/jenkins/grpc /var/local/git/grpc ${name}') cd /var/local/git/grpc #TODO(yfen): add back examples/... to build targets once python rules issues are resolved -bazel build --spawn_strategy=standalone --genrule_strategy=standalone :all test/... +bazel build --spawn_strategy=standalone --genrule_strategy=standalone :all test/... \ No newline at end of file diff --git a/tools/remote_build/windows.bazelrc b/tools/remote_build/windows.bazelrc index 70575372d02..a4cb66a7d34 100644 --- a/tools/remote_build/windows.bazelrc +++ b/tools/remote_build/windows.bazelrc @@ -1,3 +1,51 @@ # TODO(yfen): Merge with rbe_common.bazelrc and enable Windows RBE + +startup --host_jvm_args=-Dbazel.DigestFunction=SHA256 + +build --remote_cache=remotebuildexecution.googleapis.com +build --remote_executor=remotebuildexecution.googleapis.com +build --tls_enabled=true + +build --host_crosstool_top=//third_party/toolchains/bazel_0.23.2:toolchain +build --crosstool_top=//third_party/toolchains/bazel_0.23.2:toolchain +build --extra_toolchains=//third_party/toolchains/bazel_0.23.2:cc-toolchain-x64_windows +# Use custom execution platforms defined in third_party/toolchains +build --extra_execution_platforms=//third_party/toolchains:rbe_windows +build --host_platform=//third_party/toolchains:rbe_windows +build --platforms=//third_party/toolchains:rbe_windows + +build --shell_executable=C:\\tools\\msys64\\usr\\bin\\bash.exe +build --python_path=C:\\Python27\\python.exe + +build --spawn_strategy=remote +build --strategy=Javac=remote +build --strategy=Closure=remote +build --genrule_strategy=remote +build --remote_timeout=3600 + +build --remote_instance_name=projects/grpc-testing/instances/grpc-windows-rbe-test + +build --verbose_failures=true + +build --experimental_strict_action_env=true +build --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 + +# don't use port server +build --define GRPC_PORT_ISOLATED_RUNTIME=1 build --test_tag_filters=-no_windows build --build_tag_filters=-no_windows + +# without verbose gRPC logs the test outputs are not very useful +test --test_env=GRPC_VERBOSITY=debug + +# Set flags for uploading to BES in order to view results in the Bazel Build +# Results UI. +build --bes_backend="buildeventservice.googleapis.com" +build --bes_timeout=60s +build --bes_results_url="https://source.cloud.google.com/results/invocations/" +build --project_id=grpc-testing + +build --jobs=30 + +# print output for tests that fail (default is "summary") +build --test_output=errors From 327350ab3996f12d8daa425f89b3aba94c682854 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 5 Apr 2019 12:16:37 -0700 Subject: [PATCH 204/242] ServiceConfig::Create expects non-Null error and better errors --- .../resolver/dns/c_ares/dns_resolver_ares.cc | 5 +- .../client_channel/resolver_result_parsing.cc | 5 +- .../filters/client_channel/service_config.cc | 115 +++++++++++------- .../filters/client_channel/service_config.h | 15 ++- .../ext/filters/client_channel/subchannel.cc | 5 +- .../message_size/message_size_filter.cc | 5 +- .../client_channel/service_config_test.cc | 51 ++++++-- test/cpp/end2end/grpclb_end2end_test.cc | 4 +- test/cpp/end2end/xds_end2end_test.cc | 4 + 9 files changed, 150 insertions(+), 59 deletions(-) diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc index 7ce706724ee..7b5eb311393 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc @@ -308,8 +308,11 @@ void AresDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) { if (service_config_string != nullptr) { GRPC_CARES_TRACE_LOG("resolver:%p selected service config choice: %s", r, service_config_string); + grpc_error* service_config_error = GRPC_ERROR_NONE; result.service_config = - ServiceConfig::Create(service_config_string, nullptr); + ServiceConfig::Create(service_config_string, &service_config_error); + // Error is currently unused. + GRPC_ERROR_UNREF(service_config_error); } gpr_free(service_config_string); } diff --git a/src/core/ext/filters/client_channel/resolver_result_parsing.cc b/src/core/ext/filters/client_channel/resolver_result_parsing.cc index f523ffe1610..7148e16e70b 100644 --- a/src/core/ext/filters/client_channel/resolver_result_parsing.cc +++ b/src/core/ext/filters/client_channel/resolver_result_parsing.cc @@ -52,7 +52,10 @@ ProcessedResolverResult::ProcessedResolverResult( const char* service_config_json = grpc_channel_arg_get_string( grpc_channel_args_find(resolver_result->args, GRPC_ARG_SERVICE_CONFIG)); if (service_config_json != nullptr) { - service_config_ = ServiceConfig::Create(service_config_json, nullptr); + grpc_error* error = GRPC_ERROR_NONE; + service_config_ = ServiceConfig::Create(service_config_json, &error); + // Error is currently unused. + GRPC_ERROR_UNREF(error); } } else { // Add the service config JSON to channel args so that it's diff --git a/src/core/ext/filters/client_channel/service_config.cc b/src/core/ext/filters/client_channel/service_config.cc index 30b5981da84..360b4cd81bf 100644 --- a/src/core/ext/filters/client_channel/service_config.cc +++ b/src/core/ext/filters/client_channel/service_config.cc @@ -38,30 +38,16 @@ RefCountedPtr ServiceConfig::Create(const char* json, grpc_error** error) { UniquePtr service_config_json(gpr_strdup(json)); UniquePtr json_string(gpr_strdup(json)); + GPR_DEBUG_ASSERT(error != nullptr); grpc_json* json_tree = grpc_json_parse_string(json_string.get()); if (json_tree == nullptr) { - if (error != nullptr) { - *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "failed to parse JSON for service config"); - } + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "failed to parse JSON for service config"); return nullptr; } - grpc_error* create_error; auto return_value = MakeRefCounted( - std::move(service_config_json), std::move(json_string), json_tree, - &create_error); - if (create_error != GRPC_ERROR_NONE) { - if (error != nullptr) { - *error = create_error; - } else { - GRPC_ERROR_UNREF(create_error); - } - return nullptr; - } - if (error != nullptr) { - *error = GRPC_ERROR_NONE; - } - return return_value; + std::move(service_config_json), std::move(json_string), json_tree, error); + return *error == GRPC_ERROR_NONE ? return_value : nullptr; } ServiceConfig::ServiceConfig(UniquePtr service_config_json, @@ -115,22 +101,26 @@ grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( if (child->key == nullptr) continue; if (strcmp(child->key, "name") == 0) { if (child->type != GRPC_JSON_ARRAY) { - return grpc_error_add_child(error, GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "name should be of type Array")); + error = grpc_error_add_child(error, + GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:name error:not of type Array")); + goto wrap_error; } for (grpc_json* name = child->child; name != nullptr; name = name->next) { - UniquePtr path = ParseJsonMethodName(name); + grpc_error* parse_error = GRPC_ERROR_NONE; + UniquePtr path = ParseJsonMethodName(name, &parse_error); if (path == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to parse name"); + error = grpc_error_add_child(error, parse_error); + } else { + GPR_DEBUG_ASSERT(parse_error == GRPC_ERROR_NONE); } paths.push_back(std::move(path)); } } } if (paths.size() == 0) { - return grpc_error_add_child(error, - GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "No names specified in methodConfig")); + error = grpc_error_add_child( + error, GRPC_ERROR_CREATE_FROM_STATIC_STRING("No names specified")); } // Add entry for each path. for (size_t i = 0; i < paths.size(); ++i) { @@ -138,6 +128,11 @@ grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( entries[*idx].value = vector_ptr; // Takes a new ref. ++*idx; } +wrap_error: + if (error != GRPC_ERROR_NONE) { + error = grpc_error_add_child( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("field:methodConfig"), error); + } return error; } @@ -150,8 +145,9 @@ grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) { for (grpc_json* field = json_tree->child; field != nullptr; field = field->next) { if (field->key == nullptr) { - error = grpc_error_add_child(error, GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Illegal key value - NULL")); + error = + grpc_error_add_child(error, GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "error:Illegal key value - NULL")); continue; } if (strcmp(field->key, "methodConfig") == 0) { @@ -159,17 +155,17 @@ grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) { GPR_ASSERT(false); } if (field->type != GRPC_JSON_ARRAY) { - return grpc_error_add_child(error, - GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "methodConfig is not of type Array")); + return grpc_error_add_child( + error, GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:methodConfig error:not of type Array")); } for (grpc_json* method = field->child; method != nullptr; method = method->next) { int count = CountNamesInMethodConfig(method); if (count <= 0) { - error = grpc_error_add_child(error, - GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "No names found in methodConfig")); + error = grpc_error_add_child( + error, GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:methodConfig error:No names found")); } num_entries += static_cast(count); } @@ -184,6 +180,7 @@ grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) { error, ParseJsonMethodConfigToServiceConfigObjectsTable( method, entries, &idx)); } + GPR_DEBUG_ASSERT(num_entries == idx); break; } } @@ -229,24 +226,56 @@ int ServiceConfig::CountNamesInMethodConfig(grpc_json* json) { return num_names; } -UniquePtr ServiceConfig::ParseJsonMethodName(grpc_json* json) { - if (json->type != GRPC_JSON_OBJECT) return nullptr; +UniquePtr ServiceConfig::ParseJsonMethodName(grpc_json* json, + grpc_error** error) { + if (json->type != GRPC_JSON_OBJECT) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Field name should be of type object"); + return nullptr; + } const char* service_name = nullptr; const char* method_name = nullptr; for (grpc_json* child = json->child; child != nullptr; child = child->next) { - if (child->key == nullptr) return nullptr; - if (child->type != GRPC_JSON_STRING) return nullptr; + if (child->key == nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child entry with no key"); + return nullptr; + } + if (child->type != GRPC_JSON_STRING) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Child entry should of type string"); + return nullptr; + } if (strcmp(child->key, "service") == 0) { - if (service_name != nullptr) return nullptr; // Duplicate. - if (child->value == nullptr) return nullptr; + if (service_name != nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:service error:Multiple entries"); + return nullptr; // Duplicate. + } + if (child->value == nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:service error:empty value"); + return nullptr; + } service_name = child->value; } else if (strcmp(child->key, "method") == 0) { - if (method_name != nullptr) return nullptr; // Duplicate. - if (child->value == nullptr) return nullptr; + if (method_name != nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:method error:multiple entries"); + return nullptr; // Duplicate. + } + if (child->value == nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:method error:empty value"); + return nullptr; + } method_name = child->value; } } - if (service_name == nullptr) return nullptr; // Required field. + if (service_name == nullptr) { + *error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING("field:service error:not found"); + return nullptr; // Required field. + } char* path; gpr_asprintf(&path, "/%s/%s", service_name, method_name == nullptr ? "*" : method_name); diff --git a/src/core/ext/filters/client_channel/service_config.h b/src/core/ext/filters/client_channel/service_config.h index 3eb3bd54644..9738cc82d30 100644 --- a/src/core/ext/filters/client_channel/service_config.h +++ b/src/core/ext/filters/client_channel/service_config.h @@ -185,8 +185,9 @@ class ServiceConfig : public RefCounted { static int CountNamesInMethodConfig(grpc_json* json); // Returns a path string for the JSON name object specified by \a json. - // Returns null on error. - static UniquePtr ParseJsonMethodName(grpc_json* json); + // Returns null on error, and stores error in \a error. + static UniquePtr ParseJsonMethodName(grpc_json* json, + grpc_error** error); // Parses the method config from \a json. Adds an entry to \a entries for // each name found, incrementing \a idx for each entry added. @@ -209,8 +210,13 @@ class ServiceConfig : public RefCounted { InlinedVector, kNumPreallocatedParsers> parsed_global_service_config_objects_; + // A map from the method name to the service config objects vector. Note that + // we are using a raw pointer and not a unique pointer so that we can use the + // same vector for multiple names. RefCountedPtr> parsed_method_service_config_objects_table_; + // Storage for all the vectors that are being used in + // parsed_method_service_config_objects_table_. InlinedVector, 32> service_config_objects_vectors_storage_; }; @@ -247,7 +253,10 @@ bool ServiceConfig::ParseJsonMethodConfig( if (strcmp(child->key, "name") == 0) { if (child->type != GRPC_JSON_ARRAY) return false; for (grpc_json* name = child->child; name != nullptr; name = name->next) { - UniquePtr path = ParseJsonMethodName(name); + grpc_error* error = GRPC_ERROR_NONE; + UniquePtr path = ParseJsonMethodName(name, &error); + // We are not reporting the error here. + GRPC_ERROR_UNREF(error); if (path == nullptr) return false; paths.push_back(std::move(path)); } diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index d66779e6192..20a6023f71c 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -590,8 +590,11 @@ Subchannel::Subchannel(SubchannelKey* key, grpc_connector* connector, const char* service_config_json = grpc_channel_arg_get_string( grpc_channel_args_find(args_, GRPC_ARG_SERVICE_CONFIG)); if (service_config_json != nullptr) { + grpc_error* service_config_error = GRPC_ERROR_NONE; RefCountedPtr service_config = - ServiceConfig::Create(service_config_json, nullptr); + ServiceConfig::Create(service_config_json, &service_config_error); + // service_config_error is currently unused. + GRPC_ERROR_UNREF(service_config_error); if (service_config != nullptr) { HealthCheckParams params; service_config->ParseGlobalParams(HealthCheckParams::Parse, ¶ms); diff --git a/src/core/ext/filters/message_size/message_size_filter.cc b/src/core/ext/filters/message_size/message_size_filter.cc index 8c2a32cc618..4d120c0eb76 100644 --- a/src/core/ext/filters/message_size/message_size_filter.cc +++ b/src/core/ext/filters/message_size/message_size_filter.cc @@ -319,8 +319,11 @@ static grpc_error* init_channel_elem(grpc_channel_element* elem, grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVICE_CONFIG); const char* service_config_str = grpc_channel_arg_get_string(channel_arg); if (service_config_str != nullptr) { + grpc_error* service_config_error = GRPC_ERROR_NONE; grpc_core::RefCountedPtr service_config = - grpc_core::ServiceConfig::Create(service_config_str, nullptr); + grpc_core::ServiceConfig::Create(service_config_str, + &service_config_error); + GRPC_ERROR_UNREF(service_config_error); if (service_config != nullptr) { chand->method_limit_table = service_config->CreateMethodConfigTable( grpc_core::MessageSizeLimits::CreateFromJson); diff --git a/test/core/client_channel/service_config_test.cc b/test/core/client_channel/service_config_test.cc index d8cb3532cb5..50e99ccfc10 100644 --- a/test/core/client_channel/service_config_test.cc +++ b/test/core/client_channel/service_config_test.cc @@ -46,14 +46,14 @@ class TestParser1 : public ServiceConfigParser { field = field->next) { if (strcmp(field->key, "global_param") == 0) { if (field->type != GRPC_JSON_NUMBER) { - *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "global_param value type should be a number"); + *error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING(InvalidTypeErrorMessage()); return nullptr; } int value = gpr_parse_nonnegative_int(field->value); if (value == -1) { - *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "global_param value type should be non-negative"); + *error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING(InvalidValueErrorMessage()); return nullptr; } return UniquePtr( @@ -62,6 +62,14 @@ class TestParser1 : public ServiceConfigParser { } return nullptr; } + + static const char* InvalidTypeErrorMessage() { + return "global_param value type should be a number"; + } + + static const char* InvalidValueErrorMessage() { + return "global_param value type should be non-negative"; + } }; class TestParser2 : public ServiceConfigParser { @@ -76,14 +84,14 @@ class TestParser2 : public ServiceConfigParser { } if (strcmp(field->key, "method_param") == 0) { if (field->type != GRPC_JSON_NUMBER) { - *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "method_param value type should be a number"); + *error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING(InvalidTypeErrorMessage()); return nullptr; } int value = gpr_parse_nonnegative_int(field->value); if (value == -1) { - *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "method_param value type should be non-negative"); + *error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING(InvalidValueErrorMessage()); return nullptr; } return UniquePtr( @@ -92,6 +100,14 @@ class TestParser2 : public ServiceConfigParser { } return nullptr; } + + static const char* InvalidTypeErrorMessage() { + return "method_param value type should be a number"; + } + + static const char* InvalidValueErrorMessage() { + return "method_param value type should be non-negative"; + } }; class ServiceConfigTest : public ::testing::Test { @@ -110,7 +126,10 @@ TEST_F(ServiceConfigTest, ErrorCheck1) { const char* test_json = ""; grpc_error* error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(test_json, &error); + gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); EXPECT_TRUE(error != GRPC_ERROR_NONE); + EXPECT_TRUE(strstr(grpc_error_string(error), + "failed to parse JSON for service config") != nullptr); } TEST_F(ServiceConfigTest, BasicTest1) { @@ -126,6 +145,7 @@ TEST_F(ServiceConfigTest, ErrorNoNames) { auto svc_cfg = ServiceConfig::Create(test_json, &error); gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); EXPECT_TRUE(error != GRPC_ERROR_NONE); + EXPECT_TRUE(strstr(grpc_error_string(error), "No names found") != nullptr); } TEST_F(ServiceConfigTest, ErrorNoNamesWithMultipleMethodConfigs) { @@ -135,6 +155,7 @@ TEST_F(ServiceConfigTest, ErrorNoNamesWithMultipleMethodConfigs) { auto svc_cfg = ServiceConfig::Create(test_json, &error); gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); EXPECT_TRUE(error != GRPC_ERROR_NONE); + EXPECT_TRUE(strstr(grpc_error_string(error), "No names found") != nullptr); } TEST_F(ServiceConfigTest, ValidMethodConfig) { @@ -171,6 +192,8 @@ TEST_F(ServiceConfigTest, Parser1ErrorInvalidType) { auto svc_cfg = ServiceConfig::Create(test_json, &error); gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); EXPECT_TRUE(error != GRPC_ERROR_NONE); + EXPECT_TRUE(strstr(grpc_error_string(error), + TestParser1::InvalidTypeErrorMessage()) != nullptr); } TEST_F(ServiceConfigTest, Parser1ErrorInvalidValue) { @@ -179,6 +202,8 @@ TEST_F(ServiceConfigTest, Parser1ErrorInvalidValue) { auto svc_cfg = ServiceConfig::Create(test_json, &error); gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); EXPECT_TRUE(error != GRPC_ERROR_NONE); + EXPECT_TRUE(strstr(grpc_error_string(error), + TestParser1::InvalidValueErrorMessage()) != nullptr); } TEST_F(ServiceConfigTest, Parser2BasicTest) { @@ -188,6 +213,12 @@ TEST_F(ServiceConfigTest, Parser2BasicTest) { grpc_error* error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(test_json, &error); EXPECT_TRUE(error == GRPC_ERROR_NONE); + const auto* const* vector_ptr = svc_cfg->GetMethodServiceConfigObjectsVector( + grpc_slice_from_static_string("/TestServ/TestMethod")); + ASSERT_TRUE(vector_ptr != nullptr); + const auto* vector = *vector_ptr; + auto parsed_object = ((*vector)[1]).get(); + EXPECT_TRUE(static_cast(parsed_object)->value() == 5); } TEST_F(ServiceConfigTest, Parser2ErrorInvalidType) { @@ -197,6 +228,8 @@ TEST_F(ServiceConfigTest, Parser2ErrorInvalidType) { grpc_error* error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(test_json, &error); EXPECT_TRUE(error != GRPC_ERROR_NONE); + EXPECT_TRUE(strstr(grpc_error_string(error), + TestParser2::InvalidTypeErrorMessage()) != nullptr); } TEST_F(ServiceConfigTest, Parser2ErrorInvalidValue) { @@ -206,6 +239,8 @@ TEST_F(ServiceConfigTest, Parser2ErrorInvalidValue) { grpc_error* error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(test_json, &error); EXPECT_TRUE(error != GRPC_ERROR_NONE); + EXPECT_TRUE(strstr(grpc_error_string(error), + TestParser2::InvalidValueErrorMessage()) != nullptr); } } // namespace testing diff --git a/test/cpp/end2end/grpclb_end2end_test.cc b/test/cpp/end2end/grpclb_end2end_test.cc index 7c6432379a6..096482543ca 100644 --- a/test/cpp/end2end/grpclb_end2end_test.cc +++ b/test/cpp/end2end/grpclb_end2end_test.cc @@ -542,8 +542,10 @@ class GrpclbEnd2endTest : public ::testing::Test { grpc_core::Resolver::Result result; result.addresses = CreateLbAddressesFromAddressDataList(address_data); if (service_config_json != nullptr) { + grpc_error* error = GRPC_ERROR_NONE; result.service_config = - grpc_core::ServiceConfig::Create(service_config_json); + grpc_core::ServiceConfig::Create(service_config_json, &error); + GRPC_ERROR_UNREF(error); } response_generator_->SetResponse(std::move(result)); } diff --git a/test/cpp/end2end/xds_end2end_test.cc b/test/cpp/end2end/xds_end2end_test.cc index 61e759c61b5..fc343939041 100644 --- a/test/cpp/end2end/xds_end2end_test.cc +++ b/test/cpp/end2end/xds_end2end_test.cc @@ -524,8 +524,10 @@ class XdsEnd2endTest : public ::testing::Test { grpc_core::Resolver::Result result; result.addresses = CreateLbAddressesFromPortList(ports); if (service_config_json != nullptr) { + grpc_error* error = GRPC_ERROR_NONE; result.service_config = grpc_core::ServiceConfig::Create(service_config_json); + GRPC_ERROR_UNREF(error); } grpc_arg arg = grpc_core::FakeResolverResponseGenerator::MakeChannelArg( lb_channel_response_generator == nullptr @@ -555,8 +557,10 @@ class XdsEnd2endTest : public ::testing::Test { grpc_core::Resolver::Result result; result.addresses = CreateLbAddressesFromPortList(ports); if (service_config_json != nullptr) { + grpc_error* error = GRPC_ERROR_NONE; result.service_config = grpc_core::ServiceConfig::Create(service_config_json); + GRPC_ERROR_UNREF(error); } if (lb_channel_response_generator == nullptr) { lb_channel_response_generator = lb_channel_response_generator_.get(); From 8eeb429db026e13514bd6dd6f98297c14cd97d4c Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 5 Apr 2019 13:44:41 -0700 Subject: [PATCH 205/242] Missing argument --- test/cpp/end2end/xds_end2end_test.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/cpp/end2end/xds_end2end_test.cc b/test/cpp/end2end/xds_end2end_test.cc index fc343939041..e4c5d444c12 100644 --- a/test/cpp/end2end/xds_end2end_test.cc +++ b/test/cpp/end2end/xds_end2end_test.cc @@ -526,7 +526,7 @@ class XdsEnd2endTest : public ::testing::Test { if (service_config_json != nullptr) { grpc_error* error = GRPC_ERROR_NONE; result.service_config = - grpc_core::ServiceConfig::Create(service_config_json); + grpc_core::ServiceConfig::Create(service_config_json, &error); GRPC_ERROR_UNREF(error); } grpc_arg arg = grpc_core::FakeResolverResponseGenerator::MakeChannelArg( @@ -559,7 +559,7 @@ class XdsEnd2endTest : public ::testing::Test { if (service_config_json != nullptr) { grpc_error* error = GRPC_ERROR_NONE; result.service_config = - grpc_core::ServiceConfig::Create(service_config_json); + grpc_core::ServiceConfig::Create(service_config_json, &error); GRPC_ERROR_UNREF(error); } if (lb_channel_response_generator == nullptr) { From 896a59c6feb36cf38fec24d304c667ad2d44b470 Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Fri, 5 Apr 2019 15:26:10 -0700 Subject: [PATCH 206/242] Change third_party/protoc-gen-validate repo path --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 06f1394df65..f4690a2687f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -50,7 +50,7 @@ url = https://github.com/googleapis/googleapis.git [submodule "third_party/protoc-gen-validate"] path = third_party/protoc-gen-validate - url = https://github.com/lyft/protoc-gen-validate.git + url = https://github.com/envoyproxy/protoc-gen-validate.git [submodule "third_party/upb"] path = third_party/upb url = https://github.com/google/upb.git From b7f32af1d07b14306ff51af31d1995741097c05f Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 5 Apr 2019 19:17:29 -0700 Subject: [PATCH 207/242] Fix scoping for service config errors --- .../filters/client_channel/service_config.cc | 146 ++++++++++++------ .../filters/client_channel/service_config.h | 19 +-- .../client_channel/service_config_test.cc | 138 ++++++++++++++--- 3 files changed, 221 insertions(+), 82 deletions(-) diff --git a/src/core/ext/filters/client_channel/service_config.cc b/src/core/ext/filters/client_channel/service_config.cc index 360b4cd81bf..64560175804 100644 --- a/src/core/ext/filters/client_channel/service_config.cc +++ b/src/core/ext/filters/client_channel/service_config.cc @@ -33,7 +33,31 @@ namespace grpc_core { -ServiceConfig::ServiceConfigParserList* ServiceConfig::registered_parsers_; +namespace { +typedef InlinedVector, + ServiceConfig::kNumPreallocatedParsers> + ServiceConfigParserList; +ServiceConfigParserList* registered_parsers; + +// Consumes all the errors in the vector and forms a referencing error from +// them. If the vector is empty, return GRPC_ERROR_NONE. +template +grpc_error* CreateErrorFromVector(const char* desc, + InlinedVector* error_list) { + grpc_error* error = GRPC_ERROR_NONE; + if (error_list->size() != 0) { + error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + desc, error_list->data(), error_list->size()); + // Remove refs to all errors in error_list. + for (size_t i = 0; i < error_list->size(); i++) { + GRPC_ERROR_UNREF((*error_list)[i]); + } + error_list->clear(); + } + return error; +} +} // namespace + RefCountedPtr ServiceConfig::Create(const char* json, grpc_error** error) { UniquePtr service_config_json(gpr_strdup(json)); @@ -62,22 +86,38 @@ ServiceConfig::ServiceConfig(UniquePtr service_config_json, "Malformed service Config JSON object"); return; } - *error = ParseGlobalParams(json_tree); - *error = grpc_error_add_child(*error, ParsePerMethodParams(json_tree)); + grpc_error* error_list[2]; + int error_count = 0; + grpc_error* global_error = ParseGlobalParams(json_tree); + grpc_error* local_error = ParsePerMethodParams(json_tree); + if (global_error != GRPC_ERROR_NONE) { + error_list[error_count++] = global_error; + } + if (local_error != GRPC_ERROR_NONE) { + error_list[error_count++] = local_error; + } + if (error_count > 0) { + *error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Service config parsing error", error_list, error_count); + GRPC_ERROR_UNREF(global_error); + GRPC_ERROR_UNREF(local_error); + } } grpc_error* ServiceConfig::ParseGlobalParams(const grpc_json* json_tree) { GPR_DEBUG_ASSERT(json_tree_->type == GRPC_JSON_OBJECT); GPR_DEBUG_ASSERT(json_tree_->key == nullptr); - grpc_error* error = GRPC_ERROR_NONE; - for (size_t i = 0; i < registered_parsers_->size(); i++) { + InlinedVector error_list; + for (size_t i = 0; i < registered_parsers->size(); i++) { grpc_error* parser_error = GRPC_ERROR_NONE; auto parsed_obj = - (*registered_parsers_)[i]->ParseGlobalParams(json_tree, &parser_error); - error = grpc_error_add_child(error, parser_error); + (*registered_parsers)[i]->ParseGlobalParams(json_tree, &parser_error); + if (parser_error != GRPC_ERROR_NONE) { + error_list.push_back(parser_error); + } parsed_global_service_config_objects_.push_back(std::move(parsed_obj)); } - return error; + return CreateErrorFromVector("Global Params", &error_list); } grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( @@ -85,12 +125,14 @@ grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( SliceHashTable::Entry* entries, size_t* idx) { auto objs_vector = MakeUnique(); - grpc_error* error = GRPC_ERROR_NONE; - for (size_t i = 0; i < registered_parsers_->size(); i++) { + InlinedVector error_list; + for (size_t i = 0; i < registered_parsers->size(); i++) { grpc_error* parser_error = GRPC_ERROR_NONE; auto parsed_obj = - (*registered_parsers_)[i]->ParsePerMethodParams(json, &error); - error = grpc_error_add_child(error, parser_error); + (*registered_parsers)[i]->ParsePerMethodParams(json, &parser_error); + if (parser_error != GRPC_ERROR_NONE) { + error_list.push_back(parser_error); + } objs_vector->push_back(std::move(parsed_obj)); } const auto* vector_ptr = objs_vector.get(); @@ -101,16 +143,15 @@ grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( if (child->key == nullptr) continue; if (strcmp(child->key, "name") == 0) { if (child->type != GRPC_JSON_ARRAY) { - error = grpc_error_add_child(error, - GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:name error:not of type Array")); + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:name error:not of type Array")); goto wrap_error; } for (grpc_json* name = child->child; name != nullptr; name = name->next) { grpc_error* parse_error = GRPC_ERROR_NONE; UniquePtr path = ParseJsonMethodName(name, &parse_error); if (path == nullptr) { - error = grpc_error_add_child(error, parse_error); + error_list.push_back(parse_error); } else { GPR_DEBUG_ASSERT(parse_error == GRPC_ERROR_NONE); } @@ -119,21 +160,17 @@ grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( } } if (paths.size() == 0) { - error = grpc_error_add_child( - error, GRPC_ERROR_CREATE_FROM_STATIC_STRING("No names specified")); + error_list.push_back( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("No names specified")); } // Add entry for each path. for (size_t i = 0; i < paths.size(); ++i) { entries[*idx].key = grpc_slice_from_copied_string(paths[i].get()); - entries[*idx].value = vector_ptr; // Takes a new ref. + entries[*idx].value = vector_ptr; ++*idx; } wrap_error: - if (error != GRPC_ERROR_NONE) { - error = grpc_error_add_child( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("field:methodConfig"), error); - } - return error; + return CreateErrorFromVector("methodConfig", &error_list); } grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) { @@ -141,13 +178,12 @@ grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) { GPR_DEBUG_ASSERT(json_tree_->key == nullptr); SliceHashTable::Entry* entries = nullptr; size_t num_entries = 0; - grpc_error* error = GRPC_ERROR_NONE; + InlinedVector error_list; for (grpc_json* field = json_tree->child; field != nullptr; field = field->next) { if (field->key == nullptr) { - error = - grpc_error_add_child(error, GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "error:Illegal key value - NULL")); + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "error:Illegal key value - NULL")); continue; } if (strcmp(field->key, "methodConfig") == 0) { @@ -155,17 +191,15 @@ grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) { GPR_ASSERT(false); } if (field->type != GRPC_JSON_ARRAY) { - return grpc_error_add_child( - error, GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:methodConfig error:not of type Array")); + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:methodConfig error:not of type Array")); } for (grpc_json* method = field->child; method != nullptr; method = method->next) { int count = CountNamesInMethodConfig(method); if (count <= 0) { - error = grpc_error_add_child( - error, GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:methodConfig error:No names found")); + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:methodConfig error:No names found")); } num_entries += static_cast(count); } @@ -176,9 +210,11 @@ grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) { size_t idx = 0; for (grpc_json* method = field->child; method != nullptr; method = method->next) { - error = grpc_error_add_child( - error, ParseJsonMethodConfigToServiceConfigObjectsTable( - method, entries, &idx)); + grpc_error* error = ParseJsonMethodConfigToServiceConfigObjectsTable( + method, entries, &idx); + if (error != GRPC_ERROR_NONE) { + error_list.push_back(error); + } } GPR_DEBUG_ASSERT(num_entries == idx); break; @@ -190,7 +226,7 @@ grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) { num_entries, entries, nullptr); gpr_free(entries); } - return error; + return CreateErrorFromVector("Method Params", &error_list); } ServiceConfig::~ServiceConfig() { grpc_json_destroy(json_tree_); } @@ -230,50 +266,51 @@ UniquePtr ServiceConfig::ParseJsonMethodName(grpc_json* json, grpc_error** error) { if (json->type != GRPC_JSON_OBJECT) { *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Field name should be of type object"); + "field:name error:type is not object"); return nullptr; } const char* service_name = nullptr; const char* method_name = nullptr; for (grpc_json* child = json->child; child != nullptr; child = child->next) { if (child->key == nullptr) { - *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child entry with no key"); + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:name error:Child entry with no key"); return nullptr; } if (child->type != GRPC_JSON_STRING) { *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Child entry should of type string"); + "field:name error:Child entry not of type string"); return nullptr; } if (strcmp(child->key, "service") == 0) { if (service_name != nullptr) { *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:service error:Multiple entries"); + "field:name error: field:service error:Multiple entries"); return nullptr; // Duplicate. } if (child->value == nullptr) { *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:service error:empty value"); + "field:name error: field:service error:empty value"); return nullptr; } service_name = child->value; } else if (strcmp(child->key, "method") == 0) { if (method_name != nullptr) { *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:method error:multiple entries"); + "field:name error: field:method error:multiple entries"); return nullptr; // Duplicate. } if (child->value == nullptr) { *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:method error:empty value"); + "field:name error: field:method error:empty value"); return nullptr; } method_name = child->value; } } if (service_name == nullptr) { - *error = - GRPC_ERROR_CREATE_FROM_STATIC_STRING("field:service error:not found"); + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:name error: field:service error:not found"); return nullptr; // Required field. } char* path; @@ -305,4 +342,19 @@ ServiceConfig::GetMethodServiceConfigObjectsVector(const grpc_slice& path) { return value; } +int ServiceConfig::RegisterParser(UniquePtr parser) { + registered_parsers->push_back(std::move(parser)); + return registered_parsers->size() - 1; +} + +void ServiceConfig::Init() { + GPR_ASSERT(registered_parsers == nullptr); + registered_parsers = New(); +} + +void ServiceConfig::Shutdown() { + Delete(registered_parsers); + registered_parsers = nullptr; +} + } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/service_config.h b/src/core/ext/filters/client_channel/service_config.h index 9738cc82d30..f205fa2f243 100644 --- a/src/core/ext/filters/client_channel/service_config.h +++ b/src/core/ext/filters/client_channel/service_config.h @@ -150,24 +150,13 @@ class ServiceConfig : public RefCounted { /// registered parser. Each parser is responsible for reading the service /// config json and returning a parsed object. This parsed object can later be /// retrieved using the same index that was returned at registration time. - static int RegisterParser(UniquePtr parser) { - registered_parsers_->push_back(std::move(parser)); - return registered_parsers_->size() - 1; - } + static int RegisterParser(UniquePtr parser); - static void Init() { - GPR_ASSERT(registered_parsers_ == nullptr); - registered_parsers_ = New(); - } + static void Init(); - static void Shutdown() { - Delete(registered_parsers_); - registered_parsers_ = nullptr; - } + static void Shutdown(); private: - typedef InlinedVector, kNumPreallocatedParsers> - ServiceConfigParserList; // So New() can call our private ctor. template friend T* New(Args&&... args); @@ -202,8 +191,6 @@ class ServiceConfig : public RefCounted { SliceHashTable::Entry* entries, size_t* idx); - static ServiceConfigParserList* registered_parsers_; - UniquePtr service_config_json_; UniquePtr json_string_; // Underlying storage for json_tree. grpc_json* json_tree_; diff --git a/test/core/client_channel/service_config_test.cc b/test/core/client_channel/service_config_test.cc index 50e99ccfc10..f364da9cf89 100644 --- a/test/core/client_channel/service_config_test.cc +++ b/test/core/client_channel/service_config_test.cc @@ -16,6 +16,8 @@ * */ +#include + #include #include @@ -110,6 +112,28 @@ class TestParser2 : public ServiceConfigParser { } }; +// This parser always adds errors +class ErrorParser : public ServiceConfigParser { + public: + UniquePtr ParsePerMethodParams( + const grpc_json* json, grpc_error** error) override { + GPR_DEBUG_ASSERT(error != nullptr); + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(MethodError()); + return nullptr; + } + + UniquePtr ParseGlobalParams( + const grpc_json* json, grpc_error** error) override { + GPR_DEBUG_ASSERT(error != nullptr); + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(GlobalError()); + return nullptr; + } + + static const char* MethodError() { return "ErrorParser : methodError"; } + + static const char* GlobalError() { return "ErrorParser : globalError"; } +}; + class ServiceConfigTest : public ::testing::Test { protected: void SetUp() override { @@ -127,7 +151,7 @@ TEST_F(ServiceConfigTest, ErrorCheck1) { grpc_error* error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(test_json, &error); gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); - EXPECT_TRUE(error != GRPC_ERROR_NONE); + ASSERT_TRUE(error != GRPC_ERROR_NONE); EXPECT_TRUE(strstr(grpc_error_string(error), "failed to parse JSON for service config") != nullptr); } @@ -144,7 +168,7 @@ TEST_F(ServiceConfigTest, ErrorNoNames) { grpc_error* error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(test_json, &error); gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); - EXPECT_TRUE(error != GRPC_ERROR_NONE); + ASSERT_TRUE(error != GRPC_ERROR_NONE); EXPECT_TRUE(strstr(grpc_error_string(error), "No names found") != nullptr); } @@ -154,7 +178,7 @@ TEST_F(ServiceConfigTest, ErrorNoNamesWithMultipleMethodConfigs) { grpc_error* error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(test_json, &error); gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); - EXPECT_TRUE(error != GRPC_ERROR_NONE); + ASSERT_TRUE(error != GRPC_ERROR_NONE); EXPECT_TRUE(strstr(grpc_error_string(error), "No names found") != nullptr); } @@ -170,7 +194,7 @@ TEST_F(ServiceConfigTest, Parser1BasicTest1) { const char* test_json = "{\"global_param\":5}"; grpc_error* error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(test_json, &error); - EXPECT_TRUE(error == GRPC_ERROR_NONE); + ASSERT_TRUE(error == GRPC_ERROR_NONE); EXPECT_TRUE((static_cast( svc_cfg->GetParsedGlobalServiceConfigObject(0))) ->value() == 5); @@ -180,7 +204,7 @@ TEST_F(ServiceConfigTest, Parser1BasicTest2) { const char* test_json = "{\"global_param\":1000}"; grpc_error* error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(test_json, &error); - EXPECT_TRUE(error == GRPC_ERROR_NONE); + ASSERT_TRUE(error == GRPC_ERROR_NONE); EXPECT_TRUE((static_cast( svc_cfg->GetParsedGlobalServiceConfigObject(0))) ->value() == 1000); @@ -191,9 +215,14 @@ TEST_F(ServiceConfigTest, Parser1ErrorInvalidType) { grpc_error* error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(test_json, &error); gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); - EXPECT_TRUE(error != GRPC_ERROR_NONE); - EXPECT_TRUE(strstr(grpc_error_string(error), - TestParser1::InvalidTypeErrorMessage()) != nullptr); + ASSERT_TRUE(error != GRPC_ERROR_NONE); + std::regex e(std::string("(Service config parsing " + "error)(.*)(referenced_errors)(.*)(Global " + "Params)(.*)(referenced_errors)()(.*)") + + TestParser1::InvalidTypeErrorMessage()); + std::smatch match; + std::string s(grpc_error_string(error)); + EXPECT_TRUE(std::regex_search(s, match, e)); } TEST_F(ServiceConfigTest, Parser1ErrorInvalidValue) { @@ -201,9 +230,14 @@ TEST_F(ServiceConfigTest, Parser1ErrorInvalidValue) { grpc_error* error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(test_json, &error); gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); - EXPECT_TRUE(error != GRPC_ERROR_NONE); - EXPECT_TRUE(strstr(grpc_error_string(error), - TestParser1::InvalidValueErrorMessage()) != nullptr); + ASSERT_TRUE(error != GRPC_ERROR_NONE); + std::regex e(std::string("(Service config parsing " + "error)(.*)(referenced_errors)(.*)(Global " + "Params)(.*)(referenced_errors)()(.*)") + + TestParser1::InvalidValueErrorMessage()); + std::smatch match; + std::string s(grpc_error_string(error)); + EXPECT_TRUE(std::regex_search(s, match, e)); } TEST_F(ServiceConfigTest, Parser2BasicTest) { @@ -212,10 +246,10 @@ TEST_F(ServiceConfigTest, Parser2BasicTest) { "\"method_param\":5}]}"; grpc_error* error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(test_json, &error); - EXPECT_TRUE(error == GRPC_ERROR_NONE); + ASSERT_TRUE(error == GRPC_ERROR_NONE); const auto* const* vector_ptr = svc_cfg->GetMethodServiceConfigObjectsVector( grpc_slice_from_static_string("/TestServ/TestMethod")); - ASSERT_TRUE(vector_ptr != nullptr); + EXPECT_TRUE(vector_ptr != nullptr); const auto* vector = *vector_ptr; auto parsed_object = ((*vector)[1]).get(); EXPECT_TRUE(static_cast(parsed_object)->value() == 5); @@ -227,9 +261,16 @@ TEST_F(ServiceConfigTest, Parser2ErrorInvalidType) { "\"method_param\":\"5\"}]}"; grpc_error* error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(test_json, &error); - EXPECT_TRUE(error != GRPC_ERROR_NONE); - EXPECT_TRUE(strstr(grpc_error_string(error), - TestParser2::InvalidTypeErrorMessage()) != nullptr); + ASSERT_TRUE(error != GRPC_ERROR_NONE); + gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + std::regex e(std::string("(Service config parsing " + "error)(.*)(referenced_errors\":\\[)(.*)(Method " + "Params)(.*)(referenced_errors)()(.*)(methodConfig)(" + ".*)(referenced_errors)(.*)") + + TestParser2::InvalidTypeErrorMessage()); + std::smatch match; + std::string s(grpc_error_string(error)); + EXPECT_TRUE(std::regex_search(s, match, e)); } TEST_F(ServiceConfigTest, Parser2ErrorInvalidValue) { @@ -238,9 +279,68 @@ TEST_F(ServiceConfigTest, Parser2ErrorInvalidValue) { "\"method_param\":-5}]}"; grpc_error* error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(test_json, &error); - EXPECT_TRUE(error != GRPC_ERROR_NONE); - EXPECT_TRUE(strstr(grpc_error_string(error), - TestParser2::InvalidValueErrorMessage()) != nullptr); + ASSERT_TRUE(error != GRPC_ERROR_NONE); + gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + std::regex e(std::string("(Service config parsing " + "error)(.*)(referenced_errors\":\\[)(.*)(Method " + "Params)(.*)(referenced_errors)()(.*)(methodConfig)(" + ".*)(referenced_errors)(.*)") + + TestParser2::InvalidValueErrorMessage()); + std::smatch match; + std::string s(grpc_error_string(error)); + EXPECT_TRUE(std::regex_search(s, match, e)); +} + +// Test parsing with ErrorParsers which always add errors +class ErroredParsersScopingTest : public ::testing::Test { + protected: + void SetUp() override { + ServiceConfig::Shutdown(); + ServiceConfig::Init(); + EXPECT_TRUE(ServiceConfig::RegisterParser( + UniquePtr(New())) == 0); + EXPECT_TRUE(ServiceConfig::RegisterParser( + UniquePtr(New())) == 1); + } +}; + +TEST_F(ErroredParsersScopingTest, GlobalParams) { + const char* test_json = "{}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + ASSERT_TRUE(error != GRPC_ERROR_NONE); + gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + std::regex e(std::string("(Service config parsing " + "error)(.*)(referenced_errors\":\\[)(.*)(Global " + "Params)(.*)(referenced_errors)()(.*)") + + ErrorParser::GlobalError() + std::string("(.*)") + + ErrorParser::GlobalError()); + std::smatch match; + std::string s(grpc_error_string(error)); + EXPECT_TRUE(std::regex_search(s, match, e)); +} + +TEST_F(ErroredParsersScopingTest, MethodParams) { + const char* test_json = "{\"methodConfig\": [{}]}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + ASSERT_TRUE(error != GRPC_ERROR_NONE); + gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + std::regex e( + std::string("(Service config parsing " + "error)(.*)(referenced_errors\":\\[)(.*)(Global " + "Params)(.*)(referenced_errors)()(.*)") + + ErrorParser::GlobalError() + std::string("(.*)") + + ErrorParser::GlobalError() + + std::string("(.*)(Method " + "Params)(.*)(referenced_errors)(.*)(field:methodConfig " + "error:No names " + "found)(.*)(methodConfig)(.*)(referenced_errors)(.*)") + + ErrorParser::MethodError() + std::string("(.*)") + + ErrorParser::MethodError() + std::string("(.*)(No names specified)")); + std::smatch match; + std::string s(grpc_error_string(error)); + EXPECT_TRUE(std::regex_search(s, match, e)); } } // namespace testing From 9365b606b08a8fb4d04fb1d5343d33973113867a Mon Sep 17 00:00:00 2001 From: Tyler Rockwood Date: Fri, 5 Apr 2019 21:35:16 -0500 Subject: [PATCH 208/242] Expose root_certifications in BUILD file I'd like to be able to grab the root_certificates and use them in my build process to bundle them as part of my package I ship to prod, and this prevents me from having two repos for gRPC, one having a custom BUILD file that allows me to grab the roots.pem file, which is what I do now to add this into our build process. --- BUILD | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/BUILD b/BUILD index 562a71c2f29..9e7f1d9b4ec 100644 --- a/BUILD +++ b/BUILD @@ -2454,3 +2454,11 @@ grpc_cc_library( ) grpc_generate_one_off_targets() + +filegroup( + name = "root_certificates", + srcs = [ + "etc/roots.pem", + ], + visibility = ["//visibility:public"], +) From cee3292cdf8464bb98e5113f74d6a4073c36489e Mon Sep 17 00:00:00 2001 From: Hope Casey-Allen Date: Mon, 8 Apr 2019 09:11:04 -0700 Subject: [PATCH 209/242] Update callback API documentation --- include/grpcpp/impl/codegen/server_callback.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/grpcpp/impl/codegen/server_callback.h b/include/grpcpp/impl/codegen/server_callback.h index 87edea84f41..9afddfba09f 100644 --- a/include/grpcpp/impl/codegen/server_callback.h +++ b/include/grpcpp/impl/codegen/server_callback.h @@ -253,7 +253,9 @@ class ServerBidiReactor : public internal::ServerReactor { void Finish(Status s) { stream_->Finish(std::move(s)); } /// Notify the application that a streaming RPC has started and that it is now - /// ok to call any operation initation method. + /// ok to call any operation initiation method. An RPC is considered started + /// after the server has received all initial metadata from the client, which + /// is a result of the client calling StartCall(). /// /// \param[in] context The context object now associated with this RPC virtual void OnStarted(ServerContext* context) {} From b86e70592e25e04d27f52e697cd29c0bf4a02972 Mon Sep 17 00:00:00 2001 From: Hope Casey-Allen Date: Mon, 8 Apr 2019 10:13:17 -0700 Subject: [PATCH 210/242] Format --- include/grpcpp/impl/codegen/server_callback.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/grpcpp/impl/codegen/server_callback.h b/include/grpcpp/impl/codegen/server_callback.h index 9afddfba09f..4c6b189214e 100644 --- a/include/grpcpp/impl/codegen/server_callback.h +++ b/include/grpcpp/impl/codegen/server_callback.h @@ -254,7 +254,7 @@ class ServerBidiReactor : public internal::ServerReactor { /// Notify the application that a streaming RPC has started and that it is now /// ok to call any operation initiation method. An RPC is considered started - /// after the server has received all initial metadata from the client, which + /// after the server has received all initial metadata from the client, which /// is a result of the client calling StartCall(). /// /// \param[in] context The context object now associated with this RPC From 8b10d5faa753920b52241bff28e9bc03c0242cfc Mon Sep 17 00:00:00 2001 From: Prashant Jaikumar Date: Mon, 11 Mar 2019 12:00:00 -0700 Subject: [PATCH 211/242] Fix GrpcIosTestUITests flake and add some more testcases. Added testcases for switching between apps, and turning wifi on/off. Also fixed test flakes where UI button presses weren't working. --- .../xcschemes/GrpcIosTest.xcscheme | 101 ++++++++ .../GrpcIosTestUITests/GrpcIosTestUITests.m | 239 +++++++++++++++--- src/objective-c/manual_tests/Main.storyboard | 55 +++- src/objective-c/manual_tests/ViewController.m | 60 ++++- 4 files changed, 391 insertions(+), 64 deletions(-) create mode 100644 src/objective-c/manual_tests/GrpcIosTest.xcodeproj/xcshareddata/xcschemes/GrpcIosTest.xcscheme diff --git a/src/objective-c/manual_tests/GrpcIosTest.xcodeproj/xcshareddata/xcschemes/GrpcIosTest.xcscheme b/src/objective-c/manual_tests/GrpcIosTest.xcodeproj/xcshareddata/xcschemes/GrpcIosTest.xcscheme new file mode 100644 index 00000000000..b9fb9d4d129 --- /dev/null +++ b/src/objective-c/manual_tests/GrpcIosTest.xcodeproj/xcshareddata/xcschemes/GrpcIosTest.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/objective-c/manual_tests/GrpcIosTestUITests/GrpcIosTestUITests.m b/src/objective-c/manual_tests/GrpcIosTestUITests/GrpcIosTestUITests.m index b0a929e689d..b5e19657ce7 100644 --- a/src/objective-c/manual_tests/GrpcIosTestUITests/GrpcIosTestUITests.m +++ b/src/objective-c/manual_tests/GrpcIosTestUITests/GrpcIosTestUITests.m @@ -19,6 +19,7 @@ #import NSTimeInterval const kWaitTime = 30; +int const kNumIterations = 1; @interface GrpcIosTestUITests : XCTestCase @end @@ -32,16 +33,27 @@ NSTimeInterval const kWaitTime = 30; self.continueAfterFailure = NO; [[[XCUIApplication alloc] init] launch]; testApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"io.grpc.GrpcIosTest"]; + [testApp activate]; + // Reset RPC counter + [self pressButton:@"Reset counter"]; + settingsApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"com.apple.Preferences"]; [settingsApp activate]; + [NSThread sleepForTimeInterval:1]; // Go back to the first page of Settings. XCUIElement *backButton = settingsApp.navigationBars.buttons.firstMatch; - while (backButton.exists) { + while (backButton.exists && backButton.isHittable) { + NSLog(@"Tapping back button"); [backButton tap]; } XCTAssert([settingsApp.navigationBars[@"Settings"] waitForExistenceWithTimeout:kWaitTime]); + NSLog(@"Turning off airplane mode"); // Turn off airplane mode [self setAirplaneMode:NO]; + + // Turn on wifi + NSLog(@"Turning on wifi"); + [self setWifi:YES]; } - (void)tearDown { @@ -49,14 +61,25 @@ NSTimeInterval const kWaitTime = 30; - (void)doUnaryCall { [testApp activate]; - [testApp.buttons[@"Unary call"] tap]; + [self pressButton:@"Unary call"]; } -- (void)doStreamingCall { +- (void)do10UnaryCalls { [testApp activate]; - [testApp.buttons[@"Start streaming call"] tap]; - [testApp.buttons[@"Send Message"] tap]; - [testApp.buttons[@"Stop streaming call"] tap]; + [self pressButton:@"10 Unary calls"]; +} + +- (void)pressButton:(NSString *)name { + // Wait for button to be visible + while (![testApp.buttons[name] exists] || ![testApp.buttons[name] isHittable]) { + [NSThread sleepForTimeInterval:1]; + } + // Wait until all events in run loop have been processed + while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, true) == kCFRunLoopRunHandledSource) + ; + + NSLog(@"Pressing button: %@", name); + [testApp.buttons[name] tap]; } - (void)expectCallSuccess { @@ -71,41 +94,81 @@ NSTimeInterval const kWaitTime = 30; [settingsApp activate]; XCUIElement *mySwitch = settingsApp.tables.element.cells.switches[@"Airplane Mode"]; BOOL from = [(NSString *)mySwitch.value boolValue]; + NSLog(@"Setting airplane from: %d to: %d", from, to); if (from != to) { [mySwitch tap]; - // wait for gRPC to detect the change - sleep(10); + // wait for network change to finish + [NSThread sleepForTimeInterval:5]; } XCTAssert([(NSString *)mySwitch.value boolValue] == to); } +- (void)setWifi:(BOOL)to { + [settingsApp activate]; + [settingsApp.tables.element.cells.staticTexts[@"Wi-Fi"] tap]; + XCUIElement *wifiSwitch = settingsApp.tables.cells.switches[@"Wi-Fi"]; + BOOL from = [(NSString *)wifiSwitch.value boolValue]; + NSLog(@"Setting wifi from: %d to: %d", from, to); + if (from != to) { + [wifiSwitch tap]; + // wait for wifi networks to be detected + [NSThread sleepForTimeInterval:10]; + } + // Go back to the first page of Settings. + XCUIElement *backButton = settingsApp.navigationBars.buttons.firstMatch; + [backButton tap]; +} -- (void)testBackgroundBeforeUnaryCall { +- (void)typeText:(NSString *)text inApp:(XCUIApplication *)app { + [app typeText:text]; + // Wait until all events in run loop have been processed + while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, true) == kCFRunLoopRunHandledSource) + ; +} + +- (int)getRandomNumberBetween:(int)min max:(int)max { + return min + arc4random_uniform((max - min + 1)); +} + +- (void)testBackgroundBeforeCall { + NSLog(@"%s", __func__); // Open test app [testApp activate]; - // Send test app to background [XCUIDevice.sharedDevice pressButton:XCUIDeviceButtonHome]; - sleep(5); + + // Wait a bit + int sleepTime = [self getRandomNumberBetween:5 max:10]; + NSLog(@"Sleeping for %d seconds", sleepTime); + [NSThread sleepForTimeInterval:sleepTime]; // Bring test app to foreground and make a unary call. Call should succeed [self doUnaryCall]; [self expectCallSuccess]; } -- (void)testBackgroundBeforeStreamingCall { - // Open test app +- (void)testBackgroundDuringStreamingCall { + NSLog(@"%s", __func__); + // Open test app and start a streaming call [testApp activate]; + [self pressButton:@"Start streaming call"]; // Send test app to background [XCUIDevice.sharedDevice pressButton:XCUIDeviceButtonHome]; - sleep(5); + + // Wait a bit + int sleepTime = [self getRandomNumberBetween:5 max:10]; + NSLog(@"Sleeping for %d seconds", sleepTime); + [NSThread sleepForTimeInterval:sleepTime]; // Bring test app to foreground and make a streaming call. Call should succeed. - [self doStreamingCall]; + [testApp activate]; + [self pressButton:@"Send Message"]; + [self pressButton:@"Stop streaming call"]; [self expectCallSuccess]; } -- (void)testUnaryCallAfterNetworkFlap { +- (void)testCallAfterNetworkFlap { + NSLog(@"%s", __func__); // Open test app and make a unary call. Channel to server should be open after this. [self doUnaryCall]; [self expectCallSuccess]; @@ -119,26 +182,16 @@ NSTimeInterval const kWaitTime = 30; [self expectCallSuccess]; } -- (void)testStreamingCallAfterNetworkFlap { - // Open test app and make a unary call. Channel to server should be open after this. - [self doUnaryCall]; - [self expectCallSuccess]; - - // Toggle airplane mode on and off - [self setAirplaneMode:YES]; - [self setAirplaneMode:NO]; - - [self doStreamingCall]; - [self expectCallSuccess]; -} - -- (void)testUnaryCallWhileNetworkDown { +- (void)testCallWhileNetworkDown { + NSLog(@"%s", __func__); // Open test app and make a unary call. Channel to server should be open after this. [self doUnaryCall]; [self expectCallSuccess]; // Turn on airplane mode [self setAirplaneMode:YES]; + // Turn off wifi + [self setWifi:NO]; // Unary call should fail [self doUnaryCall]; @@ -146,29 +199,133 @@ NSTimeInterval const kWaitTime = 30; // Turn off airplane mode [self setAirplaneMode:NO]; + // Turn on wifi + [self setWifi:YES]; // Unary call should succeed [self doUnaryCall]; [self expectCallSuccess]; } -- (void)testStreamingCallWhileNetworkDown { +- (void)testSwitchApp { + NSLog(@"%s", __func__); // Open test app and make a unary call. Channel to server should be open after this. [self doUnaryCall]; [self expectCallSuccess]; - // Turn on airplane mode - [self setAirplaneMode:YES]; + // Send test app to background + [XCUIDevice.sharedDevice pressButton:XCUIDeviceButtonHome]; - // Streaming call should fail - [self doStreamingCall]; - [self expectCallFailed]; + // Open safari and goto a URL + XCUIApplication *safari = + [[XCUIApplication alloc] initWithBundleIdentifier:@"com.apple.mobilesafari"]; + [safari activate]; + // Ensure that safari is running in the foreground + XCTAssert([safari waitForState:XCUIApplicationStateRunningForeground timeout:5]); + // Move cursor to address bar + [safari.buttons[@"URL"] tap]; + // Wait for keyboard to appear + [NSThread sleepForTimeInterval:2]; + // Enter URL + [self typeText:@"http://maps.google.com" inApp:safari]; + // Presses return key + [self typeText:@"\n" inApp:safari]; + // Wait a bit + int sleepTime = [self getRandomNumberBetween:5 max:10]; + NSLog(@"Sleeping for %d seconds", sleepTime); + [NSThread sleepForTimeInterval:sleepTime]; - // Turn off airplane mode - [self setAirplaneMode:NO]; - - // Unary call should succeed - [self doStreamingCall]; + // Make another unary call + [self doUnaryCall]; [self expectCallSuccess]; } + +- (void)testNetworkFlapDuringStreamingCall { + NSLog(@"%s", __func__); + // Open test app and make a unary call. Channel to server should be open after this. + [self doUnaryCall]; + [self expectCallSuccess]; + // Start streaming call and send a message + [self pressButton:@"Start streaming call"]; + [self pressButton:@"Send Message"]; + + // Toggle network on and off + [self setAirplaneMode:YES]; + [self setWifi:NO]; + [self setAirplaneMode:NO]; + [self setWifi:YES]; + + [testApp activate]; + // We expect the call to have failed because the network flapped + [self expectCallFailed]; +} + +- (void)testConcurrentCalls { + NSLog(@"%s", __func__); + + // Press button to start 10 unary calls + [self do10UnaryCalls]; + + // Toggle airplane mode on and off + [self setAirplaneMode:YES]; + [self setAirplaneMode:NO]; + + // 10 calls should have completed + [testApp activate]; + XCTAssert([testApp.staticTexts[@"Calls completed: 10"] waitForExistenceWithTimeout:kWaitTime]); +} + +- (void)invokeTest { + for (int i = 0; i < kNumIterations; i++) { + [super invokeTest]; + } +} + +- (void)testUnaryCallTurnOffWifi { + NSLog(@"%s", __func__); + // Open test app and make a unary call. Channel to server should be open after this. + [self doUnaryCall]; + [self expectCallSuccess]; + + // Turn off wifi + [self setWifi:NO]; + + // Phone should switch to cellular connection, call should succeed + [self doUnaryCall]; + [self expectCallSuccess]; + + // Turn on wifi + [self setWifi:YES]; + + // Call should succeed after turning wifi back on + [self doUnaryCall]; + [self expectCallSuccess]; +} + +- (void)testStreamingCallTurnOffWifi { + NSLog(@"%s", __func__); + // Open test app and make a unary call. Channel to server should be open after this. + [self doUnaryCall]; + [self expectCallSuccess]; + + // Start streaming call and send a message + [self pressButton:@"Start streaming call"]; + [self pressButton:@"Send Message"]; + + // Turn off wifi + [self setWifi:NO]; + + // Phone should switch to cellular connection, this results in the call failing + [testApp activate]; + [self pressButton:@"Stop streaming call"]; + [self expectCallFailed]; + + // Turn on wifi + [self setWifi:YES]; + + // Call should succeed after turning wifi back on + [self doUnaryCall]; + [self expectCallSuccess]; +} + @end diff --git a/src/objective-c/manual_tests/Main.storyboard b/src/objective-c/manual_tests/Main.storyboard index e7e0530efcd..409084126d0 100644 --- a/src/objective-c/manual_tests/Main.storyboard +++ b/src/objective-c/manual_tests/Main.storyboard @@ -1,11 +1,11 @@ - + - + @@ -26,16 +26,8 @@ - + + + + + @@ -57,6 +87,7 @@ + diff --git a/src/objective-c/manual_tests/ViewController.m b/src/objective-c/manual_tests/ViewController.m index 813b176f3e8..50a729e4d6a 100644 --- a/src/objective-c/manual_tests/ViewController.m +++ b/src/objective-c/manual_tests/ViewController.m @@ -27,33 +27,36 @@ NSString *const kRemoteHost = @"grpc-test.sandbox.googleapis.com"; const int32_t kMessageSize = 100; @interface ViewController : UIViewController -@property(strong, nonatomic) UILabel *fromLabel; +@property(strong, nonatomic) UILabel *callStatusLabel; +@property(strong, nonatomic) UILabel *callCountLabel; @end @implementation ViewController { RMTTestService *_service; dispatch_queue_t _dispatchQueue; GRPCStreamingProtoCall *_call; + int _calls_completed; } - (instancetype)init { self = [super init]; + _calls_completed = 0; return self; } - (void)viewDidLoad { [super viewDidLoad]; _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); - _fromLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 500, 200, 20)]; - _fromLabel.textColor = [UIColor blueColor]; - _fromLabel.backgroundColor = [UIColor whiteColor]; - [self.view addSubview:_fromLabel]; + _callStatusLabel = (UILabel *)[self.view viewWithTag:1]; + _callCountLabel = (UILabel *)[self.view viewWithTag:2]; } -- (IBAction)tapUnaryCall:(id)sender { +- (void)startUnaryCall { if (_service == nil) { _service = [RMTTestService serviceWithHost:kRemoteHost]; } - self->_fromLabel.text = @""; + dispatch_async(dispatch_get_main_queue(), ^{ + self->_callStatusLabel.text = @""; + }); // Set up request proto message RMTSimpleRequest *request = [RMTSimpleRequest message]; @@ -63,14 +66,43 @@ const int32_t kMessageSize = 100; GRPCUnaryProtoCall *call = [_service unaryCallWithMessage:request responseHandler:self callOptions:nil]; + [call start]; } +- (IBAction)tapUnaryCall:(id)sender { + NSLog(@"In tapUnaryCall"); + [self startUnaryCall]; +} + +- (IBAction)tap10UnaryCalls:(id)sender { + NSLog(@"In tap10UnaryCalls"); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { + // Background thread + for (int i = 0; i < 10; ++i) { + [self startUnaryCall]; + [NSThread sleepForTimeInterval:0.5]; + } + }); +} + +- (IBAction)resetCounter:(id)sender { + _calls_completed = 0; + dispatch_async(dispatch_get_main_queue(), ^{ + self->_callCountLabel.text = + [NSString stringWithFormat:@"Calls completed: %d", self->_calls_completed]; + self->_callStatusLabel.text = @""; + }); +} + - (IBAction)tapStreamingCallStart:(id)sender { + NSLog(@"In tapStreamingCallStart"); if (_service == nil) { _service = [RMTTestService serviceWithHost:kRemoteHost]; } - self->_fromLabel.text = @""; + dispatch_async(dispatch_get_main_queue(), ^{ + self->_callStatusLabel.text = @""; + }); // Set up request proto message RMTStreamingOutputCallRequest *request = RMTStreamingOutputCallRequest.message; @@ -83,10 +115,10 @@ const int32_t kMessageSize = 100; [call start]; _call = call; // display something to confirm the tester the call is started - NSLog(@"Started streaming call"); } - (IBAction)tapStreamingCallSend:(id)sender { + NSLog(@"In tapStreamingCallSend"); if (_call == nil) return; RMTStreamingOutputCallRequest *request = RMTStreamingOutputCallRequest.message; @@ -99,6 +131,7 @@ const int32_t kMessageSize = 100; } - (IBAction)tapStreamingCallStop:(id)sender { + NSLog(@"In tapStreamingCallStop"); if (_call == nil) return; [_call finish]; @@ -118,13 +151,18 @@ const int32_t kMessageSize = 100; NSLog(@"Recv trailing metadata: %@, error: %@", trailingMetadata, error); if (error == nil) { dispatch_async(dispatch_get_main_queue(), ^{ - self->_fromLabel.text = @"Call done"; + self->_callStatusLabel.text = @"Call done"; }); } else { dispatch_async(dispatch_get_main_queue(), ^{ - self->_fromLabel.text = @"Call failed"; + self->_callStatusLabel.text = @"Call failed"; }); } + ++_calls_completed; + dispatch_async(dispatch_get_main_queue(), ^{ + self->_callCountLabel.text = + [NSString stringWithFormat:@"Calls completed: %d", self->_calls_completed]; + }); } - (dispatch_queue_t)dispatchQueue { From 991409798c2c8e3d8d3e742e5fda27d571427590 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Mon, 8 Apr 2019 13:09:41 -0700 Subject: [PATCH 212/242] Fix clang script errors --- include/grpcpp/server_builder_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/grpcpp/server_builder_impl.h b/include/grpcpp/server_builder_impl.h index 3a1a8da879f..f7624deba5f 100644 --- a/include/grpcpp/server_builder_impl.h +++ b/include/grpcpp/server_builder_impl.h @@ -31,8 +31,8 @@ #include #include #include -#include #include +#include struct grpc_resource_quota; From 4cb0d0d6b19244bdd5025e3bf7843786b6fc8806 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Mon, 8 Apr 2019 13:41:19 -0700 Subject: [PATCH 213/242] Fix errors from clang scripts --- BUILD.gn | 1 + include/grpcpp/impl/codegen/completion_queue.h | 2 +- include/grpcpp/impl/codegen/server_interface.h | 2 +- include/grpcpp/security/credentials.h | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index 1417f1db5ea..7bec321153f 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1003,6 +1003,7 @@ config("grpc_config") { "include/grpcpp/alarm.h", "include/grpcpp/alarm_impl.h", "include/grpcpp/channel.h", + "include/grpcpp/channel_impl.h", "include/grpcpp/client_context.h", "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", diff --git a/include/grpcpp/impl/codegen/completion_queue.h b/include/grpcpp/impl/codegen/completion_queue.h index c64d581d71d..77753bb37f0 100644 --- a/include/grpcpp/impl/codegen/completion_queue.h +++ b/include/grpcpp/impl/codegen/completion_queue.h @@ -45,7 +45,7 @@ namespace grpc_impl { class Channel; class ServerBuilder; -} // namespace grpc_impl +} // namespace grpc_impl namespace grpc { template diff --git a/include/grpcpp/impl/codegen/server_interface.h b/include/grpcpp/impl/codegen/server_interface.h index 78814aa9862..9299fdb20e1 100644 --- a/include/grpcpp/impl/codegen/server_interface.h +++ b/include/grpcpp/impl/codegen/server_interface.h @@ -31,7 +31,7 @@ namespace grpc_impl { class Channel; class ServerCredentials; -} // namespace grpc_impl +} // namespace grpc_impl namespace grpc { class AsyncGenericService; diff --git a/include/grpcpp/security/credentials.h b/include/grpcpp/security/credentials.h index 7b1efddfc08..5846da106d5 100644 --- a/include/grpcpp/security/credentials.h +++ b/include/grpcpp/security/credentials.h @@ -35,7 +35,7 @@ struct grpc_call; namespace grpc_impl { class Channel; -} // namespace grpc_impl +} // namespace grpc_impl namespace grpc { class CallCredentials; From 5158c3db275878f8db034059c4855e74e732eb10 Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Mon, 8 Apr 2019 14:39:09 -0700 Subject: [PATCH 214/242] naming update, documentation fix --- WORKSPACE | 2 +- .../{bazel_0.23.2 => bazel_0.23.2_rbe_windows}/BUILD | 0 .../cc_toolchain_config.bzl | 0 .../dummy_toolchain.bzl | 0 tools/internal_ci/linux/grpc_bazel_build_in_docker.sh | 2 +- tools/remote_build/README.md | 4 ++-- tools/remote_build/windows.bazelrc | 8 +++----- 7 files changed, 7 insertions(+), 9 deletions(-) rename third_party/toolchains/{bazel_0.23.2 => bazel_0.23.2_rbe_windows}/BUILD (100%) rename third_party/toolchains/{bazel_0.23.2 => bazel_0.23.2_rbe_windows}/cc_toolchain_config.bzl (100%) rename third_party/toolchains/{bazel_0.23.2 => bazel_0.23.2_rbe_windows}/dummy_toolchain.bzl (100%) diff --git a/WORKSPACE b/WORKSPACE index d90d7b6751d..b984438d1d6 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -16,7 +16,7 @@ register_execution_platforms( register_toolchains( "//third_party/toolchains:cc-toolchain-clang-x86_64-default", - "//third_party/toolchains/bazel_0.23.2:cc-toolchain-x64_windows", + "//third_party/toolchains/bazel_0.23.2_rbe_windows:cc-toolchain-x64_windows", ) # TODO(https://github.com/grpc/grpc/issues/18331): Move off of this dependency. diff --git a/third_party/toolchains/bazel_0.23.2/BUILD b/third_party/toolchains/bazel_0.23.2_rbe_windows/BUILD similarity index 100% rename from third_party/toolchains/bazel_0.23.2/BUILD rename to third_party/toolchains/bazel_0.23.2_rbe_windows/BUILD diff --git a/third_party/toolchains/bazel_0.23.2/cc_toolchain_config.bzl b/third_party/toolchains/bazel_0.23.2_rbe_windows/cc_toolchain_config.bzl similarity index 100% rename from third_party/toolchains/bazel_0.23.2/cc_toolchain_config.bzl rename to third_party/toolchains/bazel_0.23.2_rbe_windows/cc_toolchain_config.bzl diff --git a/third_party/toolchains/bazel_0.23.2/dummy_toolchain.bzl b/third_party/toolchains/bazel_0.23.2_rbe_windows/dummy_toolchain.bzl similarity index 100% rename from third_party/toolchains/bazel_0.23.2/dummy_toolchain.bzl rename to third_party/toolchains/bazel_0.23.2_rbe_windows/dummy_toolchain.bzl diff --git a/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh b/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh index 93f6bd65fe6..3dd0167b7c0 100755 --- a/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh +++ b/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh @@ -25,4 +25,4 @@ git clone /var/local/jenkins/grpc /var/local/git/grpc ${name}') cd /var/local/git/grpc #TODO(yfen): add back examples/... to build targets once python rules issues are resolved -bazel build --spawn_strategy=standalone --genrule_strategy=standalone :all test/... \ No newline at end of file +bazel build --spawn_strategy=standalone --genrule_strategy=standalone :all test/... diff --git a/tools/remote_build/README.md b/tools/remote_build/README.md index bb27dc7072c..2cd5f03daf1 100644 --- a/tools/remote_build/README.md +++ b/tools/remote_build/README.md @@ -31,8 +31,8 @@ bazel --bazelrc=tools/remote_build/manual.bazelrc test --config=asan //test/... Run on Windows MSVC: ``` -# local manual run only for C++ targets (RBE to be supported) -bazel --bazelrc=tools/remote_build/windows.bazelrc test //test/cpp/... +# RBE manual run only for c-core (must be run on a Windows host machine) +bazel --bazelrc=tools/remote_build/windows.bazelrc build :all [--credentials_json=(path to service account credentials)] ``` Available command line options can be found in diff --git a/tools/remote_build/windows.bazelrc b/tools/remote_build/windows.bazelrc index a4cb66a7d34..492489f3613 100644 --- a/tools/remote_build/windows.bazelrc +++ b/tools/remote_build/windows.bazelrc @@ -1,14 +1,12 @@ -# TODO(yfen): Merge with rbe_common.bazelrc and enable Windows RBE - startup --host_jvm_args=-Dbazel.DigestFunction=SHA256 build --remote_cache=remotebuildexecution.googleapis.com build --remote_executor=remotebuildexecution.googleapis.com build --tls_enabled=true -build --host_crosstool_top=//third_party/toolchains/bazel_0.23.2:toolchain -build --crosstool_top=//third_party/toolchains/bazel_0.23.2:toolchain -build --extra_toolchains=//third_party/toolchains/bazel_0.23.2:cc-toolchain-x64_windows +build --host_crosstool_top=//third_party/toolchains/bazel_0.23.2_rbe_windows:toolchain +build --crosstool_top=//third_party/toolchains/bazel_0.23.2_rbe_windows:toolchain +build --extra_toolchains=//third_party/toolchains/bazel_0.23.2_rbe_windows:cc-toolchain-x64_windows # Use custom execution platforms defined in third_party/toolchains build --extra_execution_platforms=//third_party/toolchains:rbe_windows build --host_platform=//third_party/toolchains:rbe_windows From a26c09dd258a0d4dc3023e874b13f92e29174a43 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Mon, 1 Apr 2019 12:09:05 -0400 Subject: [PATCH 215/242] Introduce C++ wrappers for gpr_mu and gpr_cv. Introduce RAII wrappers in the grpc::internal and grpc_core namespaces, and use them in place of std::mutex and std::condition_variable. Note that, since std::mutex is also used by the public C++ headers we cannot introduce these wrappers in grpc_core. Also, note that in grpcpp we cannot use gRPC core and vice versa. So we had to duplicate the code, once using core_codegen_interface and once using direct calls. --- BUILD | 14 +- BUILD.gn | 5 +- CMakeLists.txt | 5 + Makefile | 5 + build.yaml | 8 +- gRPC-C++.podspec | 7 +- gRPC-Core.podspec | 4 +- grpc.gemspec | 2 +- include/grpcpp/channel.h | 3 +- include/grpcpp/impl/codegen/client_context.h | 3 +- include/grpcpp/impl/codegen/sync.h | 138 ++++++++++++++++++ include/grpcpp/server_impl.h | 8 +- package.xml | 2 +- .../filters/client_channel/client_channel.cc | 2 +- .../health/health_check_client.cc | 4 +- .../health/health_check_client.h | 3 +- .../client_channel/http_connect_handshaker.cc | 2 +- .../client_channel/lb_policy/grpclb/grpclb.cc | 1 - .../lb_policy/grpclb/grpclb_client_stats.cc | 2 +- .../lb_policy/grpclb/grpclb_client_stats.h | 6 +- .../lb_policy/pick_first/pick_first.cc | 6 +- .../lb_policy/round_robin/round_robin.cc | 6 +- .../client_channel/lb_policy/xds/xds.cc | 19 +-- .../client_channel/resolving_lb_policy.cc | 2 +- .../ext/filters/client_channel/subchannel.cc | 70 ++++----- .../ext/filters/client_channel/subchannel.h | 3 +- src/core/lib/channel/channelz_registry.cc | 2 +- src/core/lib/channel/handshaker.h | 2 +- src/core/lib/gprpp/mutex_lock.h | 42 ------ src/core/lib/gprpp/sync.h | 126 ++++++++++++++++ src/core/lib/iomgr/ev_epollex_linux.cc | 2 +- src/core/lib/surface/init.cc | 2 +- .../ssl/session_cache/ssl_session_cache.cc | 2 +- src/cpp/client/channel_cc.cc | 2 +- src/cpp/client/client_context.cc | 5 +- src/cpp/server/dynamic_thread_pool.cc | 23 +-- src/cpp/server/dynamic_thread_pool.h | 7 +- .../health/default_health_check_service.cc | 28 ++-- .../health/default_health_check_service.h | 7 +- src/cpp/server/load_reporter/load_reporter.cc | 18 +-- src/cpp/server/load_reporter/load_reporter.h | 5 +- .../load_reporter_async_service_impl.cc | 24 +-- .../load_reporter_async_service_impl.h | 3 +- src/cpp/server/server_cc.cc | 24 +-- src/cpp/server/server_context.cc | 14 +- src/cpp/thread_manager/thread_manager.cc | 34 ++--- src/cpp/thread_manager/thread_manager.h | 7 +- test/cpp/client/client_channel_stress_test.cc | 17 ++- test/cpp/end2end/client_lb_end2end_test.cc | 37 ++--- test/cpp/end2end/grpclb_end2end_test.cc | 67 ++++----- test/cpp/end2end/thread_stress_test.cc | 21 +-- test/cpp/end2end/xds_end2end_test.cc | 66 ++++----- tools/doxygen/Doxyfile.c++ | 1 + tools/doxygen/Doxyfile.c++.internal | 3 +- tools/doxygen/Doxyfile.core.internal | 2 +- .../generated/sources_and_headers.json | 20 ++- 56 files changed, 607 insertions(+), 336 deletions(-) create mode 100644 include/grpcpp/impl/codegen/sync.h delete mode 100644 src/core/lib/gprpp/mutex_lock.h create mode 100644 src/core/lib/gprpp/sync.h diff --git a/BUILD b/BUILD index 914a0b9bf92..6bea6557904 100644 --- a/BUILD +++ b/BUILD @@ -526,6 +526,17 @@ grpc_cc_library( ], ) +grpc_cc_library( + name = "grpc++_internal_hdrs_only", + hdrs = [ + "include/grpcpp/impl/codegen/sync.h", + ], + language = "c++", + deps = [ + "gpr_codegen", + ], +) + grpc_cc_library( name = "gpr_base", srcs = [ @@ -591,8 +602,8 @@ grpc_cc_library( "src/core/lib/gprpp/manual_constructor.h", "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", - "src/core/lib/gprpp/mutex_lock.h", "src/core/lib/gprpp/pair.h", + "src/core/lib/gprpp/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/profiling/timers.h", ], @@ -2146,6 +2157,7 @@ grpc_cc_library( "include/grpcpp/impl/codegen/time.h", ], deps = [ + "grpc++_internal_hdrs_only", "grpc_codegen", ], ) diff --git a/BUILD.gn b/BUILD.gn index 0813898bcb7..57e15800e20 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -186,8 +186,8 @@ config("grpc_config") { "src/core/lib/gprpp/manual_constructor.h", "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", - "src/core/lib/gprpp/mutex_lock.h", "src/core/lib/gprpp/pair.h", + "src/core/lib/gprpp/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/gprpp/thd_posix.cc", "src/core/lib/gprpp/thd_windows.cc", @@ -1064,6 +1064,7 @@ config("grpc_config") { "include/grpcpp/impl/codegen/status_code_enum.h", "include/grpcpp/impl/codegen/string_ref.h", "include/grpcpp/impl/codegen/stub_options.h", + "include/grpcpp/impl/codegen/sync.h", "include/grpcpp/impl/codegen/sync_stream.h", "include/grpcpp/impl/codegen/time.h", "include/grpcpp/impl/grpc_library.h", @@ -1159,12 +1160,12 @@ config("grpc_config") { "src/core/lib/gprpp/manual_constructor.h", "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", - "src/core/lib/gprpp/mutex_lock.h", "src/core/lib/gprpp/optional.h", "src/core/lib/gprpp/orphanable.h", "src/core/lib/gprpp/pair.h", "src/core/lib/gprpp/ref_counted.h", "src/core/lib/gprpp/ref_counted_ptr.h", + "src/core/lib/gprpp/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 89bd64743ff..72d2a76d64d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3181,6 +3181,7 @@ foreach(_hdr include/grpcpp/impl/codegen/stub_options.h include/grpcpp/impl/codegen/sync_stream.h include/grpcpp/impl/codegen/time.h + include/grpcpp/impl/codegen/sync.h include/grpc++/impl/codegen/proto_utils.h include/grpcpp/impl/codegen/proto_buffer_reader.h include/grpcpp/impl/codegen/proto_buffer_writer.h @@ -3784,6 +3785,7 @@ foreach(_hdr include/grpcpp/impl/codegen/stub_options.h include/grpcpp/impl/codegen/sync_stream.h include/grpcpp/impl/codegen/time.h + include/grpcpp/impl/codegen/sync.h include/grpc/census.h ) string(REPLACE "include/" "" _path ${_hdr}) @@ -4238,6 +4240,7 @@ foreach(_hdr include/grpc/impl/codegen/sync_generic.h include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h + include/grpcpp/impl/codegen/sync.h include/grpc++/impl/codegen/proto_utils.h include/grpcpp/impl/codegen/proto_buffer_reader.h include/grpcpp/impl/codegen/proto_buffer_writer.h @@ -4434,6 +4437,7 @@ foreach(_hdr include/grpc/impl/codegen/sync_generic.h include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h + include/grpcpp/impl/codegen/sync.h include/grpc++/impl/codegen/proto_utils.h include/grpcpp/impl/codegen/proto_buffer_reader.h include/grpcpp/impl/codegen/proto_buffer_writer.h @@ -4761,6 +4765,7 @@ foreach(_hdr include/grpcpp/impl/codegen/stub_options.h include/grpcpp/impl/codegen/sync_stream.h include/grpcpp/impl/codegen/time.h + include/grpcpp/impl/codegen/sync.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) diff --git a/Makefile b/Makefile index e777f69e921..3acdcb256d3 100644 --- a/Makefile +++ b/Makefile @@ -5512,6 +5512,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/stub_options.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ + include/grpcpp/impl/codegen/sync.h \ include/grpc++/impl/codegen/proto_utils.h \ include/grpcpp/impl/codegen/proto_buffer_reader.h \ include/grpcpp/impl/codegen/proto_buffer_writer.h \ @@ -6123,6 +6124,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/stub_options.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ + include/grpcpp/impl/codegen/sync.h \ include/grpc/census.h \ LIBGRPC++_CRONET_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_CRONET_SRC)))) @@ -6549,6 +6551,7 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ + include/grpcpp/impl/codegen/sync.h \ include/grpc++/impl/codegen/proto_utils.h \ include/grpcpp/impl/codegen/proto_buffer_reader.h \ include/grpcpp/impl/codegen/proto_buffer_writer.h \ @@ -6716,6 +6719,7 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ + include/grpcpp/impl/codegen/sync.h \ include/grpc++/impl/codegen/proto_utils.h \ include/grpcpp/impl/codegen/proto_buffer_reader.h \ include/grpcpp/impl/codegen/proto_buffer_writer.h \ @@ -7049,6 +7053,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/stub_options.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ + include/grpcpp/impl/codegen/sync.h \ LIBGRPC++_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_UNSECURE_SRC)))) diff --git a/build.yaml b/build.yaml index a539f062d2e..99f9ef35f63 100644 --- a/build.yaml +++ b/build.yaml @@ -196,8 +196,8 @@ filegroups: - src/core/lib/gprpp/manual_constructor.h - src/core/lib/gprpp/map.h - src/core/lib/gprpp/memory.h - - src/core/lib/gprpp/mutex_lock.h - src/core/lib/gprpp/pair.h + - src/core/lib/gprpp/sync.h - src/core/lib/gprpp/thd.h - src/core/lib/profiling/timers.h uses: @@ -1276,6 +1276,7 @@ filegroups: - include/grpcpp/impl/codegen/time.h uses: - grpc_codegen + - grpc++_internal_hdrs_only - name: grpc++_codegen_base_src language: c++ src: @@ -1451,6 +1452,7 @@ filegroups: - grpc_base_headers - grpc_transport_inproc_headers - grpc++_codegen_base + - grpc++_internal_hdrs_only - nanopb_headers - health_proto - name: grpc++_config_proto @@ -1458,6 +1460,10 @@ filegroups: public_headers: - include/grpc++/impl/codegen/config_protobuf.h - include/grpcpp/impl/codegen/config_protobuf.h +- name: grpc++_internal_hdrs_only + language: c++ + public_headers: + - include/grpcpp/impl/codegen/sync.h - name: grpc++_reflection_proto language: c++ src: diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 58a4c82253b..7f1ae557537 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -184,7 +184,8 @@ Pod::Spec.new do |s| 'include/grpcpp/impl/codegen/string_ref.h', 'include/grpcpp/impl/codegen/stub_options.h', 'include/grpcpp/impl/codegen/sync_stream.h', - 'include/grpcpp/impl/codegen/time.h' + 'include/grpcpp/impl/codegen/time.h', + 'include/grpcpp/impl/codegen/sync.h' end s.subspec 'Implementation' do |ss| @@ -267,8 +268,8 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/manual_constructor.h', 'src/core/lib/gprpp/map.h', 'src/core/lib/gprpp/memory.h', - 'src/core/lib/gprpp/mutex_lock.h', 'src/core/lib/gprpp/pair.h', + 'src/core/lib/gprpp/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/ext/transport/chttp2/transport/bin_decoder.h', @@ -584,8 +585,8 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/manual_constructor.h', 'src/core/lib/gprpp/map.h', 'src/core/lib/gprpp/memory.h', - 'src/core/lib/gprpp/mutex_lock.h', 'src/core/lib/gprpp/pair.h', + 'src/core/lib/gprpp/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/lib/avl/avl.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index bab7ce4378e..c58152cf7f8 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -210,8 +210,8 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/manual_constructor.h', 'src/core/lib/gprpp/map.h', 'src/core/lib/gprpp/memory.h', - 'src/core/lib/gprpp/mutex_lock.h', 'src/core/lib/gprpp/pair.h', + 'src/core/lib/gprpp/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/lib/gpr/alloc.cc', @@ -889,8 +889,8 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/manual_constructor.h', 'src/core/lib/gprpp/map.h', 'src/core/lib/gprpp/memory.h', - 'src/core/lib/gprpp/mutex_lock.h', 'src/core/lib/gprpp/pair.h', + 'src/core/lib/gprpp/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/ext/transport/chttp2/transport/bin_decoder.h', diff --git a/grpc.gemspec b/grpc.gemspec index b9d2107ee48..c41db6f6293 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -104,8 +104,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/gprpp/manual_constructor.h ) s.files += %w( src/core/lib/gprpp/map.h ) s.files += %w( src/core/lib/gprpp/memory.h ) - s.files += %w( src/core/lib/gprpp/mutex_lock.h ) s.files += %w( src/core/lib/gprpp/pair.h ) + s.files += %w( src/core/lib/gprpp/sync.h ) s.files += %w( src/core/lib/gprpp/thd.h ) s.files += %w( src/core/lib/profiling/timers.h ) s.files += %w( src/core/lib/gpr/alloc.cc ) diff --git a/include/grpcpp/channel.h b/include/grpcpp/channel.h index ee833960698..c4d5ab1177b 100644 --- a/include/grpcpp/channel.h +++ b/include/grpcpp/channel.h @@ -28,6 +28,7 @@ #include #include #include +#include struct grpc_channel; @@ -97,7 +98,7 @@ class Channel final : public ChannelInterface, grpc_channel* const c_channel_; // owned // mu_ protects callback_cq_ (the per-channel callbackable completion queue) - std::mutex mu_; + grpc::internal::Mutex mu_; // callback_cq_ references the callbackable completion queue associated // with this channel (if any). It is set on the first call to CallbackCQ(). diff --git a/include/grpcpp/impl/codegen/client_context.h b/include/grpcpp/impl/codegen/client_context.h index 5946488566e..85bbf36f06d 100644 --- a/include/grpcpp/impl/codegen/client_context.h +++ b/include/grpcpp/impl/codegen/client_context.h @@ -51,6 +51,7 @@ #include #include #include +#include #include struct census_context; @@ -457,7 +458,7 @@ class ClientContext { bool idempotent_; bool cacheable_; std::shared_ptr channel_; - std::mutex mu_; + grpc::internal::Mutex mu_; grpc_call* call_; bool call_canceled_; gpr_timespec deadline_; diff --git a/include/grpcpp/impl/codegen/sync.h b/include/grpcpp/impl/codegen/sync.h new file mode 100644 index 00000000000..2ed71eeb9f2 --- /dev/null +++ b/include/grpcpp/impl/codegen/sync.h @@ -0,0 +1,138 @@ +/* + * + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_IMPL_CODEGEN_SYNC_H +#define GRPCPP_IMPL_CODEGEN_SYNC_H + +#include +#include +#include + +#include + +// The core library is not accessible in C++ codegen headers, and vice versa. +// Thus, we need to have duplicate headers with similar functionality. +// Make sure any change to this file is also reflected in +// src/core/lib/gprpp/sync.h too. +// +// Whenever possible, prefer "src/core/lib/gprpp/sync.h" over this file, +// since in core we do not rely on g_core_codegen_interface and hence do not +// pay the costs of virtual function calls. + +namespace grpc { +namespace internal { + +class Mutex { + public: + Mutex() { g_core_codegen_interface->gpr_mu_init(&mu_); } + ~Mutex() { g_core_codegen_interface->gpr_mu_destroy(&mu_); } + + Mutex(const Mutex&) = delete; + Mutex& operator=(const Mutex&) = delete; + + gpr_mu* get() { return &mu_; } + const gpr_mu* get() const { return &mu_; } + + private: + gpr_mu mu_; +}; + +// MutexLock is a std:: +class MutexLock { + public: + explicit MutexLock(Mutex* mu) : mu_(mu->get()) { + g_core_codegen_interface->gpr_mu_lock(mu_); + } + explicit MutexLock(gpr_mu* mu) : mu_(mu) { + g_core_codegen_interface->gpr_mu_lock(mu_); + } + ~MutexLock() { g_core_codegen_interface->gpr_mu_unlock(mu_); } + + MutexLock(const MutexLock&) = delete; + MutexLock& operator=(const MutexLock&) = delete; + + private: + gpr_mu* const mu_; +}; + +class ReleasableMutexLock { + public: + explicit ReleasableMutexLock(Mutex* mu) : mu_(mu->get()) { + g_core_codegen_interface->gpr_mu_lock(mu_); + } + explicit ReleasableMutexLock(gpr_mu* mu) : mu_(mu) { + g_core_codegen_interface->gpr_mu_lock(mu_); + } + ~ReleasableMutexLock() { + if (!released_) g_core_codegen_interface->gpr_mu_unlock(mu_); + } + + ReleasableMutexLock(const ReleasableMutexLock&) = delete; + ReleasableMutexLock& operator=(const ReleasableMutexLock&) = delete; + + void Lock() { + GPR_DEBUG_ASSERT(released_); + g_core_codegen_interface->gpr_mu_lock(mu_); + released_ = false; + } + + void Unlock() { + GPR_DEBUG_ASSERT(!released_); + released_ = true; + g_core_codegen_interface->gpr_mu_unlock(mu_); + } + + private: + gpr_mu* const mu_; + bool released_ = false; +}; + +class CondVar { + public: + CondVar() { g_core_codegen_interface->gpr_cv_init(&cv_); } + ~CondVar() { g_core_codegen_interface->gpr_cv_destroy(&cv_); } + + CondVar(const CondVar&) = delete; + CondVar& operator=(const CondVar&) = delete; + + void Signal() { g_core_codegen_interface->gpr_cv_signal(&cv_); } + void Broadcast() { g_core_codegen_interface->gpr_cv_broadcast(&cv_); } + + int Wait(Mutex* mu) { + return Wait(mu, + g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME)); + } + int Wait(Mutex* mu, const gpr_timespec& deadline) { + return g_core_codegen_interface->gpr_cv_wait(&cv_, mu->get(), deadline); + } + + template + void WaitUntil(Mutex* mu, Predicate pred) { + while (!pred()) { + Wait(mu, g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME)); + } + } + + private: + gpr_cv cv_; +}; + +} // namespace internal +} // namespace grpc + +#endif // GRPCPP_IMPL_CODEGEN_SYNC_H diff --git a/include/grpcpp/server_impl.h b/include/grpcpp/server_impl.h index 771a3a10be9..14b16a06f4e 100644 --- a/include/grpcpp/server_impl.h +++ b/include/grpcpp/server_impl.h @@ -304,12 +304,12 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen { experimental_registration_type experimental_registration_{this}; // Server status - std::mutex mu_; + grpc::internal::Mutex mu_; bool started_; bool shutdown_; bool shutdown_notified_; // Was notify called on the shutdown_cv_ - std::condition_variable shutdown_cv_; + grpc::internal::CondVar shutdown_cv_; // It is ok (but not required) to nest callback_reqs_mu_ under mu_ . // Incrementing callback_reqs_outstanding_ is ok without a lock but it must be @@ -318,8 +318,8 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen { // during periods of increasing load; the decrement happens only when memory // is maxed out, during server shutdown, or (possibly in a future version) // during decreasing load, so it is less performance-critical. - std::mutex callback_reqs_mu_; - std::condition_variable callback_reqs_done_cv_; + grpc::internal::Mutex callback_reqs_mu_; + grpc::internal::CondVar callback_reqs_done_cv_; std::atomic_int callback_reqs_outstanding_{0}; std::shared_ptr global_callbacks_; diff --git a/package.xml b/package.xml index f3bbb449ac5..5be3d24365d 100644 --- a/package.xml +++ b/package.xml @@ -109,8 +109,8 @@ - + diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 86938a51d9b..cd552739732 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -51,7 +51,7 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/manual_constructor.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/polling_entity.h" diff --git a/src/core/ext/filters/client_channel/health/health_check_client.cc b/src/core/ext/filters/client_channel/health/health_check_client.cc index a22d6450cbd..a99f1e54062 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.cc +++ b/src/core/ext/filters/client_channel/health/health_check_client.cc @@ -27,7 +27,7 @@ #include "pb_encode.h" #include "src/core/ext/filters/client_channel/health/health.pb.h" #include "src/core/lib/debug/trace.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/transport/error_utils.h" #include "src/core/lib/transport/status_metadata.h" @@ -69,7 +69,6 @@ HealthCheckClient::HealthCheckClient( } GRPC_CLOSURE_INIT(&retry_timer_callback_, OnRetryTimer, this, grpc_schedule_on_exec_ctx); - gpr_mu_init(&mu_); StartCall(); } @@ -78,7 +77,6 @@ HealthCheckClient::~HealthCheckClient() { gpr_log(GPR_INFO, "destroying HealthCheckClient %p", this); } GRPC_ERROR_UNREF(error_); - gpr_mu_destroy(&mu_); } void HealthCheckClient::NotifyOnHealthChange(grpc_connectivity_state* state, diff --git a/src/core/ext/filters/client_channel/health/health_check_client.h b/src/core/ext/filters/client_channel/health/health_check_client.h index 1fa4487c403..6e0123e4925 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.h +++ b/src/core/ext/filters/client_channel/health/health_check_client.h @@ -31,6 +31,7 @@ #include "src/core/lib/gprpp/atomic.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/call_combiner.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/polling_entity.h" @@ -157,7 +158,7 @@ class HealthCheckClient : public InternallyRefCounted { grpc_pollset_set* interested_parties_; // Do not own. RefCountedPtr channelz_node_; - gpr_mu mu_; + Mutex mu_; grpc_connectivity_state state_ = GRPC_CHANNEL_CONNECTING; grpc_error* error_ = GRPC_ERROR_NONE; grpc_connectivity_state* notify_state_ = nullptr; diff --git a/src/core/ext/filters/client_channel/http_connect_handshaker.cc b/src/core/ext/filters/client_channel/http_connect_handshaker.cc index 2b1eb92bbd4..90a79843458 100644 --- a/src/core/ext/filters/client_channel/http_connect_handshaker.cc +++ b/src/core/ext/filters/client_channel/http_connect_handshaker.cc @@ -33,7 +33,7 @@ #include "src/core/lib/channel/handshaker_registry.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/http/format_request.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/slice/slice_internal.h" diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index aebd2fd3faa..ead15308f49 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -88,7 +88,6 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/gprpp/memory.h" -#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/combiner.h" diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc index 84b9c41a734..35123633feb 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc @@ -25,7 +25,7 @@ #include #include -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" namespace grpc_core { diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h index fdebdf55c17..bcc6598c105 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h @@ -26,6 +26,7 @@ #include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/gprpp/sync.h" namespace grpc_core { @@ -41,9 +42,6 @@ class GrpcLbClientStats : public RefCounted { typedef InlinedVector DroppedCallCounts; - GrpcLbClientStats() { gpr_mu_init(&drop_count_mu_); } - ~GrpcLbClientStats() { gpr_mu_destroy(&drop_count_mu_); } - void AddCallStarted(); void AddCallFinished(bool finished_with_client_failed_to_send, bool finished_known_received); @@ -66,7 +64,7 @@ class GrpcLbClientStats : public RefCounted { gpr_atm num_calls_finished_ = 0; gpr_atm num_calls_finished_with_client_failed_to_send_ = 0; gpr_atm num_calls_finished_known_received_ = 0; - gpr_mu drop_count_mu_; // Guards drop_token_counts_. + Mutex drop_count_mu_; // Guards drop_token_counts_. UniquePtr drop_token_counts_; }; diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index 332f66808e0..892472e1c9b 100644 --- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -27,7 +27,7 @@ #include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" @@ -154,13 +154,12 @@ class PickFirst : public LoadBalancingPolicy { /// Lock and data used to capture snapshots of this channels child /// channels and subchannels. This data is consumed by channelz. - gpr_mu child_refs_mu_; + Mutex child_refs_mu_; channelz::ChildRefsList child_subchannels_; channelz::ChildRefsList child_channels_; }; PickFirst::PickFirst(Args args) : LoadBalancingPolicy(std::move(args)) { - gpr_mu_init(&child_refs_mu_); if (grpc_lb_pick_first_trace.enabled()) { gpr_log(GPR_INFO, "Pick First %p created.", this); } @@ -170,7 +169,6 @@ PickFirst::~PickFirst() { if (grpc_lb_pick_first_trace.enabled()) { gpr_log(GPR_INFO, "Destroying Pick First %p", this); } - gpr_mu_destroy(&child_refs_mu_); GPR_ASSERT(subchannel_list_ == nullptr); GPR_ASSERT(latest_pending_subchannel_list_ == nullptr); } diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc index d3faaaddc98..29cfe972f78 100644 --- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc @@ -36,8 +36,8 @@ #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/debug/trace.h" -#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" @@ -193,7 +193,7 @@ class RoundRobin : public LoadBalancingPolicy { bool shutdown_ = false; /// Lock and data used to capture snapshots of this channel's child /// channels and subchannels. This data is consumed by channelz. - gpr_mu child_refs_mu_; + Mutex child_refs_mu_; channelz::ChildRefsList child_subchannels_; channelz::ChildRefsList child_channels_; }; @@ -245,7 +245,6 @@ RoundRobin::PickResult RoundRobin::Picker::Pick(PickArgs* pick, // RoundRobin::RoundRobin(Args args) : LoadBalancingPolicy(std::move(args)) { - gpr_mu_init(&child_refs_mu_); if (grpc_lb_round_robin_trace.enabled()) { gpr_log(GPR_INFO, "[RR %p] Created", this); } @@ -255,7 +254,6 @@ RoundRobin::~RoundRobin() { if (grpc_lb_round_robin_trace.enabled()) { gpr_log(GPR_INFO, "[RR %p] Destroying Round Robin policy", this); } - gpr_mu_destroy(&child_refs_mu_); GPR_ASSERT(subchannel_list_ == nullptr); GPR_ASSERT(latest_pending_subchannel_list_ == nullptr); } diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc b/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc index fe49e9aca03..443deb01274 100644 --- a/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +++ b/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc @@ -89,9 +89,9 @@ #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/gprpp/map.h" #include "src/core/lib/gprpp/memory.h" -#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" @@ -278,10 +278,8 @@ class XdsLb : public LoadBalancingPolicy { class LocalityEntry : public InternallyRefCounted { public: explicit LocalityEntry(RefCountedPtr parent) - : parent_(std::move(parent)) { - gpr_mu_init(&child_policy_mu_); - } - ~LocalityEntry() { gpr_mu_destroy(&child_policy_mu_); } + : parent_(std::move(parent)) {} + ~LocalityEntry() = default; void UpdateLocked(xds_grpclb_serverlist* serverlist, LoadBalancingPolicy::Config* child_policy_config, @@ -323,13 +321,10 @@ class XdsLb : public LoadBalancingPolicy { OrphanablePtr pending_child_policy_; // Lock held when modifying the value of child_policy_ or // pending_child_policy_. - gpr_mu child_policy_mu_; + Mutex child_policy_mu_; RefCountedPtr parent_; }; - LocalityMap() { gpr_mu_init(&child_refs_mu_); } - ~LocalityMap() { gpr_mu_destroy(&child_refs_mu_); } - void UpdateLocked(const LocalityList& locality_list, LoadBalancingPolicy::Config* child_policy_config, const grpc_channel_args* args, XdsLb* parent); @@ -343,7 +338,7 @@ class XdsLb : public LoadBalancingPolicy { Map, OrphanablePtr, StringLess> map_; // Lock held while filling child refs for all localities // inside the map - gpr_mu child_refs_mu_; + Mutex child_refs_mu_; }; struct LocalityServerlistEntry { @@ -397,7 +392,7 @@ class XdsLb : public LoadBalancingPolicy { // Mutex to protect the channel to the LB server. This is used when // processing a channelz request. // TODO(juanlishen): Replace this with atomic. - gpr_mu lb_chand_mu_; + Mutex lb_chand_mu_; // Timeout in milliseconds for the LB call. 0 means no deadline. int lb_call_timeout_ms_ = 0; @@ -1090,7 +1085,6 @@ XdsLb::XdsLb(Args args) : LoadBalancingPolicy(std::move(args)), locality_map_(), locality_serverlist_() { - gpr_mu_init(&lb_chand_mu_); // Record server name. const grpc_arg* arg = grpc_channel_args_find(args.args, GRPC_ARG_SERVER_URI); const char* server_uri = grpc_channel_arg_get_string(arg); @@ -1114,7 +1108,6 @@ XdsLb::XdsLb(Args args) } XdsLb::~XdsLb() { - gpr_mu_destroy(&lb_chand_mu_); gpr_free((void*)server_name_); grpc_channel_args_destroy(args_); locality_serverlist_.clear(); diff --git a/src/core/ext/filters/client_channel/resolving_lb_policy.cc b/src/core/ext/filters/client_channel/resolving_lb_policy.cc index d15af908b3f..a2367e09d9b 100644 --- a/src/core/ext/filters/client_channel/resolving_lb_policy.cc +++ b/src/core/ext/filters/client_channel/resolving_lb_policy.cc @@ -48,7 +48,7 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/manual_constructor.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/polling_entity.h" diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 8bb0c4c3498..3d3815384aa 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -42,8 +42,8 @@ #include "src/core/lib/gpr/alloc.h" #include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/gprpp/manual_constructor.h" -#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" @@ -457,13 +457,14 @@ struct Subchannel::ExternalStateWatcher { grpc_pollset_set_del_pollset_set(w->subchannel->pollset_set_, w->pollset_set); } - gpr_mu_lock(&w->subchannel->mu_); - if (w->subchannel->external_state_watcher_list_ == w) { - w->subchannel->external_state_watcher_list_ = w->next; + { + MutexLock lock(&w->subchannel->mu_); + if (w->subchannel->external_state_watcher_list_ == w) { + w->subchannel->external_state_watcher_list_ = w->next; + } + if (w->next != nullptr) w->next->prev = w->prev; + if (w->prev != nullptr) w->prev->next = w->next; } - if (w->next != nullptr) w->next->prev = w->prev; - if (w->prev != nullptr) w->prev->next = w->next; - gpr_mu_unlock(&w->subchannel->mu_); GRPC_SUBCHANNEL_WEAK_UNREF(w->subchannel, "external_state_watcher+done"); Delete(w); GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error)); @@ -585,7 +586,6 @@ Subchannel::Subchannel(SubchannelKey* key, grpc_connector* connector, "subchannel"); grpc_connectivity_state_init(&state_and_health_tracker_, GRPC_CHANNEL_IDLE, "subchannel"); - gpr_mu_init(&mu_); // Check whether we should enable health checking. const char* service_config_json = grpc_channel_arg_get_string( grpc_channel_args_find(args_, GRPC_ARG_SERVICE_CONFIG)); @@ -629,7 +629,6 @@ Subchannel::~Subchannel() { grpc_connector_unref(connector_); grpc_pollset_set_destroy(pollset_set_); Delete(key_); - gpr_mu_destroy(&mu_); } Subchannel* Subchannel::Create(grpc_connector* connector, @@ -905,7 +904,9 @@ void Subchannel::MaybeStartConnectingLocked() { void Subchannel::OnRetryAlarm(void* arg, grpc_error* error) { Subchannel* c = static_cast(arg); - gpr_mu_lock(&c->mu_); + // TODO(soheilhy): Once subchannel refcounting is simplified, we can get use + // MutexLock instead of ReleasableMutexLock, here. + ReleasableMutexLock lock(&c->mu_); c->have_retry_alarm_ = false; if (c->disconnected_) { error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected", @@ -919,9 +920,9 @@ void Subchannel::OnRetryAlarm(void* arg, grpc_error* error) { if (error == GRPC_ERROR_NONE) { gpr_log(GPR_INFO, "Failed to connect to channel, retrying"); c->ContinueConnectingLocked(); - gpr_mu_unlock(&c->mu_); + lock.Unlock(); } else { - gpr_mu_unlock(&c->mu_); + lock.Unlock(); GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); } GRPC_ERROR_UNREF(error); @@ -948,29 +949,30 @@ void Subchannel::OnConnectingFinished(void* arg, grpc_error* error) { auto* c = static_cast(arg); grpc_channel_args* delete_channel_args = c->connecting_result_.channel_args; GRPC_SUBCHANNEL_WEAK_REF(c, "on_connecting_finished"); - gpr_mu_lock(&c->mu_); - c->connecting_ = false; - if (c->connecting_result_.transport != nullptr && - c->PublishTransportLocked()) { - // Do nothing, transport was published. - } else if (c->disconnected_) { - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); - } else { - const char* errmsg = grpc_error_string(error); - gpr_log(GPR_INFO, "Connect failed: %s", errmsg); - error = - grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Connect Failed", &error, 1), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); - c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, - GRPC_ERROR_REF(error), "connect_failed"); - grpc_connectivity_state_set(&c->state_and_health_tracker_, - GRPC_CHANNEL_TRANSIENT_FAILURE, error, - "connect_failed"); - c->MaybeStartConnectingLocked(); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + { + MutexLock lock(&c->mu_); + c->connecting_ = false; + if (c->connecting_result_.transport != nullptr && + c->PublishTransportLocked()) { + // Do nothing, transport was published. + } else if (c->disconnected_) { + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + } else { + const char* errmsg = grpc_error_string(error); + gpr_log(GPR_INFO, "Connect failed: %s", errmsg); + error = grpc_error_set_int( + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Connect Failed", + &error, 1), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); + c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, + GRPC_ERROR_REF(error), "connect_failed"); + grpc_connectivity_state_set(&c->state_and_health_tracker_, + GRPC_CHANNEL_TRANSIENT_FAILURE, error, + "connect_failed"); + c->MaybeStartConnectingLocked(); + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + } } - gpr_mu_unlock(&c->mu_); GRPC_SUBCHANNEL_WEAK_UNREF(c, "on_connecting_finished"); grpc_channel_args_destroy(delete_channel_args); } diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 968fc74e22a..83b57dd7ff3 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -29,6 +29,7 @@ #include "src/core/lib/gpr/arena.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/transport/connectivity_state.h" @@ -264,7 +265,7 @@ class Subchannel { // pollset_set tracking who's interested in a connection being setup. grpc_pollset_set* pollset_set_; // Protects the other members. - gpr_mu mu_; + Mutex mu_; // Refcount // - lower INTERNAL_REF_BITS bits are for internal references: // these do not keep the subchannel open. diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index 9f0169aeaab..b6a660b18fd 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -23,7 +23,7 @@ #include "src/core/lib/channel/channelz_registry.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/memory.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include #include diff --git a/src/core/lib/channel/handshaker.h b/src/core/lib/channel/handshaker.h index 912d524c8db..b68799b6e0e 100644 --- a/src/core/lib/channel/handshaker.h +++ b/src/core/lib/channel/handshaker.h @@ -27,8 +27,8 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/inlined_vector.h" -#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/exec_ctx.h" diff --git a/src/core/lib/gprpp/mutex_lock.h b/src/core/lib/gprpp/mutex_lock.h deleted file mode 100644 index 54751d5fe46..00000000000 --- a/src/core/lib/gprpp/mutex_lock.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef GRPC_CORE_LIB_GPRPP_MUTEX_LOCK_H -#define GRPC_CORE_LIB_GPRPP_MUTEX_LOCK_H - -#include - -#include - -namespace grpc_core { - -class MutexLock { - public: - explicit MutexLock(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu); } - ~MutexLock() { gpr_mu_unlock(mu_); } - - MutexLock(const MutexLock&) = delete; - MutexLock& operator=(const MutexLock&) = delete; - - private: - gpr_mu* const mu_; -}; - -} // namespace grpc_core - -#endif /* GRPC_CORE_LIB_GPRPP_MUTEX_LOCK_H */ diff --git a/src/core/lib/gprpp/sync.h b/src/core/lib/gprpp/sync.h new file mode 100644 index 00000000000..895ca60fec0 --- /dev/null +++ b/src/core/lib/gprpp/sync.h @@ -0,0 +1,126 @@ +/* + * + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_GPRPP_SYNC_H +#define GRPC_CORE_LIB_GPRPP_SYNC_H + +#include + +#include +#include +#include +#include + +// The core library is not accessible in C++ codegen headers, and vice versa. +// Thus, we need to have duplicate headers with similar functionality. +// Make sure any change to this file is also reflected in +// include/grpcpp/impl/codegen/sync.h. +// +// Whenever possible, prefer using this file over +// since this file doesn't rely on g_core_codegen_interface and hence does not +// pay the costs of virtual function calls. + +namespace grpc_core { + +class Mutex { + public: + Mutex() { gpr_mu_init(&mu_); } + ~Mutex() { gpr_mu_destroy(&mu_); } + + Mutex(const Mutex&) = delete; + Mutex& operator=(const Mutex&) = delete; + + gpr_mu* get() { return &mu_; } + const gpr_mu* get() const { return &mu_; } + + private: + gpr_mu mu_; +}; + +// MutexLock is a std:: +class MutexLock { + public: + explicit MutexLock(Mutex* mu) : mu_(mu->get()) { gpr_mu_lock(mu_); } + explicit MutexLock(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu_); } + ~MutexLock() { gpr_mu_unlock(mu_); } + + MutexLock(const MutexLock&) = delete; + MutexLock& operator=(const MutexLock&) = delete; + + private: + gpr_mu* const mu_; +}; + +class ReleasableMutexLock { + public: + explicit ReleasableMutexLock(Mutex* mu) : mu_(mu->get()) { gpr_mu_lock(mu_); } + explicit ReleasableMutexLock(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu_); } + ~ReleasableMutexLock() { + if (!released_) gpr_mu_unlock(mu_); + } + + ReleasableMutexLock(const ReleasableMutexLock&) = delete; + ReleasableMutexLock& operator=(const ReleasableMutexLock&) = delete; + + void Lock() { + GPR_DEBUG_ASSERT(released_); + gpr_mu_lock(mu_); + released_ = false; + } + + void Unlock() { + GPR_DEBUG_ASSERT(!released_); + released_ = true; + gpr_mu_unlock(mu_); + } + + private: + gpr_mu* const mu_; + bool released_ = false; +}; + +class CondVar { + public: + CondVar() { gpr_cv_init(&cv_); } + ~CondVar() { gpr_cv_destroy(&cv_); } + + CondVar(const CondVar&) = delete; + CondVar& operator=(const CondVar&) = delete; + + void Signal() { gpr_cv_signal(&cv_); } + void Broadcast() { gpr_cv_broadcast(&cv_); } + + int Wait(Mutex* mu) { return Wait(mu, gpr_inf_future(GPR_CLOCK_REALTIME)); } + int Wait(Mutex* mu, const gpr_timespec& deadline) { + return gpr_cv_wait(&cv_, mu->get(), deadline); + } + + template + void WaitUntil(Mutex* mu, Predicate pred) { + while (!pred()) { + Wait(mu, gpr_inf_future(GPR_CLOCK_REALTIME)); + } + } + + private: + gpr_cv cv_; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_GPRPP_SYNC_H */ diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc index 01be46c9f68..c387f8359a0 100644 --- a/src/core/lib/iomgr/ev_epollex_linux.cc +++ b/src/core/lib/iomgr/ev_epollex_linux.cc @@ -47,7 +47,7 @@ #include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/manual_constructor.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/block_annotate.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/is_epollexclusive_available.h" diff --git a/src/core/lib/surface/init.cc b/src/core/lib/surface/init.cc index b67d4f12252..57d975564b1 100644 --- a/src/core/lib/surface/init.cc +++ b/src/core/lib/surface/init.cc @@ -33,7 +33,7 @@ #include "src/core/lib/debug/stats.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/gprpp/fork.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/call_combiner.h" #include "src/core/lib/iomgr/combiner.h" diff --git a/src/core/tsi/ssl/session_cache/ssl_session_cache.cc b/src/core/tsi/ssl/session_cache/ssl_session_cache.cc index f9184bcc34f..ba0745a2359 100644 --- a/src/core/tsi/ssl/session_cache/ssl_session_cache.cc +++ b/src/core/tsi/ssl/session_cache/ssl_session_cache.cc @@ -18,7 +18,7 @@ #include -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/tsi/ssl/session_cache/ssl_session.h" #include "src/core/tsi/ssl/session_cache/ssl_session_cache.h" diff --git a/src/cpp/client/channel_cc.cc b/src/cpp/client/channel_cc.cc index db59d4d8416..2d5e74163a9 100644 --- a/src/cpp/client/channel_cc.cc +++ b/src/cpp/client/channel_cc.cc @@ -232,7 +232,7 @@ class ShutdownCallback : public grpc_experimental_completion_queue_functor { CompletionQueue* Channel::CallbackCQ() { // TODO(vjpai): Consider using a single global CQ for the default CQ // if there is no explicit per-channel CQ registered - std::lock_guard l(mu_); + grpc::internal::MutexLock l(&mu_); if (callback_cq_ == nullptr) { auto* shutdown_callback = new ShutdownCallback; callback_cq_ = new CompletionQueue(grpc_completion_queue_attributes{ diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc index efb59c71a8c..b4fce79b99a 100644 --- a/src/cpp/client/client_context.cc +++ b/src/cpp/client/client_context.cc @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -84,7 +85,7 @@ void ClientContext::AddMetadata(const grpc::string& meta_key, void ClientContext::set_call(grpc_call* call, const std::shared_ptr& channel) { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); GPR_ASSERT(call_ == nullptr); call_ = call; channel_ = channel; @@ -114,7 +115,7 @@ void ClientContext::set_compression_algorithm( } void ClientContext::TryCancel() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); if (call_) { SendCancelToInterceptors(); grpc_call_cancel(call_, nullptr); diff --git a/src/cpp/server/dynamic_thread_pool.cc b/src/cpp/server/dynamic_thread_pool.cc index ef99d6459f7..c8bdbdea7e6 100644 --- a/src/cpp/server/dynamic_thread_pool.cc +++ b/src/cpp/server/dynamic_thread_pool.cc @@ -21,6 +21,7 @@ #include #include +#include #include "src/core/lib/gprpp/thd.h" @@ -40,27 +41,27 @@ DynamicThreadPool::DynamicThread::~DynamicThread() { thd_.Join(); } void DynamicThreadPool::DynamicThread::ThreadFunc() { pool_->ThreadFunc(); // Now that we have killed ourselves, we should reduce the thread count - std::unique_lock lock(pool_->mu_); + grpc_core::MutexLock lock(&pool_->mu_); pool_->nthreads_--; // Move ourselves to dead list pool_->dead_threads_.push_back(this); if ((pool_->shutdown_) && (pool_->nthreads_ == 0)) { - pool_->shutdown_cv_.notify_one(); + pool_->shutdown_cv_.Signal(); } } void DynamicThreadPool::ThreadFunc() { for (;;) { // Wait until work is available or we are shutting down. - std::unique_lock lock(mu_); + grpc_core::ReleasableMutexLock lock(&mu_); if (!shutdown_ && callbacks_.empty()) { // If there are too many threads waiting, then quit this thread if (threads_waiting_ >= reserve_threads_) { break; } threads_waiting_++; - cv_.wait(lock); + cv_.Wait(&mu_); threads_waiting_--; } // Drain callbacks before considering shutdown to ensure all work @@ -68,7 +69,7 @@ void DynamicThreadPool::ThreadFunc() { if (!callbacks_.empty()) { auto cb = callbacks_.front(); callbacks_.pop(); - lock.unlock(); + lock.Unlock(); cb(); } else if (shutdown_) { break; @@ -82,7 +83,7 @@ DynamicThreadPool::DynamicThreadPool(int reserve_threads) nthreads_(0), threads_waiting_(0) { for (int i = 0; i < reserve_threads_; i++) { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); nthreads_++; new DynamicThread(this); } @@ -95,17 +96,17 @@ void DynamicThreadPool::ReapThreads(std::list* tlist) { } DynamicThreadPool::~DynamicThreadPool() { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); shutdown_ = true; - cv_.notify_all(); + cv_.Broadcast(); while (nthreads_ != 0) { - shutdown_cv_.wait(lock); + shutdown_cv_.Wait(&mu_); } ReapThreads(&dead_threads_); } void DynamicThreadPool::Add(const std::function& callback) { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); // Add works to the callbacks list callbacks_.push(callback); // Increase pool size or notify as needed @@ -114,7 +115,7 @@ void DynamicThreadPool::Add(const std::function& callback) { nthreads_++; new DynamicThread(this); } else { - cv_.notify_one(); + cv_.Signal(); } // Also use this chance to harvest dead threads if (!dead_threads_.empty()) { diff --git a/src/cpp/server/dynamic_thread_pool.h b/src/cpp/server/dynamic_thread_pool.h index 5df8cf2b043..4ae0257d40b 100644 --- a/src/cpp/server/dynamic_thread_pool.h +++ b/src/cpp/server/dynamic_thread_pool.h @@ -27,6 +27,7 @@ #include +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/thd.h" #include "src/cpp/server/thread_pool_interface.h" @@ -50,9 +51,9 @@ class DynamicThreadPool final : public ThreadPoolInterface { grpc_core::Thread thd_; void ThreadFunc(); }; - std::mutex mu_; - std::condition_variable cv_; - std::condition_variable shutdown_cv_; + grpc_core::Mutex mu_; + grpc_core::CondVar cv_; + grpc_core::CondVar shutdown_cv_; bool shutdown_; std::queue> callbacks_; int reserve_threads_; diff --git a/src/cpp/server/health/default_health_check_service.cc b/src/cpp/server/health/default_health_check_service.cc index 44aebd2f9d9..01bc51aa213 100644 --- a/src/cpp/server/health/default_health_check_service.cc +++ b/src/cpp/server/health/default_health_check_service.cc @@ -41,7 +41,7 @@ DefaultHealthCheckService::DefaultHealthCheckService() { void DefaultHealthCheckService::SetServingStatus( const grpc::string& service_name, bool serving) { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); if (shutdown_) { // Set to NOT_SERVING in case service_name is not in the map. serving = false; @@ -51,7 +51,7 @@ void DefaultHealthCheckService::SetServingStatus( void DefaultHealthCheckService::SetServingStatus(bool serving) { const ServingStatus status = serving ? SERVING : NOT_SERVING; - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); if (shutdown_) { return; } @@ -62,7 +62,7 @@ void DefaultHealthCheckService::SetServingStatus(bool serving) { } void DefaultHealthCheckService::Shutdown() { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); if (shutdown_) { return; } @@ -76,7 +76,7 @@ void DefaultHealthCheckService::Shutdown() { DefaultHealthCheckService::ServingStatus DefaultHealthCheckService::GetServingStatus( const grpc::string& service_name) const { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); auto it = services_map_.find(service_name); if (it == services_map_.end()) { return NOT_FOUND; @@ -88,7 +88,7 @@ DefaultHealthCheckService::GetServingStatus( void DefaultHealthCheckService::RegisterCallHandler( const grpc::string& service_name, std::shared_ptr handler) { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); ServiceData& service_data = services_map_[service_name]; service_data.AddCallHandler(handler /* copies ref */); HealthCheckServiceImpl::CallHandler* h = handler.get(); @@ -98,7 +98,7 @@ void DefaultHealthCheckService::RegisterCallHandler( void DefaultHealthCheckService::UnregisterCallHandler( const grpc::string& service_name, const std::shared_ptr& handler) { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); auto it = services_map_.find(service_name); if (it == services_map_.end()) return; ServiceData& service_data = it->second; @@ -166,7 +166,7 @@ DefaultHealthCheckService::HealthCheckServiceImpl::~HealthCheckServiceImpl() { // We will reach here after the server starts shutting down. shutdown_ = true; { - std::unique_lock lock(cq_shutdown_mu_); + grpc_core::MutexLock lock(&cq_shutdown_mu_); cq_->Shutdown(); } thread_->Join(); @@ -266,7 +266,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::CheckCallHandler:: std::make_shared(cq, database, service); CheckCallHandler* handler = static_cast(self.get()); { - std::unique_lock lock(service->cq_shutdown_mu_); + grpc_core::MutexLock lock(&service->cq_shutdown_mu_); if (service->shutdown_) return; // Request a Check() call. handler->next_ = @@ -311,7 +311,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::CheckCallHandler:: } // Send response. { - std::unique_lock lock(service_->cq_shutdown_mu_); + grpc_core::MutexLock lock(&service_->cq_shutdown_mu_); if (!service_->shutdown_) { next_ = CallableTag(std::bind(&CheckCallHandler::OnFinishDone, this, @@ -347,7 +347,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: std::make_shared(cq, database, service); WatchCallHandler* handler = static_cast(self.get()); { - std::unique_lock lock(service->cq_shutdown_mu_); + grpc_core::MutexLock lock(&service->cq_shutdown_mu_); if (service->shutdown_) return; // Request AsyncNotifyWhenDone(). handler->on_done_notified_ = @@ -402,7 +402,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: SendHealth(std::shared_ptr self, ServingStatus status) { - std::unique_lock lock(send_mu_); + grpc_core::MutexLock lock(&send_mu_); // If there's already a send in flight, cache the new status, and // we'll start a new send for it when the one in flight completes. if (send_in_flight_) { @@ -420,7 +420,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: ByteBuffer response; bool success = service_->EncodeResponse(status, &response); // Grab shutdown lock and send response. - std::unique_lock cq_lock(service_->cq_shutdown_mu_); + grpc_core::MutexLock cq_lock(&service_->cq_shutdown_mu_); if (service_->shutdown_) { SendFinishLocked(std::move(self), Status::CANCELLED); return; @@ -442,7 +442,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: SendFinish(std::move(self), Status::CANCELLED); return; } - std::unique_lock lock(send_mu_); + grpc_core::MutexLock lock(&send_mu_); send_in_flight_ = false; // If we got a new status since we started the last send, start a // new send for it. @@ -456,7 +456,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: SendFinish(std::shared_ptr self, const Status& status) { if (finish_called_) return; - std::unique_lock cq_lock(service_->cq_shutdown_mu_); + grpc_core::MutexLock cq_lock(&service_->cq_shutdown_mu_); if (service_->shutdown_) return; SendFinishLocked(std::move(self), status); } diff --git a/src/cpp/server/health/default_health_check_service.h b/src/cpp/server/health/default_health_check_service.h index 9551cd2e2cf..4b926efdfe8 100644 --- a/src/cpp/server/health/default_health_check_service.h +++ b/src/cpp/server/health/default_health_check_service.h @@ -31,6 +31,7 @@ #include #include +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/thd.h" namespace grpc { @@ -197,7 +198,7 @@ class DefaultHealthCheckService final : public HealthCheckServiceInterface { GenericServerAsyncWriter stream_; ServerContext ctx_; - std::mutex send_mu_; + grpc_core::Mutex send_mu_; bool send_in_flight_ = false; // Guarded by mu_. ServingStatus pending_status_ = NOT_FOUND; // Guarded by mu_. @@ -226,7 +227,7 @@ class DefaultHealthCheckService final : public HealthCheckServiceInterface { // To synchronize the operations related to shutdown state of cq_, so that // we don't enqueue new tags into cq_ after it is already shut down. - std::mutex cq_shutdown_mu_; + grpc_core::Mutex cq_shutdown_mu_; std::atomic_bool shutdown_{false}; std::unique_ptr<::grpc_core::Thread> thread_; }; @@ -273,7 +274,7 @@ class DefaultHealthCheckService final : public HealthCheckServiceInterface { const grpc::string& service_name, const std::shared_ptr& handler); - mutable std::mutex mu_; + mutable grpc_core::Mutex mu_; bool shutdown_ = false; // Guarded by mu_. std::map services_map_; // Guarded by mu_. std::unique_ptr impl_; diff --git a/src/cpp/server/load_reporter/load_reporter.cc b/src/cpp/server/load_reporter/load_reporter.cc index 464063a13ff..422ea62efd5 100644 --- a/src/cpp/server/load_reporter/load_reporter.cc +++ b/src/cpp/server/load_reporter/load_reporter.cc @@ -239,7 +239,7 @@ grpc::string LoadReporter::GenerateLbId() { ::grpc::lb::v1::LoadBalancingFeedback LoadReporter::GenerateLoadBalancingFeedback() { - std::unique_lock lock(feedback_mu_); + grpc_core::ReleasableMutexLock lock(&feedback_mu_); auto now = std::chrono::system_clock::now(); // Discard records outside the window until there is only one record // outside the window, which is used as the base for difference. @@ -277,7 +277,7 @@ LoadReporter::GenerateLoadBalancingFeedback() { double cpu_limit = newest->cpu_limit - oldest->cpu_limit; std::chrono::duration duration_seconds = newest->end_time - oldest->end_time; - lock.unlock(); + lock.Unlock(); ::grpc::lb::v1::LoadBalancingFeedback feedback; feedback.set_server_utilization(static_cast(cpu_usage / cpu_limit)); feedback.set_calls_per_second( @@ -290,7 +290,7 @@ LoadReporter::GenerateLoadBalancingFeedback() { ::google::protobuf::RepeatedPtrField<::grpc::lb::v1::Load> LoadReporter::GenerateLoads(const grpc::string& hostname, const grpc::string& lb_id) { - std::lock_guard lock(store_mu_); + grpc_core::MutexLock lock(&store_mu_); auto assigned_stores = load_data_store_.GetAssignedStores(hostname, lb_id); GPR_ASSERT(assigned_stores != nullptr); GPR_ASSERT(!assigned_stores->empty()); @@ -371,7 +371,7 @@ void LoadReporter::AppendNewFeedbackRecord(uint64_t rpcs, uint64_t errors) { // This will make the load balancing feedback generation a no-op. cpu_stats = {0, 0}; } - std::unique_lock lock(feedback_mu_); + grpc_core::MutexLock lock(&feedback_mu_); feedback_records_.emplace_back(std::chrono::system_clock::now(), rpcs, errors, cpu_stats.first, cpu_stats.second); } @@ -379,7 +379,7 @@ void LoadReporter::AppendNewFeedbackRecord(uint64_t rpcs, uint64_t errors) { void LoadReporter::ReportStreamCreated(const grpc::string& hostname, const grpc::string& lb_id, const grpc::string& load_key) { - std::lock_guard lock(store_mu_); + grpc_core::MutexLock lock(&store_mu_); load_data_store_.ReportStreamCreated(hostname, lb_id, load_key); gpr_log(GPR_INFO, "[LR %p] Report stream created (host: %s, LB ID: %s, load key: %s).", @@ -388,7 +388,7 @@ void LoadReporter::ReportStreamCreated(const grpc::string& hostname, void LoadReporter::ReportStreamClosed(const grpc::string& hostname, const grpc::string& lb_id) { - std::lock_guard lock(store_mu_); + grpc_core::MutexLock lock(&store_mu_); load_data_store_.ReportStreamClosed(hostname, lb_id); gpr_log(GPR_INFO, "[LR %p] Report stream closed (host: %s, LB ID: %s).", this, hostname.c_str(), lb_id.c_str()); @@ -407,7 +407,7 @@ void LoadReporter::ProcessViewDataCallStart( LoadRecordKey key(client_ip_and_token, user_id); LoadRecordValue value = LoadRecordValue(start_count); { - std::unique_lock lock(store_mu_); + grpc_core::MutexLock lock(&store_mu_); load_data_store_.MergeRow(host, key, value); } } @@ -459,7 +459,7 @@ void LoadReporter::ProcessViewDataCallEnd( LoadRecordValue value = LoadRecordValue( 0, ok_count, error_count, bytes_sent, bytes_received, latency_ms); { - std::unique_lock lock(store_mu_); + grpc_core::MutexLock lock(&store_mu_); load_data_store_.MergeRow(host, key, value); } } @@ -486,7 +486,7 @@ void LoadReporter::ProcessViewDataOtherCallMetrics( LoadRecordValue value = LoadRecordValue( metric_name, static_cast(num_calls), total_metric_value); { - std::unique_lock lock(store_mu_); + grpc_core::MutexLock lock(&store_mu_); load_data_store_.MergeRow(host, key, value); } } diff --git a/src/cpp/server/load_reporter/load_reporter.h b/src/cpp/server/load_reporter/load_reporter.h index b2254d56016..766e02a407a 100644 --- a/src/cpp/server/load_reporter/load_reporter.h +++ b/src/cpp/server/load_reporter/load_reporter.h @@ -29,6 +29,7 @@ #include #include +#include "src/core/lib/gprpp/sync.h" #include "src/cpp/server/load_reporter/load_data_store.h" #include "src/proto/grpc/lb/v1/load_reporter.grpc.pb.h" @@ -212,11 +213,11 @@ class LoadReporter { std::atomic next_lb_id_{0}; const std::chrono::seconds feedback_sample_window_seconds_; - std::mutex feedback_mu_; + grpc_core::Mutex feedback_mu_; std::deque feedback_records_; // TODO(juanlishen): Lock in finer grain. Locking the whole store may be // too expensive. - std::mutex store_mu_; + grpc_core::Mutex store_mu_; LoadDataStore load_data_store_; std::unique_ptr census_view_provider_; std::unique_ptr cpu_stats_provider_; diff --git a/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc b/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc index 859ad9946c8..9eaab5d6366 100644 --- a/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc +++ b/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc @@ -48,7 +48,7 @@ LoadReporterAsyncServiceImpl::~LoadReporterAsyncServiceImpl() { // We will reach here after the server starts shutting down. shutdown_ = true; { - std::unique_lock lock(cq_shutdown_mu_); + grpc_core::MutexLock lock(&cq_shutdown_mu_); cq_->Shutdown(); } if (next_fetch_and_sample_alarm_ != nullptr) @@ -62,7 +62,7 @@ void LoadReporterAsyncServiceImpl::ScheduleNextFetchAndSample() { gpr_time_from_millis(kFetchAndSampleIntervalSeconds * 1000, GPR_TIMESPAN)); { - std::unique_lock lock(cq_shutdown_mu_); + grpc_core::MutexLock lock(&cq_shutdown_mu_); if (shutdown_) return; // TODO(juanlishen): Improve the Alarm implementation to reuse a single // instance for multiple events. @@ -119,7 +119,7 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::CreateAndStart( std::make_shared(cq, service, load_reporter); ReportLoadHandler* p = handler.get(); { - std::unique_lock lock(service->cq_shutdown_mu_); + grpc_core::MutexLock lock(&service->cq_shutdown_mu_); if (service->shutdown_) return; p->on_done_notified_ = CallableTag(std::bind(&ReportLoadHandler::OnDoneNotified, p, @@ -164,9 +164,9 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::OnRequestDelivered( // instance will deallocate itself when it's done. CreateAndStart(cq_, service_, load_reporter_); { - std::unique_lock lock(service_->cq_shutdown_mu_); + grpc_core::ReleasableMutexLock lock(&service_->cq_shutdown_mu_); if (service_->shutdown_) { - lock.release()->unlock(); + lock.Unlock(); Shutdown(std::move(self), "OnRequestDelivered"); return; } @@ -222,9 +222,9 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::OnReadDone( SendReport(self, true /* ok */); // Expect this read to fail. { - std::unique_lock lock(service_->cq_shutdown_mu_); + grpc_core::ReleasableMutexLock lock(&service_->cq_shutdown_mu_); if (service_->shutdown_) { - lock.release()->unlock(); + lock.Unlock(); Shutdown(std::move(self), "OnReadDone"); return; } @@ -254,9 +254,9 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::ScheduleNextReport( gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_millis(load_report_interval_ms_, GPR_TIMESPAN)); { - std::unique_lock lock(service_->cq_shutdown_mu_); + grpc_core::ReleasableMutexLock lock(&service_->cq_shutdown_mu_); if (service_->shutdown_) { - lock.release()->unlock(); + lock.Unlock(); Shutdown(std::move(self), "ScheduleNextReport"); return; } @@ -294,9 +294,9 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::SendReport( call_status_ = INITIAL_RESPONSE_SENT; } { - std::unique_lock lock(service_->cq_shutdown_mu_); + grpc_core::ReleasableMutexLock lock(&service_->cq_shutdown_mu_); if (service_->shutdown_) { - lock.release()->unlock(); + lock.Unlock(); Shutdown(std::move(self), "SendReport"); return; } @@ -342,7 +342,7 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::Shutdown( // OnRequestDelivered() may be called after OnDoneNotified(), so we need to // try to Finish() every time we are in Shutdown(). if (call_status_ >= DELIVERED && call_status_ < FINISH_CALLED) { - std::unique_lock lock(service_->cq_shutdown_mu_); + grpc_core::MutexLock lock(&service_->cq_shutdown_mu_); if (!service_->shutdown_) { on_finish_done_ = CallableTag(std::bind(&ReportLoadHandler::OnFinishDone, this, diff --git a/src/cpp/server/load_reporter/load_reporter_async_service_impl.h b/src/cpp/server/load_reporter/load_reporter_async_service_impl.h index 6fc577ff493..3087cbfc04d 100644 --- a/src/cpp/server/load_reporter/load_reporter_async_service_impl.h +++ b/src/cpp/server/load_reporter/load_reporter_async_service_impl.h @@ -25,6 +25,7 @@ #include #include +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/thd.h" #include "src/cpp/server/load_reporter/load_reporter.h" @@ -181,7 +182,7 @@ class LoadReporterAsyncServiceImpl std::unique_ptr cq_; // To synchronize the operations related to shutdown state of cq_, so that we // don't enqueue new tags into cq_ after it is already shut down. - std::mutex cq_shutdown_mu_; + grpc_core::Mutex cq_shutdown_mu_; std::atomic_bool shutdown_{false}; std::unique_ptr<::grpc_core::Thread> thread_; std::unique_ptr load_reporter_; diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 734940c248d..4f0fdefceda 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -561,9 +561,9 @@ class Server::CallbackRequest final : public Server::CallbackRequestBase { // The counter of outstanding requests must be decremented // under a lock in case it causes the server shutdown. - std::lock_guard l(server_->callback_reqs_mu_); + grpc::internal::MutexLock l(&server_->callback_reqs_mu_); if (--server_->callback_reqs_outstanding_ == 0) { - server_->callback_reqs_done_cv_.notify_one(); + server_->callback_reqs_done_cv_.Signal(); } } @@ -992,12 +992,12 @@ Server::Server( Server::~Server() { { - std::unique_lock lock(mu_); + grpc::internal::ReleasableMutexLock lock(&mu_); if (callback_cq_ != nullptr) { callback_cq_->Shutdown(); } if (started_ && !shutdown_) { - lock.unlock(); + lock.Unlock(); Shutdown(); } else if (!started_) { // Shutdown the completion queues @@ -1233,7 +1233,7 @@ void Server::Start(grpc::ServerCompletionQueue** cqs, size_t num_cqs) { } void Server::ShutdownInternal(gpr_timespec deadline) { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); if (shutdown_) { return; } @@ -1284,9 +1284,9 @@ void Server::ShutdownInternal(gpr_timespec deadline) { // will report a failure, indicating a shutdown and again we won't end // up incrementing the counter. { - std::unique_lock cblock(callback_reqs_mu_); - callback_reqs_done_cv_.wait( - cblock, [this] { return callback_reqs_outstanding_ == 0; }); + grpc::internal::MutexLock cblock(&callback_reqs_mu_); + callback_reqs_done_cv_.WaitUntil( + &callback_reqs_mu_, [this] { return callback_reqs_outstanding_ == 0; }); } // Drain the shutdown queue (if the previous call to AsyncNext() timed out @@ -1296,13 +1296,13 @@ void Server::ShutdownInternal(gpr_timespec deadline) { } shutdown_notified_ = true; - shutdown_cv_.notify_all(); + shutdown_cv_.Broadcast(); } void Server::Wait() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); while (started_ && !shutdown_notified_) { - shutdown_cv_.wait(lock); + shutdown_cv_.Wait(&mu_); } } @@ -1342,7 +1342,7 @@ grpc::ServerInitializer* Server::initializer() { grpc::CompletionQueue* Server::CallbackCQ() { // TODO(vjpai): Consider using a single global CQ for the default CQ // if there is no explicit per-server CQ registered - std::lock_guard l(mu_); + grpc::internal::MutexLock l(&mu_); if (callback_cq_ == nullptr) { auto* shutdown_callback = new grpc::ShutdownCallback; callback_cq_ = new grpc::CompletionQueue(grpc_completion_queue_attributes{ diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc index 73fd6a62c48..70c5cd8861e 100644 --- a/src/cpp/server/server_context.cc +++ b/src/cpp/server/server_context.cc @@ -33,6 +33,7 @@ #include #include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/surface/call.h" namespace grpc { @@ -96,7 +97,7 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { } void SetCancelCallback(std::function callback) { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); if (finalized_ && (cancelled_ != 0)) { callback(); @@ -107,7 +108,7 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { } void ClearCancelCallback() { - std::lock_guard g(mu_); + grpc_core::MutexLock g(&mu_); cancel_callback_ = nullptr; } @@ -144,7 +145,7 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { private: bool CheckCancelledNoPluck() { - std::lock_guard g(mu_); + grpc_core::MutexLock lock(&mu_); return finalized_ ? (cancelled_ != 0) : false; } @@ -154,7 +155,7 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { void* tag_; void* core_cq_tag_; grpc_core::RefCount refs_; - std::mutex mu_; + grpc_core::Mutex mu_; bool finalized_; int cancelled_; // This is an int (not bool) because it is passed to core std::function cancel_callback_; @@ -186,7 +187,7 @@ void ServerContext::CompletionOp::FillOps(internal::Call* call) { bool ServerContext::CompletionOp::FinalizeResult(void** tag, bool* status) { bool ret = false; - std::unique_lock lock(mu_); + grpc_core::ReleasableMutexLock lock(&mu_); if (done_intercepting_) { /* We are done intercepting. */ if (has_tag_) { @@ -216,12 +217,11 @@ bool ServerContext::CompletionOp::FinalizeResult(void** tag, bool* status) { // Release the lock since we are going to be calling a callback and // interceptors now - lock.unlock(); + lock.Unlock(); if (call_cancel && reactor_ != nullptr) { reactor_->OnCancel(); } - /* Add interception point and run through interceptors */ interceptor_methods_.AddInterceptionHookPoint( experimental::InterceptionHookPoints::POST_RECV_CLOSE); diff --git a/src/cpp/thread_manager/thread_manager.cc b/src/cpp/thread_manager/thread_manager.cc index 3e8606a76fd..2b65352f797 100644 --- a/src/cpp/thread_manager/thread_manager.cc +++ b/src/cpp/thread_manager/thread_manager.cc @@ -62,7 +62,7 @@ ThreadManager::ThreadManager(const char* name, ThreadManager::~ThreadManager() { { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); GPR_ASSERT(num_threads_ == 0); } @@ -72,38 +72,38 @@ ThreadManager::~ThreadManager() { } void ThreadManager::Wait() { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); while (num_threads_ != 0) { - shutdown_cv_.wait(lock); + shutdown_cv_.Wait(&mu_); } } void ThreadManager::Shutdown() { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); shutdown_ = true; } bool ThreadManager::IsShutdown() { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); return shutdown_; } int ThreadManager::GetMaxActiveThreadsSoFar() { - std::lock_guard list_lock(list_mu_); + grpc_core::MutexLock list_lock(&list_mu_); return max_active_threads_sofar_; } void ThreadManager::MarkAsCompleted(WorkerThread* thd) { { - std::lock_guard list_lock(list_mu_); + grpc_core::MutexLock list_lock(&list_mu_); completed_threads_.push_back(thd); } { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); num_threads_--; if (num_threads_ == 0) { - shutdown_cv_.notify_one(); + shutdown_cv_.Signal(); } } @@ -116,7 +116,7 @@ void ThreadManager::CleanupCompletedThreads() { { // swap out the completed threads list: allows other threads to clean up // more quickly - std::unique_lock lock(list_mu_); + grpc_core::MutexLock lock(&list_mu_); completed_threads.swap(completed_threads_); } for (auto thd : completed_threads) delete thd; @@ -132,7 +132,7 @@ void ThreadManager::Initialize() { } { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); num_pollers_ = min_pollers_; num_threads_ = min_pollers_; max_active_threads_sofar_ = min_pollers_; @@ -149,7 +149,7 @@ void ThreadManager::MainWorkLoop() { bool ok; WorkStatus work_status = PollForWork(&tag, &ok); - std::unique_lock lock(mu_); + grpc_core::ReleasableMutexLock lock(&mu_); // Reduce the number of pollers by 1 and check what happened with the poll num_pollers_--; bool done = false; @@ -176,30 +176,30 @@ void ThreadManager::MainWorkLoop() { max_active_threads_sofar_ = num_threads_; } // Drop lock before spawning thread to avoid contention - lock.unlock(); + lock.Unlock(); new WorkerThread(this); } else if (num_pollers_ > 0) { // There is still at least some thread polling, so we can go on // even though we are below the number of pollers that we would // like to have (min_pollers_) - lock.unlock(); + lock.Unlock(); } else { // There are no pollers to spare and we couldn't allocate // a new thread, so resources are exhausted! - lock.unlock(); + lock.Unlock(); resource_exhausted = true; } } else { // There are a sufficient number of pollers available so we can do // the work and continue polling with our existing poller threads - lock.unlock(); + lock.Unlock(); } // Lock is always released at this point - do the application work // or return resource exhausted if there is new work but we couldn't // get a thread in which to do it. DoWork(tag, ok, !resource_exhausted); // Take the lock again to check post conditions - lock.lock(); + lock.Lock(); // If we're shutdown, we should finish at this point. if (shutdown_) done = true; break; diff --git a/src/cpp/thread_manager/thread_manager.h b/src/cpp/thread_manager/thread_manager.h index 6f0bd17c5fe..2fbf309d421 100644 --- a/src/cpp/thread_manager/thread_manager.h +++ b/src/cpp/thread_manager/thread_manager.h @@ -26,6 +26,7 @@ #include +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/thd.h" #include "src/core/lib/iomgr/resource_quota.h" @@ -140,10 +141,10 @@ class ThreadManager { // Protects shutdown_, num_pollers_, num_threads_ and // max_active_threads_sofar_ - std::mutex mu_; + grpc_core::Mutex mu_; bool shutdown_; - std::condition_variable shutdown_cv_; + grpc_core::CondVar shutdown_cv_; // The resource user object to use when requesting quota to create threads // @@ -169,7 +170,7 @@ class ThreadManager { // ever set so far int max_active_threads_sofar_; - std::mutex list_mu_; + grpc_core::Mutex list_mu_; std::list completed_threads_; }; diff --git a/test/cpp/client/client_channel_stress_test.cc b/test/cpp/client/client_channel_stress_test.cc index 91419cb257b..d326b2ed37e 100644 --- a/test/cpp/client/client_channel_stress_test.cc +++ b/test/cpp/client/client_channel_stress_test.cc @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -168,24 +169,24 @@ class ClientChannelStressTest { explicit ServerThread(const grpc::string& type, const grpc::string& server_host, T* service) : type_(type), service_(service) { - std::mutex mu; + grpc::internal::Mutex mu; // We need to acquire the lock here in order to prevent the notify_one // by ServerThread::Start from firing before the wait below is hit. - std::unique_lock lock(mu); + grpc::internal::MutexLock lock(&mu); port_ = grpc_pick_unused_port_or_die(); gpr_log(GPR_INFO, "starting %s server on port %d", type_.c_str(), port_); - std::condition_variable cond; + grpc::internal::CondVar cond; thread_.reset(new std::thread( std::bind(&ServerThread::Start, this, server_host, &mu, &cond))); - cond.wait(lock); + cond.Wait(&mu); gpr_log(GPR_INFO, "%s server startup complete", type_.c_str()); } - void Start(const grpc::string& server_host, std::mutex* mu, - std::condition_variable* cond) { + void Start(const grpc::string& server_host, grpc::internal::Mutex* mu, + grpc::internal::CondVar* cond) { // We need to acquire the lock here in order to prevent the notify_one // below from firing before its corresponding wait is executed. - std::lock_guard lock(*mu); + grpc::internal::MutexLock lock(mu); std::ostringstream server_address; server_address << server_host << ":" << port_; ServerBuilder builder; @@ -193,7 +194,7 @@ class ClientChannelStressTest { InsecureServerCredentials()); builder.RegisterService(service_); server_ = builder.BuildAndStart(); - cond->notify_one(); + cond->Signal(); } void Shutdown() { diff --git a/test/cpp/end2end/client_lb_end2end_test.cc b/test/cpp/end2end/client_lb_end2end_test.cc index 77f9db94acc..6623a2ff55f 100644 --- a/test/cpp/end2end/client_lb_end2end_test.cc +++ b/test/cpp/end2end/client_lb_end2end_test.cc @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -98,7 +99,7 @@ class MyTestServiceImpl : public TestServiceImpl { Status Echo(ServerContext* context, const EchoRequest* request, EchoResponse* response) override { { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); ++request_count_; } AddClient(context->peer()); @@ -106,29 +107,29 @@ class MyTestServiceImpl : public TestServiceImpl { } int request_count() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); return request_count_; } void ResetCounters() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); request_count_ = 0; } std::set clients() { - std::unique_lock lock(clients_mu_); + grpc::internal::MutexLock lock(&clients_mu_); return clients_; } private: void AddClient(const grpc::string& client) { - std::unique_lock lock(clients_mu_); + grpc::internal::MutexLock lock(&clients_mu_); clients_.insert(client); } - std::mutex mu_; + grpc::internal::Mutex mu_; int request_count_; - std::mutex clients_mu_; + grpc::internal::Mutex clients_mu_; std::set clients_; }; @@ -293,18 +294,18 @@ class ClientLbEnd2endTest : public ::testing::Test { void Start(const grpc::string& server_host) { gpr_log(GPR_INFO, "starting server on port %d", port_); started_ = true; - std::mutex mu; - std::unique_lock lock(mu); - std::condition_variable cond; + grpc::internal::Mutex mu; + grpc::internal::MutexLock lock(&mu); + grpc::internal::CondVar cond; thread_.reset(new std::thread( std::bind(&ServerData::Serve, this, server_host, &mu, &cond))); - cond.wait(lock, [this] { return server_ready_; }); + cond.WaitUntil(&mu, [this] { return server_ready_; }); server_ready_ = false; gpr_log(GPR_INFO, "server startup complete"); } - void Serve(const grpc::string& server_host, std::mutex* mu, - std::condition_variable* cond) { + void Serve(const grpc::string& server_host, grpc::internal::Mutex* mu, + grpc::internal::CondVar* cond) { std::ostringstream server_address; server_address << server_host << ":" << port_; ServerBuilder builder; @@ -313,9 +314,9 @@ class ClientLbEnd2endTest : public ::testing::Test { builder.AddListeningPort(server_address.str(), std::move(creds)); builder.RegisterService(&service_); server_ = builder.BuildAndStart(); - std::lock_guard lock(*mu); + grpc::internal::MutexLock lock(mu); server_ready_ = true; - cond->notify_one(); + cond->Signal(); } void Shutdown() { @@ -1374,7 +1375,7 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest { void TearDown() override { ClientLbEnd2endTest::TearDown(); } int trailers_intercepted() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); return trailers_intercepted_; } @@ -1382,11 +1383,11 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest { static void ReportTrailerIntercepted(void* arg) { ClientLbInterceptTrailingMetadataTest* self = static_cast(arg); - std::unique_lock lock(self->mu_); + grpc::internal::MutexLock lock(&self->mu_); self->trailers_intercepted_++; } - std::mutex mu_; + grpc::internal::Mutex mu_; int trailers_intercepted_ = 0; }; diff --git a/test/cpp/end2end/grpclb_end2end_test.cc b/test/cpp/end2end/grpclb_end2end_test.cc index ee8b3e1e52b..6d470785ec2 100644 --- a/test/cpp/end2end/grpclb_end2end_test.cc +++ b/test/cpp/end2end/grpclb_end2end_test.cc @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -85,32 +86,32 @@ template class CountedService : public ServiceType { public: size_t request_count() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); return request_count_; } size_t response_count() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); return response_count_; } void IncreaseResponseCount() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); ++response_count_; } void IncreaseRequestCount() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); ++request_count_; } void ResetCounters() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); request_count_ = 0; response_count_ = 0; } protected: - std::mutex mu_; + grpc::internal::Mutex mu_; private: size_t request_count_ = 0; @@ -148,18 +149,18 @@ class BackendServiceImpl : public BackendService { void Shutdown() {} std::set clients() { - std::unique_lock lock(clients_mu_); + grpc::internal::MutexLock lock(&clients_mu_); return clients_; } private: void AddClient(const grpc::string& client) { - std::unique_lock lock(clients_mu_); + grpc::internal::MutexLock lock(&clients_mu_); clients_.insert(client); } - std::mutex mu_; - std::mutex clients_mu_; + grpc::internal::Mutex mu_; + grpc::internal::Mutex clients_mu_; std::set clients_; }; @@ -210,7 +211,7 @@ class BalancerServiceImpl : public BalancerService { Status BalanceLoad(ServerContext* context, Stream* stream) override { gpr_log(GPR_INFO, "LB[%p]: BalanceLoad", this); { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); if (serverlist_done_) goto done; } { @@ -237,7 +238,7 @@ class BalancerServiceImpl : public BalancerService { } { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); responses_and_delays = responses_and_delays_; } for (const auto& response_and_delay : responses_and_delays) { @@ -245,8 +246,8 @@ class BalancerServiceImpl : public BalancerService { response_and_delay.second); } { - std::unique_lock lock(mu_); - serverlist_cond_.wait(lock, [this] { return serverlist_done_; }); + grpc::internal::MutexLock lock(&mu_); + serverlist_cond_.WaitUntil(&mu_, [this] { return serverlist_done_; }); } if (client_load_reporting_interval_seconds_ > 0) { @@ -257,7 +258,7 @@ class BalancerServiceImpl : public BalancerService { GPR_ASSERT(request.has_client_stats()); // We need to acquire the lock here in order to prevent the notify_one // below from firing before its corresponding wait is executed. - std::lock_guard lock(mu_); + grpc::internal::MutexLock lock(&mu_); client_stats_.num_calls_started += request.client_stats().num_calls_started(); client_stats_.num_calls_finished += @@ -274,7 +275,7 @@ class BalancerServiceImpl : public BalancerService { drop_token_count.num_calls(); } load_report_ready_ = true; - load_report_cond_.notify_one(); + load_report_cond_.Signal(); } } } @@ -284,12 +285,12 @@ class BalancerServiceImpl : public BalancerService { } void add_response(const LoadBalanceResponse& response, int send_after_ms) { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); responses_and_delays_.push_back(std::make_pair(response, send_after_ms)); } void Start() { - std::lock_guard lock(mu_); + grpc::internal::MutexLock lock(&mu_); serverlist_done_ = false; load_report_ready_ = false; responses_and_delays_.clear(); @@ -326,17 +327,17 @@ class BalancerServiceImpl : public BalancerService { } const ClientStats& WaitForLoadReport() { - std::unique_lock lock(mu_); - load_report_cond_.wait(lock, [this] { return load_report_ready_; }); + grpc::internal::MutexLock lock(&mu_); + load_report_cond_.WaitUntil(&mu_, [this] { return load_report_ready_; }); load_report_ready_ = false; return client_stats_; } void NotifyDoneWithServerlists() { - std::lock_guard lock(mu_); + grpc::internal::MutexLock lock(&mu_); if (!serverlist_done_) { serverlist_done_ = true; - serverlist_cond_.notify_all(); + serverlist_cond_.Broadcast(); } } @@ -355,10 +356,10 @@ class BalancerServiceImpl : public BalancerService { const int client_load_reporting_interval_seconds_; std::vector responses_and_delays_; - std::mutex mu_; - std::condition_variable load_report_cond_; + grpc::internal::Mutex mu_; + grpc::internal::CondVar load_report_cond_; bool load_report_ready_ = false; - std::condition_variable serverlist_cond_; + grpc::internal::CondVar serverlist_cond_; bool serverlist_done_ = false; ClientStats client_stats_; }; @@ -622,22 +623,22 @@ class GrpclbEnd2endTest : public ::testing::Test { GPR_ASSERT(!running_); running_ = true; service_.Start(); - std::mutex mu; + grpc::internal::Mutex mu; // We need to acquire the lock here in order to prevent the notify_one // by ServerThread::Serve from firing before the wait below is hit. - std::unique_lock lock(mu); - std::condition_variable cond; + grpc::internal::MutexLock lock(&mu); + grpc::internal::CondVar cond; thread_.reset(new std::thread( std::bind(&ServerThread::Serve, this, server_host, &mu, &cond))); - cond.wait(lock); + cond.Wait(&mu); gpr_log(GPR_INFO, "%s server startup complete", type_.c_str()); } - void Serve(const grpc::string& server_host, std::mutex* mu, - std::condition_variable* cond) { + void Serve(const grpc::string& server_host, grpc::internal::Mutex* mu, + grpc::internal::CondVar* cond) { // We need to acquire the lock here in order to prevent the notify_one // below from firing before its corresponding wait is executed. - std::lock_guard lock(*mu); + grpc::internal::MutexLock lock(mu); std::ostringstream server_address; server_address << server_host << ":" << port_; ServerBuilder builder; @@ -646,7 +647,7 @@ class GrpclbEnd2endTest : public ::testing::Test { builder.AddListeningPort(server_address.str(), creds); builder.RegisterService(&service_); server_ = builder.BuildAndStart(); - cond->notify_one(); + cond->Signal(); } void Shutdown() { diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc index e30ce0dbcbf..5b8af61ee33 100644 --- a/test/cpp/end2end/thread_stress_test.cc +++ b/test/cpp/end2end/thread_stress_test.cc @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -188,7 +189,7 @@ class CommonStressTestAsyncServer : public BaseClass { } void TearDown() override { { - std::unique_lock l(mu_); + grpc::internal::MutexLock l(&mu_); this->TearDownStart(); shutting_down_ = true; cq_->Shutdown(); @@ -229,7 +230,7 @@ class CommonStressTestAsyncServer : public BaseClass { } } void RefreshContext(int i) { - std::unique_lock l(mu_); + grpc::internal::MutexLock l(&mu_); if (!shutting_down_) { contexts_[i].state = Context::READY; contexts_[i].srv_ctx.reset(new ServerContext); @@ -253,7 +254,7 @@ class CommonStressTestAsyncServer : public BaseClass { ::grpc::testing::EchoTestService::AsyncService service_; std::unique_ptr cq_; bool shutting_down_; - std::mutex mu_; + grpc::internal::Mutex mu_; std::vector server_threads_; }; @@ -341,9 +342,9 @@ class AsyncClientEnd2endTest : public ::testing::Test { } void Wait() { - std::unique_lock l(mu_); + grpc::internal::MutexLock l(&mu_); while (rpcs_outstanding_ != 0) { - cv_.wait(l); + cv_.Wait(&mu_); } cq_.Shutdown(); @@ -366,7 +367,7 @@ class AsyncClientEnd2endTest : public ::testing::Test { call->response_reader->Finish(&call->response, &call->status, (void*)call); - std::unique_lock l(mu_); + grpc::internal::MutexLock l(&mu_); rpcs_outstanding_++; } } @@ -384,20 +385,20 @@ class AsyncClientEnd2endTest : public ::testing::Test { bool notify; { - std::unique_lock l(mu_); + grpc::internal::MutexLock l(&mu_); rpcs_outstanding_--; notify = (rpcs_outstanding_ == 0); } if (notify) { - cv_.notify_all(); + cv_.Signal(); } } } Common common_; CompletionQueue cq_; - std::mutex mu_; - std::condition_variable cv_; + grpc::internal::Mutex mu_; + grpc::internal::CondVar cv_; int rpcs_outstanding_; }; diff --git a/test/cpp/end2end/xds_end2end_test.cc b/test/cpp/end2end/xds_end2end_test.cc index 11a64264494..85753f1016c 100644 --- a/test/cpp/end2end/xds_end2end_test.cc +++ b/test/cpp/end2end/xds_end2end_test.cc @@ -84,32 +84,32 @@ template class CountedService : public ServiceType { public: size_t request_count() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); return request_count_; } size_t response_count() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); return response_count_; } void IncreaseResponseCount() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); ++response_count_; } void IncreaseRequestCount() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); ++request_count_; } void ResetCounters() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); request_count_ = 0; response_count_ = 0; } protected: - std::mutex mu_; + grpc::internal::Mutex mu_; private: size_t request_count_ = 0; @@ -145,18 +145,18 @@ class BackendServiceImpl : public BackendService { void Shutdown() {} std::set clients() { - std::unique_lock lock(clients_mu_); + grpc::internal::MutexLock lock(&clients_mu_); return clients_; } private: void AddClient(const grpc::string& client) { - std::unique_lock lock(clients_mu_); + grpc::internal::MutexLock lock(&clients_mu_); clients_.insert(client); } - std::mutex mu_; - std::mutex clients_mu_; + grpc::internal::Mutex mu_; + grpc::internal::Mutex clients_mu_; std::set clients_; }; @@ -208,7 +208,7 @@ class BalancerServiceImpl : public BalancerService { // TODO(juanlishen): Clean up the scoping. gpr_log(GPR_INFO, "LB[%p]: BalanceLoad", this); { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); if (serverlist_done_) goto done; } { @@ -234,7 +234,7 @@ class BalancerServiceImpl : public BalancerService { } { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); responses_and_delays = responses_and_delays_; } for (const auto& response_and_delay : responses_and_delays) { @@ -242,8 +242,8 @@ class BalancerServiceImpl : public BalancerService { response_and_delay.second); } { - std::unique_lock lock(mu_); - serverlist_cond_.wait(lock, [this] { return serverlist_done_; }); + grpc::internal::MutexLock lock(&mu_); + serverlist_cond_.WaitUntil(&mu_, [this] { return serverlist_done_; }); } if (client_load_reporting_interval_seconds_ > 0) { @@ -254,7 +254,7 @@ class BalancerServiceImpl : public BalancerService { GPR_ASSERT(request.has_client_stats()); // We need to acquire the lock here in order to prevent the notify_one // below from firing before its corresponding wait is executed. - std::lock_guard lock(mu_); + grpc::internal::MutexLock lock(&mu_); client_stats_.num_calls_started += request.client_stats().num_calls_started(); client_stats_.num_calls_finished += @@ -271,7 +271,7 @@ class BalancerServiceImpl : public BalancerService { drop_token_count.num_calls(); } load_report_ready_ = true; - load_report_cond_.notify_one(); + load_report_cond_.Signal(); } } } @@ -281,12 +281,12 @@ class BalancerServiceImpl : public BalancerService { } void add_response(const LoadBalanceResponse& response, int send_after_ms) { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); responses_and_delays_.push_back(std::make_pair(response, send_after_ms)); } void Shutdown() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); NotifyDoneWithServerlistsLocked(); responses_and_delays_.clear(); client_stats_.Reset(); @@ -318,21 +318,21 @@ class BalancerServiceImpl : public BalancerService { } const ClientStats& WaitForLoadReport() { - std::unique_lock lock(mu_); - load_report_cond_.wait(lock, [this] { return load_report_ready_; }); + grpc::internal::MutexLock lock(&mu_); + load_report_cond_.WaitUntil(&mu_, [this] { return load_report_ready_; }); load_report_ready_ = false; return client_stats_; } void NotifyDoneWithServerlists() { - std::lock_guard lock(mu_); + grpc::internal::MutexLock lock(&mu_); NotifyDoneWithServerlistsLocked(); } void NotifyDoneWithServerlistsLocked() { if (!serverlist_done_) { serverlist_done_ = true; - serverlist_cond_.notify_all(); + serverlist_cond_.Broadcast(); } } @@ -351,10 +351,10 @@ class BalancerServiceImpl : public BalancerService { const int client_load_reporting_interval_seconds_; std::vector responses_and_delays_; - std::mutex mu_; - std::condition_variable load_report_cond_; + grpc::internal::Mutex mu_; + grpc::internal::CondVar load_report_cond_; bool load_report_ready_ = false; - std::condition_variable serverlist_cond_; + grpc::internal::CondVar serverlist_cond_; bool serverlist_done_ = false; ClientStats client_stats_; }; @@ -633,22 +633,22 @@ class XdsEnd2endTest : public ::testing::Test { gpr_log(GPR_INFO, "starting %s server on port %d", type_.c_str(), port_); GPR_ASSERT(!running_); running_ = true; - std::mutex mu; + grpc::internal::Mutex mu; // We need to acquire the lock here in order to prevent the notify_one // by ServerThread::Serve from firing before the wait below is hit. - std::unique_lock lock(mu); - std::condition_variable cond; + grpc::internal::MutexLock lock(&mu); + grpc::internal::CondVar cond; thread_.reset(new std::thread( std::bind(&ServerThread::Serve, this, server_host, &mu, &cond))); - cond.wait(lock); + cond.Wait(&mu); gpr_log(GPR_INFO, "%s server startup complete", type_.c_str()); } - void Serve(const grpc::string& server_host, std::mutex* mu, - std::condition_variable* cond) { + void Serve(const grpc::string& server_host, grpc::internal::Mutex* mu, + grpc::internal::CondVar* cond) { // We need to acquire the lock here in order to prevent the notify_one // below from firing before its corresponding wait is executed. - std::lock_guard lock(*mu); + grpc::internal::MutexLock lock(mu); std::ostringstream server_address; server_address << server_host << ":" << port_; ServerBuilder builder; @@ -657,7 +657,7 @@ class XdsEnd2endTest : public ::testing::Test { builder.AddListeningPort(server_address.str(), creds); builder.RegisterService(&service_); server_ = builder.BuildAndStart(); - cond->notify_one(); + cond->Signal(); } void Shutdown() { diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 07e44b39bb6..67bbb4efa6b 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -987,6 +987,7 @@ include/grpcpp/impl/codegen/status.h \ include/grpcpp/impl/codegen/status_code_enum.h \ include/grpcpp/impl/codegen/string_ref.h \ include/grpcpp/impl/codegen/stub_options.h \ +include/grpcpp/impl/codegen/sync.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ include/grpcpp/impl/grpc_library.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 0301818b9db..438cb98dbae 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -989,6 +989,7 @@ include/grpcpp/impl/codegen/status.h \ include/grpcpp/impl/codegen/status_code_enum.h \ include/grpcpp/impl/codegen/string_ref.h \ include/grpcpp/impl/codegen/stub_options.h \ +include/grpcpp/impl/codegen/sync.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ include/grpcpp/impl/grpc_library.h \ @@ -1086,12 +1087,12 @@ src/core/lib/gprpp/inlined_vector.h \ src/core/lib/gprpp/manual_constructor.h \ src/core/lib/gprpp/map.h \ src/core/lib/gprpp/memory.h \ -src/core/lib/gprpp/mutex_lock.h \ src/core/lib/gprpp/optional.h \ src/core/lib/gprpp/orphanable.h \ src/core/lib/gprpp/pair.h \ src/core/lib/gprpp/ref_counted.h \ src/core/lib/gprpp/ref_counted_ptr.h \ +src/core/lib/gprpp/sync.h \ src/core/lib/gprpp/thd.h \ src/core/lib/http/format_request.h \ src/core/lib/http/httpcli.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index e68e758c64e..1817be44bc3 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1166,12 +1166,12 @@ src/core/lib/gprpp/inlined_vector.h \ src/core/lib/gprpp/manual_constructor.h \ src/core/lib/gprpp/map.h \ src/core/lib/gprpp/memory.h \ -src/core/lib/gprpp/mutex_lock.h \ src/core/lib/gprpp/optional.h \ src/core/lib/gprpp/orphanable.h \ src/core/lib/gprpp/pair.h \ src/core/lib/gprpp/ref_counted.h \ src/core/lib/gprpp/ref_counted_ptr.h \ +src/core/lib/gprpp/sync.h \ src/core/lib/gprpp/thd.h \ src/core/lib/gprpp/thd_posix.cc \ src/core/lib/gprpp/thd_windows.cc \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 4afbb767b66..5cf7bf3fc8c 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -8015,8 +8015,8 @@ "src/core/lib/gprpp/manual_constructor.h", "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", - "src/core/lib/gprpp/mutex_lock.h", "src/core/lib/gprpp/pair.h", + "src/core/lib/gprpp/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/profiling/timers.h" ], @@ -8063,8 +8063,8 @@ "src/core/lib/gprpp/manual_constructor.h", "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", - "src/core/lib/gprpp/mutex_lock.h", "src/core/lib/gprpp/pair.h", + "src/core/lib/gprpp/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/profiling/timers.h" ], @@ -9842,6 +9842,7 @@ }, { "deps": [ + "grpc++_internal_hdrs_only", "grpc_codegen" ], "headers": [ @@ -10038,6 +10039,7 @@ "gpr", "gpr_base_headers", "grpc++_codegen_base", + "grpc++_internal_hdrs_only", "grpc_base_headers", "grpc_transport_inproc_headers", "health_proto", @@ -10334,6 +10336,20 @@ "third_party": false, "type": "filegroup" }, + { + "deps": [], + "headers": [ + "include/grpcpp/impl/codegen/sync.h" + ], + "is_filegroup": true, + "language": "c++", + "name": "grpc++_internal_hdrs_only", + "src": [ + "include/grpcpp/impl/codegen/sync.h" + ], + "third_party": false, + "type": "filegroup" + }, { "deps": [], "headers": [ From 1dce1009e67ea4b5934a61b1bcf8a217bd12cc76 Mon Sep 17 00:00:00 2001 From: Ahmed Mahdy <44652453+ahmeb99@users.noreply.github.com> Date: Mon, 8 Apr 2019 16:58:15 -0700 Subject: [PATCH 216/242] Disable Nagle algorithm in Windows --- src/core/lib/iomgr/tcp_windows.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/core/lib/iomgr/tcp_windows.cc b/src/core/lib/iomgr/tcp_windows.cc index 7b464651ea1..3c17d7e2057 100644 --- a/src/core/lib/iomgr/tcp_windows.cc +++ b/src/core/lib/iomgr/tcp_windows.cc @@ -88,6 +88,19 @@ static grpc_error* enable_loopback_fast_path(SOCKET sock) { : GRPC_WSA_ERROR(status, "WSAIoctl(SIO_LOOPBACK_FAST_PATH)"); } +static grpc_error* enable_socket_low_latency(SOCKET sock) { + int status; + BOOL param = TRUE; + status = ::setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + reinterpret_cast(¶m), sizeof(param)); + if (status == SOCKET_ERROR) { + status = WSAGetLastError(); + } + return status == 0 + ? GRPC_ERROR_NONE + : GRPC_WSA_ERROR(status, "setsockopt(TCP_NODELAY)"); +} + grpc_error* grpc_tcp_prepare_socket(SOCKET sock) { grpc_error* err; err = grpc_tcp_set_non_block(sock); @@ -96,6 +109,8 @@ grpc_error* grpc_tcp_prepare_socket(SOCKET sock) { if (err != GRPC_ERROR_NONE) return err; err = enable_loopback_fast_path(sock); if (err != GRPC_ERROR_NONE) return err; + err = enable_socket_low_latency(sock); + if (err != GRPC_ERROR_NONE) return err; return GRPC_ERROR_NONE; } From 960864736bdc236815e81cc09ad18768b1dc4a43 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 8 Apr 2019 19:51:20 -0700 Subject: [PATCH 217/242] Unref errors in test --- src/core/ext/filters/client_channel/service_config.cc | 2 +- src/core/ext/filters/client_channel/service_config.h | 2 +- test/core/client_channel/service_config_test.cc | 9 +++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/core/ext/filters/client_channel/service_config.cc b/src/core/ext/filters/client_channel/service_config.cc index 64560175804..a7d489a18ed 100644 --- a/src/core/ext/filters/client_channel/service_config.cc +++ b/src/core/ext/filters/client_channel/service_config.cc @@ -342,7 +342,7 @@ ServiceConfig::GetMethodServiceConfigObjectsVector(const grpc_slice& path) { return value; } -int ServiceConfig::RegisterParser(UniquePtr parser) { +size_t ServiceConfig::RegisterParser(UniquePtr parser) { registered_parsers->push_back(std::move(parser)); return registered_parsers->size() - 1; } diff --git a/src/core/ext/filters/client_channel/service_config.h b/src/core/ext/filters/client_channel/service_config.h index f205fa2f243..0f2d2b387ae 100644 --- a/src/core/ext/filters/client_channel/service_config.h +++ b/src/core/ext/filters/client_channel/service_config.h @@ -150,7 +150,7 @@ class ServiceConfig : public RefCounted { /// registered parser. Each parser is responsible for reading the service /// config json and returning a parsed object. This parsed object can later be /// retrieved using the same index that was returned at registration time. - static int RegisterParser(UniquePtr parser); + static size_t RegisterParser(UniquePtr parser); static void Init(); diff --git a/test/core/client_channel/service_config_test.cc b/test/core/client_channel/service_config_test.cc index f364da9cf89..10cb4cd4404 100644 --- a/test/core/client_channel/service_config_test.cc +++ b/test/core/client_channel/service_config_test.cc @@ -154,6 +154,7 @@ TEST_F(ServiceConfigTest, ErrorCheck1) { ASSERT_TRUE(error != GRPC_ERROR_NONE); EXPECT_TRUE(strstr(grpc_error_string(error), "failed to parse JSON for service config") != nullptr); + GRPC_ERROR_UNREF(error); } TEST_F(ServiceConfigTest, BasicTest1) { @@ -170,6 +171,7 @@ TEST_F(ServiceConfigTest, ErrorNoNames) { gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); ASSERT_TRUE(error != GRPC_ERROR_NONE); EXPECT_TRUE(strstr(grpc_error_string(error), "No names found") != nullptr); + GRPC_ERROR_UNREF(error); } TEST_F(ServiceConfigTest, ErrorNoNamesWithMultipleMethodConfigs) { @@ -180,6 +182,7 @@ TEST_F(ServiceConfigTest, ErrorNoNamesWithMultipleMethodConfigs) { gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); ASSERT_TRUE(error != GRPC_ERROR_NONE); EXPECT_TRUE(strstr(grpc_error_string(error), "No names found") != nullptr); + GRPC_ERROR_UNREF(error); } TEST_F(ServiceConfigTest, ValidMethodConfig) { @@ -223,6 +226,7 @@ TEST_F(ServiceConfigTest, Parser1ErrorInvalidType) { std::smatch match; std::string s(grpc_error_string(error)); EXPECT_TRUE(std::regex_search(s, match, e)); + GRPC_ERROR_UNREF(error); } TEST_F(ServiceConfigTest, Parser1ErrorInvalidValue) { @@ -238,6 +242,7 @@ TEST_F(ServiceConfigTest, Parser1ErrorInvalidValue) { std::smatch match; std::string s(grpc_error_string(error)); EXPECT_TRUE(std::regex_search(s, match, e)); + GRPC_ERROR_UNREF(error); } TEST_F(ServiceConfigTest, Parser2BasicTest) { @@ -271,6 +276,7 @@ TEST_F(ServiceConfigTest, Parser2ErrorInvalidType) { std::smatch match; std::string s(grpc_error_string(error)); EXPECT_TRUE(std::regex_search(s, match, e)); + GRPC_ERROR_UNREF(error); } TEST_F(ServiceConfigTest, Parser2ErrorInvalidValue) { @@ -289,6 +295,7 @@ TEST_F(ServiceConfigTest, Parser2ErrorInvalidValue) { std::smatch match; std::string s(grpc_error_string(error)); EXPECT_TRUE(std::regex_search(s, match, e)); + GRPC_ERROR_UNREF(error); } // Test parsing with ErrorParsers which always add errors @@ -318,6 +325,7 @@ TEST_F(ErroredParsersScopingTest, GlobalParams) { std::smatch match; std::string s(grpc_error_string(error)); EXPECT_TRUE(std::regex_search(s, match, e)); + GRPC_ERROR_UNREF(error); } TEST_F(ErroredParsersScopingTest, MethodParams) { @@ -341,6 +349,7 @@ TEST_F(ErroredParsersScopingTest, MethodParams) { std::smatch match; std::string s(grpc_error_string(error)); EXPECT_TRUE(std::regex_search(s, match, e)); + GRPC_ERROR_UNREF(error); } } // namespace testing From a7592d098f73e26904d3bfc70a40d1e29a10a173 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 9 Apr 2019 03:39:18 -0400 Subject: [PATCH 218/242] grpc-performance-kokoro-v5 kokoro perf image changes --- tools/gce/create_linux_kokoro_performance_worker_from_image.sh | 2 +- tools/gce/linux_kokoro_performance_worker_init.sh | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/gce/create_linux_kokoro_performance_worker_from_image.sh b/tools/gce/create_linux_kokoro_performance_worker_from_image.sh index 903166122eb..1b014ad4a8e 100755 --- a/tools/gce/create_linux_kokoro_performance_worker_from_image.sh +++ b/tools/gce/create_linux_kokoro_performance_worker_from_image.sh @@ -22,7 +22,7 @@ cd "$(dirname "$0")" CLOUD_PROJECT=grpc-testing ZONE=us-central1-b # this zone allows 32core machines -LATEST_PERF_WORKER_IMAGE=grpc-performance-kokoro-v4 # update if newer image exists +LATEST_PERF_WORKER_IMAGE=grpc-performance-kokoro-v5 # update if newer image exists INSTANCE_NAME="${1:-grpc-kokoro-performance-server}" MACHINE_TYPE="${2:-n1-standard-32}" diff --git a/tools/gce/linux_kokoro_performance_worker_init.sh b/tools/gce/linux_kokoro_performance_worker_init.sh index 1bf2228279e..46061a0cc67 100755 --- a/tools/gce/linux_kokoro_performance_worker_init.sh +++ b/tools/gce/linux_kokoro_performance_worker_init.sh @@ -219,6 +219,8 @@ touch /tmpfs/READY # See https://github.com/grpc/grpc/issues/17794 sudo sed -i 's/APT::Periodic::Update-Package-Lists "1"/APT::Periodic::Update-Package-Lists "0"/' /etc/apt/apt.conf.d/10periodic sudo sed -i 's/APT::Periodic::AutocleanInterval "1"/APT::Periodic::AutocleanInterval "0"/' /etc/apt/apt.conf.d/10periodic +sudo sed -i 's/APT::Periodic::Update-Package-Lists "1"/APT::Periodic::Update-Package-Lists "0"/' /etc/apt/apt.conf.d/20auto-upgrades +sudo sed -i 's/APT::Periodic::Unattended-Upgrade "1"/APT::Periodic::Unattended-Upgrade "0"/' /etc/apt/apt.conf.d/20auto-upgrades # Restart for VM to pick up kernel update echo 'Successfully initialized the linux worker, going for reboot in 10 seconds' From bb8ba4547aa04f720fb418f6e8d76ffb9d4730ea Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Mon, 8 Apr 2019 10:46:06 -0700 Subject: [PATCH 219/242] Ban std:: sync constructs --- .../run_tests/sanity/cpp_banned_constructs.sh | 29 +++++++++++++++++++ tools/run_tests/sanity/sanity_tests.yaml | 1 + 2 files changed, 30 insertions(+) create mode 100755 tools/run_tests/sanity/cpp_banned_constructs.sh diff --git a/tools/run_tests/sanity/cpp_banned_constructs.sh b/tools/run_tests/sanity/cpp_banned_constructs.sh new file mode 100755 index 00000000000..68240d6f831 --- /dev/null +++ b/tools/run_tests/sanity/cpp_banned_constructs.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# Copyright 2019 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +cd "$(dirname "$0")/../../.." + +# +# Prevent the use of synchronization and threading constructs from std:: since +# the code should be using grpc_core::Mutex, grpc::internal::Mutex, +# grpc_core::Thread, etc. +# + +egrep -Irn \ + 'std::(mutex|condition_variable|lock_guard|unique_lock|thread)' \ + include/grpc include/grpcpp src/core src/cpp | diff - /dev/null + diff --git a/tools/run_tests/sanity/sanity_tests.yaml b/tools/run_tests/sanity/sanity_tests.yaml index 1913edd4257..40686e0f3ab 100644 --- a/tools/run_tests/sanity/sanity_tests.yaml +++ b/tools/run_tests/sanity/sanity_tests.yaml @@ -10,6 +10,7 @@ - script: tools/run_tests/sanity/check_tracer_sanity.py - script: tools/run_tests/sanity/core_banned_functions.py - script: tools/run_tests/sanity/core_untyped_structs.sh +- script: tools/run_tests/sanity/cpp_banned_constructs.sh - script: tools/run_tests/sanity/check_deprecated_grpc++.py - script: tools/run_tests/sanity/check_port_platform.py - script: tools/buildgen/generate_projects.sh -j 3 From d171c74c9d7172248d672a3a3a0e261e3e3c0035 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 9 Apr 2019 18:07:00 +0200 Subject: [PATCH 220/242] address PR feedback --- src/csharp/Grpc.Core/CallCredentials.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/csharp/Grpc.Core/CallCredentials.cs b/src/csharp/Grpc.Core/CallCredentials.cs index ebe5f260df4..6344a881070 100644 --- a/src/csharp/Grpc.Core/CallCredentials.cs +++ b/src/csharp/Grpc.Core/CallCredentials.cs @@ -37,7 +37,7 @@ namespace Grpc.Core /// The new CompositeCallCredentials public static CallCredentials Compose(params CallCredentials[] credentials) { - return new CompositeCallCredentialsConfiguration(credentials); + return new CompositeCallCredentials(credentials); } /// @@ -47,7 +47,7 @@ namespace Grpc.Core /// authentication interceptor public static CallCredentials FromInterceptor(AsyncAuthInterceptor interceptor) { - return new AsyncAuthInterceptorCredentialsConfiguration(interceptor); + return new AsyncAuthInterceptorCredentials(interceptor); } /// @@ -56,11 +56,11 @@ namespace Grpc.Core /// public abstract void InternalPopulateConfiguration(CallCredentialsConfiguratorBase configurator, object state); - private class CompositeCallCredentialsConfiguration : CallCredentials + private class CompositeCallCredentials : CallCredentials { readonly IReadOnlyList credentials; - public CompositeCallCredentialsConfiguration(CallCredentials[] credentials) + public CompositeCallCredentials(CallCredentials[] credentials) { GrpcPreconditions.CheckArgument(credentials.Length >= 2, "Composite credentials object can only be created from 2 or more credentials."); this.credentials = new List(credentials).AsReadOnly(); @@ -72,11 +72,11 @@ namespace Grpc.Core } } - internal class AsyncAuthInterceptorCredentialsConfiguration : CallCredentials + private class AsyncAuthInterceptorCredentials : CallCredentials { readonly AsyncAuthInterceptor interceptor; - public AsyncAuthInterceptorCredentialsConfiguration(AsyncAuthInterceptor interceptor) + public AsyncAuthInterceptorCredentials(AsyncAuthInterceptor interceptor) { this.interceptor = GrpcPreconditions.CheckNotNull(interceptor); } From 917d025f0301c21a7321be9de5f027d7775f4e3b Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Tue, 9 Apr 2019 09:39:42 -0700 Subject: [PATCH 221/242] Fix diff between num_entries and idx of path --- src/core/ext/filters/client_channel/service_config.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/ext/filters/client_channel/service_config.cc b/src/core/ext/filters/client_channel/service_config.cc index a7d489a18ed..ce815f370de 100644 --- a/src/core/ext/filters/client_channel/service_config.cc +++ b/src/core/ext/filters/client_channel/service_config.cc @@ -154,8 +154,8 @@ grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( error_list.push_back(parse_error); } else { GPR_DEBUG_ASSERT(parse_error == GRPC_ERROR_NONE); + paths.push_back(std::move(path)); } - paths.push_back(std::move(path)); } } } @@ -216,7 +216,8 @@ grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) { error_list.push_back(error); } } - GPR_DEBUG_ASSERT(num_entries == idx); + // idx might not be equal to num_entries due to parsing errors + num_entries = idx; break; } } From b4e94b652d8e30ec77f1a2b91677f1f0f6762a0a Mon Sep 17 00:00:00 2001 From: Ahmed Mahdy <44652453+ahmeb99@users.noreply.github.com> Date: Tue, 9 Apr 2019 10:05:53 -0700 Subject: [PATCH 222/242] Fix formatting --- src/core/lib/iomgr/tcp_windows.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/core/lib/iomgr/tcp_windows.cc b/src/core/lib/iomgr/tcp_windows.cc index 3c17d7e2057..60d34ef897f 100644 --- a/src/core/lib/iomgr/tcp_windows.cc +++ b/src/core/lib/iomgr/tcp_windows.cc @@ -91,14 +91,13 @@ static grpc_error* enable_loopback_fast_path(SOCKET sock) { static grpc_error* enable_socket_low_latency(SOCKET sock) { int status; BOOL param = TRUE; - status = ::setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + status = ::setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(¶m), sizeof(param)); if (status == SOCKET_ERROR) { status = WSAGetLastError(); } - return status == 0 - ? GRPC_ERROR_NONE - : GRPC_WSA_ERROR(status, "setsockopt(TCP_NODELAY)"); + return status == 0 ? GRPC_ERROR_NONE + : GRPC_WSA_ERROR(status, "setsockopt(TCP_NODELAY)"); } grpc_error* grpc_tcp_prepare_socket(SOCKET sock) { From b84d3db7624f220305a73cefd77e67e9238b041b Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Tue, 9 Apr 2019 11:11:09 -0700 Subject: [PATCH 223/242] Fix build after merge from master --- include/grpcpp/channel.h | 1 + include/grpcpp/generic/generic_stub_impl.h | 2 +- .../grpcpp/impl/codegen/completion_queue_impl.h | 17 ++++++++++------- include/grpcpp/impl/codegen/server_context.h | 1 - include/grpcpp/server_builder_impl.h | 4 ++-- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/include/grpcpp/channel.h b/include/grpcpp/channel.h index c4d5ab1177b..3208430f397 100644 --- a/include/grpcpp/channel.h +++ b/include/grpcpp/channel.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/include/grpcpp/generic/generic_stub_impl.h b/include/grpcpp/generic/generic_stub_impl.h index 2d6a11de923..ff1223453c1 100644 --- a/include/grpcpp/generic/generic_stub_impl.h +++ b/include/grpcpp/generic/generic_stub_impl.h @@ -29,12 +29,12 @@ namespace grpc { -class CompletionQueue; typedef ClientAsyncReaderWriter GenericClientAsyncReaderWriter; typedef ClientAsyncResponseReader GenericClientAsyncResponseReader; } // namespace grpc namespace grpc_impl { +class CompletionQueue; /// Generic stubs provide a type-unsafe interface to call gRPC methods /// by name. diff --git a/include/grpcpp/impl/codegen/completion_queue_impl.h b/include/grpcpp/impl/codegen/completion_queue_impl.h index 0a4b2100454..42f5a31354b 100644 --- a/include/grpcpp/impl/codegen/completion_queue_impl.h +++ b/include/grpcpp/impl/codegen/completion_queue_impl.h @@ -41,7 +41,13 @@ struct grpc_completion_queue; +namespace grpc_impl { + +class Server; +class ServerBuilder; +} // namespace grpc_impl namespace grpc { +class Channel; template class ClientReader; @@ -60,8 +66,6 @@ class ServerReaderWriterBody; class ChannelInterface; class ClientContext; -class Server; -class ServerBuilder; class ServerContext; class ServerInterface; @@ -91,7 +95,6 @@ extern CoreCodegenInterface* g_core_codegen_interface; } // namespace grpc namespace grpc_impl { -class Channel; /// A thin wrapper around \ref grpc_completion_queue (see \ref /// src/core/lib/surface/completion_queue.h). @@ -274,14 +277,14 @@ class CompletionQueue : private ::grpc::GrpcLibraryCodegen { friend class ::grpc::internal::TemplatedBidiStreamingHandler; template <::grpc::StatusCode code> friend class ::grpc::internal::ErrorMethodHandler; - friend class ::grpc::Server; + friend class ::grpc_impl::Server; friend class ::grpc::ServerContext; friend class ::grpc::ServerInterface; template friend class ::grpc::internal::BlockingUnaryCallImpl; // Friends that need access to constructor for callback CQ - friend class ::grpc_impl::Channel; + friend class ::grpc::Channel; // For access to Register/CompleteAvalanching template @@ -410,8 +413,8 @@ class ServerCompletionQueue : public CompletionQueue { polling_type_(polling_type) {} grpc_cq_polling_type polling_type_; - friend class ::grpc::ServerBuilder; - friend class ::grpc::Server; + friend class ::grpc_impl::ServerBuilder; + friend class ::grpc_impl::Server; }; } // namespace grpc_impl diff --git a/include/grpcpp/impl/codegen/server_context.h b/include/grpcpp/impl/codegen/server_context.h index a9b857a4b67..fe5a0097d0a 100644 --- a/include/grpcpp/impl/codegen/server_context.h +++ b/include/grpcpp/impl/codegen/server_context.h @@ -48,7 +48,6 @@ class Server; namespace grpc { class ClientContext; class GenericServerContext; -class CompletionQueue; class ServerInterface; template class ServerAsyncReader; diff --git a/include/grpcpp/server_builder_impl.h b/include/grpcpp/server_builder_impl.h index f7624deba5f..be21ed024ea 100644 --- a/include/grpcpp/server_builder_impl.h +++ b/include/grpcpp/server_builder_impl.h @@ -38,14 +38,14 @@ struct grpc_resource_quota; namespace grpc_impl { +class CompletionQueue; class ResourceQuota; +class ServerCompletionQueue; class ServerCredentials; } // namespace grpc_impl namespace grpc { class AsyncGenericService; -class CompletionQueue; -class ServerCompletionQueue; class Service; namespace testing { From 2b7cab0d414773a9d7b34b2364cd95a76010d80c Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Tue, 9 Apr 2019 11:37:59 -0700 Subject: [PATCH 224/242] Remove check on error --- src/core/ext/filters/client_channel/service_config.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/ext/filters/client_channel/service_config.cc b/src/core/ext/filters/client_channel/service_config.cc index ce815f370de..d9e64ccf5a8 100644 --- a/src/core/ext/filters/client_channel/service_config.cc +++ b/src/core/ext/filters/client_channel/service_config.cc @@ -69,9 +69,8 @@ RefCountedPtr ServiceConfig::Create(const char* json, "failed to parse JSON for service config"); return nullptr; } - auto return_value = MakeRefCounted( + return MakeRefCounted( std::move(service_config_json), std::move(json_string), json_tree, error); - return *error == GRPC_ERROR_NONE ? return_value : nullptr; } ServiceConfig::ServiceConfig(UniquePtr service_config_json, From 506ca7fc3616865431dd62d8e499bf641edb4d08 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Tue, 9 Apr 2019 11:51:39 -0700 Subject: [PATCH 225/242] Fix clang script errors --- BUILD.gn | 1 + include/grpcpp/impl/codegen/completion_queue_impl.h | 2 +- include/grpcpp/impl/codegen/server_interface.h | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index 57e15800e20..5609956a789 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1034,6 +1034,7 @@ config("grpc_config") { "include/grpcpp/impl/codegen/client_interceptor.h", "include/grpcpp/impl/codegen/client_unary_call.h", "include/grpcpp/impl/codegen/completion_queue.h", + "include/grpcpp/impl/codegen/completion_queue_impl.h", "include/grpcpp/impl/codegen/completion_queue_tag.h", "include/grpcpp/impl/codegen/config.h", "include/grpcpp/impl/codegen/config_protobuf.h", diff --git a/include/grpcpp/impl/codegen/completion_queue_impl.h b/include/grpcpp/impl/codegen/completion_queue_impl.h index 42f5a31354b..bcfd1fa5083 100644 --- a/include/grpcpp/impl/codegen/completion_queue_impl.h +++ b/include/grpcpp/impl/codegen/completion_queue_impl.h @@ -45,7 +45,7 @@ namespace grpc_impl { class Server; class ServerBuilder; -} // namespace grpc_impl +} // namespace grpc_impl namespace grpc { class Channel; diff --git a/include/grpcpp/impl/codegen/server_interface.h b/include/grpcpp/impl/codegen/server_interface.h index 22a81c02b99..3146dd19b18 100644 --- a/include/grpcpp/impl/codegen/server_interface.h +++ b/include/grpcpp/impl/codegen/server_interface.h @@ -32,7 +32,7 @@ namespace grpc_impl { class CompletionQueue; class ServerCompletionQueue; class ServerCredentials; -} +} // namespace grpc_impl namespace grpc { class AsyncGenericService; From df3d5bc8f7888582192e370f8f9f47ae1b86ffd2 Mon Sep 17 00:00:00 2001 From: Vishal Powar Date: Tue, 26 Mar 2019 15:33:03 -0700 Subject: [PATCH 226/242] Add upb generated code and build rule for lrs protocol. --- BUILD | 21 ++ .../envoy/api/v2/endpoint/load_report.upb.c | 105 ++++++ .../envoy/api/v2/endpoint/load_report.upb.h | 299 ++++++++++++++++++ .../envoy/service/load_stats/v2/lrs.upb.c | 52 +++ .../envoy/service/load_stats/v2/lrs.upb.h | 132 ++++++++ tools/codegen/core/gen_upb_api.sh | 4 +- 6 files changed, 612 insertions(+), 1 deletion(-) create mode 100644 src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c create mode 100644 src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h create mode 100644 src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c create mode 100644 src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h diff --git a/BUILD b/BUILD index d2dc14f196f..fdcccbee1a9 100644 --- a/BUILD +++ b/BUILD @@ -2329,6 +2329,27 @@ grpc_cc_library( ) #TODO: Get this into build.yaml once we start using it. +grpc_cc_library( + name = "envoy_lrs_upb", + srcs = [ + "src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c", + "src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c", + ], + hdrs = [ + "src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h", + "src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h", + ], + language = "c++", + external_deps = [ + "upb_lib", + ], + deps = [ + ":envoy_core_upb", + ":google_api_upb", + ":proto_gen_validate_upb", + ] +) + grpc_cc_library( name = "envoy_ads_upb", srcs = [ diff --git a/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c b/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c new file mode 100644 index 00000000000..2af77c59efb --- /dev/null +++ b/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c @@ -0,0 +1,105 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/api/v2/endpoint/load_report.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include +#include "upb/msg.h" +#include "envoy/api/v2/endpoint/load_report.upb.h" +#include "envoy/api/v2/core/address.upb.h" +#include "envoy/api/v2/core/base.upb.h" +#include "google/protobuf/duration.upb.h" +#include "validate/validate.upb.h" +#include "gogoproto/gogo.upb.h" + +#include "upb/port_def.inc" + +static const upb_msglayout *const envoy_api_v2_endpoint_UpstreamLocalityStats_submsgs[3] = { + &envoy_api_v2_core_Locality_msginit, + &envoy_api_v2_endpoint_EndpointLoadMetricStats_msginit, + &envoy_api_v2_endpoint_UpstreamEndpointStats_msginit, +}; + +static const upb_msglayout_field envoy_api_v2_endpoint_UpstreamLocalityStats__fields[7] = { + {1, UPB_SIZE(28, 32), 0, 0, 11, 1}, + {2, UPB_SIZE(0, 0), 0, 0, 4, 1}, + {3, UPB_SIZE(8, 8), 0, 0, 4, 1}, + {4, UPB_SIZE(16, 16), 0, 0, 4, 1}, + {5, UPB_SIZE(32, 40), 0, 1, 11, 3}, + {6, UPB_SIZE(24, 24), 0, 0, 13, 1}, + {7, UPB_SIZE(36, 48), 0, 2, 11, 3}, +}; + +const upb_msglayout envoy_api_v2_endpoint_UpstreamLocalityStats_msginit = { + &envoy_api_v2_endpoint_UpstreamLocalityStats_submsgs[0], + &envoy_api_v2_endpoint_UpstreamLocalityStats__fields[0], + UPB_SIZE(40, 56), 7, false, +}; + +static const upb_msglayout *const envoy_api_v2_endpoint_UpstreamEndpointStats_submsgs[2] = { + &envoy_api_v2_core_Address_msginit, + &envoy_api_v2_endpoint_EndpointLoadMetricStats_msginit, +}; + +static const upb_msglayout_field envoy_api_v2_endpoint_UpstreamEndpointStats__fields[5] = { + {1, UPB_SIZE(24, 24), 0, 0, 11, 1}, + {2, UPB_SIZE(0, 0), 0, 0, 4, 1}, + {3, UPB_SIZE(8, 8), 0, 0, 4, 1}, + {4, UPB_SIZE(16, 16), 0, 0, 4, 1}, + {5, UPB_SIZE(28, 32), 0, 1, 11, 3}, +}; + +const upb_msglayout envoy_api_v2_endpoint_UpstreamEndpointStats_msginit = { + &envoy_api_v2_endpoint_UpstreamEndpointStats_submsgs[0], + &envoy_api_v2_endpoint_UpstreamEndpointStats__fields[0], + UPB_SIZE(32, 40), 5, false, +}; + +static const upb_msglayout_field envoy_api_v2_endpoint_EndpointLoadMetricStats__fields[3] = { + {1, UPB_SIZE(16, 16), 0, 0, 9, 1}, + {2, UPB_SIZE(0, 0), 0, 0, 4, 1}, + {3, UPB_SIZE(8, 8), 0, 0, 1, 1}, +}; + +const upb_msglayout envoy_api_v2_endpoint_EndpointLoadMetricStats_msginit = { + NULL, + &envoy_api_v2_endpoint_EndpointLoadMetricStats__fields[0], + UPB_SIZE(24, 32), 3, false, +}; + +static const upb_msglayout *const envoy_api_v2_endpoint_ClusterStats_submsgs[3] = { + &envoy_api_v2_endpoint_ClusterStats_DroppedRequests_msginit, + &envoy_api_v2_endpoint_UpstreamLocalityStats_msginit, + &google_protobuf_Duration_msginit, +}; + +static const upb_msglayout_field envoy_api_v2_endpoint_ClusterStats__fields[5] = { + {1, UPB_SIZE(8, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(20, 32), 0, 1, 11, 3}, + {3, UPB_SIZE(0, 0), 0, 0, 4, 1}, + {4, UPB_SIZE(16, 24), 0, 2, 11, 1}, + {5, UPB_SIZE(24, 40), 0, 0, 11, 3}, +}; + +const upb_msglayout envoy_api_v2_endpoint_ClusterStats_msginit = { + &envoy_api_v2_endpoint_ClusterStats_submsgs[0], + &envoy_api_v2_endpoint_ClusterStats__fields[0], + UPB_SIZE(32, 48), 5, false, +}; + +static const upb_msglayout_field envoy_api_v2_endpoint_ClusterStats_DroppedRequests__fields[2] = { + {1, UPB_SIZE(8, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(0, 0), 0, 0, 4, 1}, +}; + +const upb_msglayout envoy_api_v2_endpoint_ClusterStats_DroppedRequests_msginit = { + NULL, + &envoy_api_v2_endpoint_ClusterStats_DroppedRequests__fields[0], + UPB_SIZE(16, 32), 2, false, +}; + +#include "upb/port_undef.inc" + diff --git a/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h b/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h new file mode 100644 index 00000000000..7ee2129f436 --- /dev/null +++ b/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h @@ -0,0 +1,299 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/api/v2/endpoint/load_report.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_API_V2_ENDPOINT_LOAD_REPORT_PROTO_UPB_H_ +#define ENVOY_API_V2_ENDPOINT_LOAD_REPORT_PROTO_UPB_H_ + +#include "upb/generated_util.h" + +#include "upb/msg.h" + +#include "upb/decode.h" +#include "upb/encode.h" +#include "upb/port_def.inc" +#ifdef __cplusplus +extern "C" { +#endif + +struct envoy_api_v2_endpoint_UpstreamLocalityStats; +struct envoy_api_v2_endpoint_UpstreamEndpointStats; +struct envoy_api_v2_endpoint_EndpointLoadMetricStats; +struct envoy_api_v2_endpoint_ClusterStats; +struct envoy_api_v2_endpoint_ClusterStats_DroppedRequests; +typedef struct envoy_api_v2_endpoint_UpstreamLocalityStats envoy_api_v2_endpoint_UpstreamLocalityStats; +typedef struct envoy_api_v2_endpoint_UpstreamEndpointStats envoy_api_v2_endpoint_UpstreamEndpointStats; +typedef struct envoy_api_v2_endpoint_EndpointLoadMetricStats envoy_api_v2_endpoint_EndpointLoadMetricStats; +typedef struct envoy_api_v2_endpoint_ClusterStats envoy_api_v2_endpoint_ClusterStats; +typedef struct envoy_api_v2_endpoint_ClusterStats_DroppedRequests envoy_api_v2_endpoint_ClusterStats_DroppedRequests; +extern const upb_msglayout envoy_api_v2_endpoint_UpstreamLocalityStats_msginit; +extern const upb_msglayout envoy_api_v2_endpoint_UpstreamEndpointStats_msginit; +extern const upb_msglayout envoy_api_v2_endpoint_EndpointLoadMetricStats_msginit; +extern const upb_msglayout envoy_api_v2_endpoint_ClusterStats_msginit; +extern const upb_msglayout envoy_api_v2_endpoint_ClusterStats_DroppedRequests_msginit; +struct envoy_api_v2_core_Address; +struct envoy_api_v2_core_Locality; +struct google_protobuf_Duration; +extern const upb_msglayout envoy_api_v2_core_Address_msginit; +extern const upb_msglayout envoy_api_v2_core_Locality_msginit; +extern const upb_msglayout google_protobuf_Duration_msginit; + +/* Enums */ + + +/* envoy.api.v2.endpoint.UpstreamLocalityStats */ + +UPB_INLINE envoy_api_v2_endpoint_UpstreamLocalityStats *envoy_api_v2_endpoint_UpstreamLocalityStats_new(upb_arena *arena) { + return (envoy_api_v2_endpoint_UpstreamLocalityStats *)upb_msg_new(&envoy_api_v2_endpoint_UpstreamLocalityStats_msginit, arena); +} +UPB_INLINE envoy_api_v2_endpoint_UpstreamLocalityStats *envoy_api_v2_endpoint_UpstreamLocalityStats_parsenew(upb_strview buf, upb_arena *arena) { + envoy_api_v2_endpoint_UpstreamLocalityStats *ret = envoy_api_v2_endpoint_UpstreamLocalityStats_new(arena); + return (ret && upb_decode(buf, ret, &envoy_api_v2_endpoint_UpstreamLocalityStats_msginit)) ? ret : NULL; +} +UPB_INLINE char *envoy_api_v2_endpoint_UpstreamLocalityStats_serialize(const envoy_api_v2_endpoint_UpstreamLocalityStats *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_api_v2_endpoint_UpstreamLocalityStats_msginit, arena, len); +} + +UPB_INLINE const struct envoy_api_v2_core_Locality* envoy_api_v2_endpoint_UpstreamLocalityStats_locality(const envoy_api_v2_endpoint_UpstreamLocalityStats *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_Locality*, UPB_SIZE(28, 32)); } +UPB_INLINE uint64_t envoy_api_v2_endpoint_UpstreamLocalityStats_total_successful_requests(const envoy_api_v2_endpoint_UpstreamLocalityStats *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)); } +UPB_INLINE uint64_t envoy_api_v2_endpoint_UpstreamLocalityStats_total_requests_in_progress(const envoy_api_v2_endpoint_UpstreamLocalityStats *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(8, 8)); } +UPB_INLINE uint64_t envoy_api_v2_endpoint_UpstreamLocalityStats_total_error_requests(const envoy_api_v2_endpoint_UpstreamLocalityStats *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(16, 16)); } +UPB_INLINE const envoy_api_v2_endpoint_EndpointLoadMetricStats* const* envoy_api_v2_endpoint_UpstreamLocalityStats_load_metric_stats(const envoy_api_v2_endpoint_UpstreamLocalityStats *msg, size_t *len) { return (const envoy_api_v2_endpoint_EndpointLoadMetricStats* const*)_upb_array_accessor(msg, UPB_SIZE(32, 40), len); } +UPB_INLINE uint32_t envoy_api_v2_endpoint_UpstreamLocalityStats_priority(const envoy_api_v2_endpoint_UpstreamLocalityStats *msg) { return UPB_FIELD_AT(msg, uint32_t, UPB_SIZE(24, 24)); } +UPB_INLINE const envoy_api_v2_endpoint_UpstreamEndpointStats* const* envoy_api_v2_endpoint_UpstreamLocalityStats_upstream_endpoint_stats(const envoy_api_v2_endpoint_UpstreamLocalityStats *msg, size_t *len) { return (const envoy_api_v2_endpoint_UpstreamEndpointStats* const*)_upb_array_accessor(msg, UPB_SIZE(36, 48), len); } + +UPB_INLINE void envoy_api_v2_endpoint_UpstreamLocalityStats_set_locality(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, struct envoy_api_v2_core_Locality* value) { + UPB_FIELD_AT(msg, struct envoy_api_v2_core_Locality*, UPB_SIZE(28, 32)) = value; +} +UPB_INLINE struct envoy_api_v2_core_Locality* envoy_api_v2_endpoint_UpstreamLocalityStats_mutable_locality(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, upb_arena *arena) { + struct envoy_api_v2_core_Locality* sub = (struct envoy_api_v2_core_Locality*)envoy_api_v2_endpoint_UpstreamLocalityStats_locality(msg); + if (sub == NULL) { + sub = (struct envoy_api_v2_core_Locality*)upb_msg_new(&envoy_api_v2_core_Locality_msginit, arena); + if (!sub) return NULL; + envoy_api_v2_endpoint_UpstreamLocalityStats_set_locality(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_api_v2_endpoint_UpstreamLocalityStats_set_total_successful_requests(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, uint64_t value) { + UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)) = value; +} +UPB_INLINE void envoy_api_v2_endpoint_UpstreamLocalityStats_set_total_requests_in_progress(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, uint64_t value) { + UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(8, 8)) = value; +} +UPB_INLINE void envoy_api_v2_endpoint_UpstreamLocalityStats_set_total_error_requests(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, uint64_t value) { + UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(16, 16)) = value; +} +UPB_INLINE envoy_api_v2_endpoint_EndpointLoadMetricStats** envoy_api_v2_endpoint_UpstreamLocalityStats_mutable_load_metric_stats(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, size_t *len) { + return (envoy_api_v2_endpoint_EndpointLoadMetricStats**)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 40), len); +} +UPB_INLINE envoy_api_v2_endpoint_EndpointLoadMetricStats** envoy_api_v2_endpoint_UpstreamLocalityStats_resize_load_metric_stats(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, size_t len, upb_arena *arena) { + return (envoy_api_v2_endpoint_EndpointLoadMetricStats**)_upb_array_resize_accessor(msg, UPB_SIZE(32, 40), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); +} +UPB_INLINE struct envoy_api_v2_endpoint_EndpointLoadMetricStats* envoy_api_v2_endpoint_UpstreamLocalityStats_add_load_metric_stats(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, upb_arena *arena) { + struct envoy_api_v2_endpoint_EndpointLoadMetricStats* sub = (struct envoy_api_v2_endpoint_EndpointLoadMetricStats*)upb_msg_new(&envoy_api_v2_endpoint_EndpointLoadMetricStats_msginit, arena); + bool ok = _upb_array_append_accessor( + msg, UPB_SIZE(32, 40), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void envoy_api_v2_endpoint_UpstreamLocalityStats_set_priority(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, uint32_t value) { + UPB_FIELD_AT(msg, uint32_t, UPB_SIZE(24, 24)) = value; +} +UPB_INLINE envoy_api_v2_endpoint_UpstreamEndpointStats** envoy_api_v2_endpoint_UpstreamLocalityStats_mutable_upstream_endpoint_stats(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, size_t *len) { + return (envoy_api_v2_endpoint_UpstreamEndpointStats**)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 48), len); +} +UPB_INLINE envoy_api_v2_endpoint_UpstreamEndpointStats** envoy_api_v2_endpoint_UpstreamLocalityStats_resize_upstream_endpoint_stats(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, size_t len, upb_arena *arena) { + return (envoy_api_v2_endpoint_UpstreamEndpointStats**)_upb_array_resize_accessor(msg, UPB_SIZE(36, 48), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); +} +UPB_INLINE struct envoy_api_v2_endpoint_UpstreamEndpointStats* envoy_api_v2_endpoint_UpstreamLocalityStats_add_upstream_endpoint_stats(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, upb_arena *arena) { + struct envoy_api_v2_endpoint_UpstreamEndpointStats* sub = (struct envoy_api_v2_endpoint_UpstreamEndpointStats*)upb_msg_new(&envoy_api_v2_endpoint_UpstreamEndpointStats_msginit, arena); + bool ok = _upb_array_append_accessor( + msg, UPB_SIZE(36, 48), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); + if (!ok) return NULL; + return sub; +} + + +/* envoy.api.v2.endpoint.UpstreamEndpointStats */ + +UPB_INLINE envoy_api_v2_endpoint_UpstreamEndpointStats *envoy_api_v2_endpoint_UpstreamEndpointStats_new(upb_arena *arena) { + return (envoy_api_v2_endpoint_UpstreamEndpointStats *)upb_msg_new(&envoy_api_v2_endpoint_UpstreamEndpointStats_msginit, arena); +} +UPB_INLINE envoy_api_v2_endpoint_UpstreamEndpointStats *envoy_api_v2_endpoint_UpstreamEndpointStats_parsenew(upb_strview buf, upb_arena *arena) { + envoy_api_v2_endpoint_UpstreamEndpointStats *ret = envoy_api_v2_endpoint_UpstreamEndpointStats_new(arena); + return (ret && upb_decode(buf, ret, &envoy_api_v2_endpoint_UpstreamEndpointStats_msginit)) ? ret : NULL; +} +UPB_INLINE char *envoy_api_v2_endpoint_UpstreamEndpointStats_serialize(const envoy_api_v2_endpoint_UpstreamEndpointStats *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_api_v2_endpoint_UpstreamEndpointStats_msginit, arena, len); +} + +UPB_INLINE const struct envoy_api_v2_core_Address* envoy_api_v2_endpoint_UpstreamEndpointStats_address(const envoy_api_v2_endpoint_UpstreamEndpointStats *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_Address*, UPB_SIZE(24, 24)); } +UPB_INLINE uint64_t envoy_api_v2_endpoint_UpstreamEndpointStats_total_successful_requests(const envoy_api_v2_endpoint_UpstreamEndpointStats *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)); } +UPB_INLINE uint64_t envoy_api_v2_endpoint_UpstreamEndpointStats_total_requests_in_progress(const envoy_api_v2_endpoint_UpstreamEndpointStats *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(8, 8)); } +UPB_INLINE uint64_t envoy_api_v2_endpoint_UpstreamEndpointStats_total_error_requests(const envoy_api_v2_endpoint_UpstreamEndpointStats *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(16, 16)); } +UPB_INLINE const envoy_api_v2_endpoint_EndpointLoadMetricStats* const* envoy_api_v2_endpoint_UpstreamEndpointStats_load_metric_stats(const envoy_api_v2_endpoint_UpstreamEndpointStats *msg, size_t *len) { return (const envoy_api_v2_endpoint_EndpointLoadMetricStats* const*)_upb_array_accessor(msg, UPB_SIZE(28, 32), len); } + +UPB_INLINE void envoy_api_v2_endpoint_UpstreamEndpointStats_set_address(envoy_api_v2_endpoint_UpstreamEndpointStats *msg, struct envoy_api_v2_core_Address* value) { + UPB_FIELD_AT(msg, struct envoy_api_v2_core_Address*, UPB_SIZE(24, 24)) = value; +} +UPB_INLINE struct envoy_api_v2_core_Address* envoy_api_v2_endpoint_UpstreamEndpointStats_mutable_address(envoy_api_v2_endpoint_UpstreamEndpointStats *msg, upb_arena *arena) { + struct envoy_api_v2_core_Address* sub = (struct envoy_api_v2_core_Address*)envoy_api_v2_endpoint_UpstreamEndpointStats_address(msg); + if (sub == NULL) { + sub = (struct envoy_api_v2_core_Address*)upb_msg_new(&envoy_api_v2_core_Address_msginit, arena); + if (!sub) return NULL; + envoy_api_v2_endpoint_UpstreamEndpointStats_set_address(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_api_v2_endpoint_UpstreamEndpointStats_set_total_successful_requests(envoy_api_v2_endpoint_UpstreamEndpointStats *msg, uint64_t value) { + UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)) = value; +} +UPB_INLINE void envoy_api_v2_endpoint_UpstreamEndpointStats_set_total_requests_in_progress(envoy_api_v2_endpoint_UpstreamEndpointStats *msg, uint64_t value) { + UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(8, 8)) = value; +} +UPB_INLINE void envoy_api_v2_endpoint_UpstreamEndpointStats_set_total_error_requests(envoy_api_v2_endpoint_UpstreamEndpointStats *msg, uint64_t value) { + UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(16, 16)) = value; +} +UPB_INLINE envoy_api_v2_endpoint_EndpointLoadMetricStats** envoy_api_v2_endpoint_UpstreamEndpointStats_mutable_load_metric_stats(envoy_api_v2_endpoint_UpstreamEndpointStats *msg, size_t *len) { + return (envoy_api_v2_endpoint_EndpointLoadMetricStats**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 32), len); +} +UPB_INLINE envoy_api_v2_endpoint_EndpointLoadMetricStats** envoy_api_v2_endpoint_UpstreamEndpointStats_resize_load_metric_stats(envoy_api_v2_endpoint_UpstreamEndpointStats *msg, size_t len, upb_arena *arena) { + return (envoy_api_v2_endpoint_EndpointLoadMetricStats**)_upb_array_resize_accessor(msg, UPB_SIZE(28, 32), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); +} +UPB_INLINE struct envoy_api_v2_endpoint_EndpointLoadMetricStats* envoy_api_v2_endpoint_UpstreamEndpointStats_add_load_metric_stats(envoy_api_v2_endpoint_UpstreamEndpointStats *msg, upb_arena *arena) { + struct envoy_api_v2_endpoint_EndpointLoadMetricStats* sub = (struct envoy_api_v2_endpoint_EndpointLoadMetricStats*)upb_msg_new(&envoy_api_v2_endpoint_EndpointLoadMetricStats_msginit, arena); + bool ok = _upb_array_append_accessor( + msg, UPB_SIZE(28, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); + if (!ok) return NULL; + return sub; +} + + +/* envoy.api.v2.endpoint.EndpointLoadMetricStats */ + +UPB_INLINE envoy_api_v2_endpoint_EndpointLoadMetricStats *envoy_api_v2_endpoint_EndpointLoadMetricStats_new(upb_arena *arena) { + return (envoy_api_v2_endpoint_EndpointLoadMetricStats *)upb_msg_new(&envoy_api_v2_endpoint_EndpointLoadMetricStats_msginit, arena); +} +UPB_INLINE envoy_api_v2_endpoint_EndpointLoadMetricStats *envoy_api_v2_endpoint_EndpointLoadMetricStats_parsenew(upb_strview buf, upb_arena *arena) { + envoy_api_v2_endpoint_EndpointLoadMetricStats *ret = envoy_api_v2_endpoint_EndpointLoadMetricStats_new(arena); + return (ret && upb_decode(buf, ret, &envoy_api_v2_endpoint_EndpointLoadMetricStats_msginit)) ? ret : NULL; +} +UPB_INLINE char *envoy_api_v2_endpoint_EndpointLoadMetricStats_serialize(const envoy_api_v2_endpoint_EndpointLoadMetricStats *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_api_v2_endpoint_EndpointLoadMetricStats_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_api_v2_endpoint_EndpointLoadMetricStats_metric_name(const envoy_api_v2_endpoint_EndpointLoadMetricStats *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(16, 16)); } +UPB_INLINE uint64_t envoy_api_v2_endpoint_EndpointLoadMetricStats_num_requests_finished_with_metric(const envoy_api_v2_endpoint_EndpointLoadMetricStats *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)); } +UPB_INLINE double envoy_api_v2_endpoint_EndpointLoadMetricStats_total_metric_value(const envoy_api_v2_endpoint_EndpointLoadMetricStats *msg) { return UPB_FIELD_AT(msg, double, UPB_SIZE(8, 8)); } + +UPB_INLINE void envoy_api_v2_endpoint_EndpointLoadMetricStats_set_metric_name(envoy_api_v2_endpoint_EndpointLoadMetricStats *msg, upb_strview value) { + UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(16, 16)) = value; +} +UPB_INLINE void envoy_api_v2_endpoint_EndpointLoadMetricStats_set_num_requests_finished_with_metric(envoy_api_v2_endpoint_EndpointLoadMetricStats *msg, uint64_t value) { + UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)) = value; +} +UPB_INLINE void envoy_api_v2_endpoint_EndpointLoadMetricStats_set_total_metric_value(envoy_api_v2_endpoint_EndpointLoadMetricStats *msg, double value) { + UPB_FIELD_AT(msg, double, UPB_SIZE(8, 8)) = value; +} + + +/* envoy.api.v2.endpoint.ClusterStats */ + +UPB_INLINE envoy_api_v2_endpoint_ClusterStats *envoy_api_v2_endpoint_ClusterStats_new(upb_arena *arena) { + return (envoy_api_v2_endpoint_ClusterStats *)upb_msg_new(&envoy_api_v2_endpoint_ClusterStats_msginit, arena); +} +UPB_INLINE envoy_api_v2_endpoint_ClusterStats *envoy_api_v2_endpoint_ClusterStats_parsenew(upb_strview buf, upb_arena *arena) { + envoy_api_v2_endpoint_ClusterStats *ret = envoy_api_v2_endpoint_ClusterStats_new(arena); + return (ret && upb_decode(buf, ret, &envoy_api_v2_endpoint_ClusterStats_msginit)) ? ret : NULL; +} +UPB_INLINE char *envoy_api_v2_endpoint_ClusterStats_serialize(const envoy_api_v2_endpoint_ClusterStats *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_api_v2_endpoint_ClusterStats_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_api_v2_endpoint_ClusterStats_cluster_name(const envoy_api_v2_endpoint_ClusterStats *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(8, 8)); } +UPB_INLINE const envoy_api_v2_endpoint_UpstreamLocalityStats* const* envoy_api_v2_endpoint_ClusterStats_upstream_locality_stats(const envoy_api_v2_endpoint_ClusterStats *msg, size_t *len) { return (const envoy_api_v2_endpoint_UpstreamLocalityStats* const*)_upb_array_accessor(msg, UPB_SIZE(20, 32), len); } +UPB_INLINE uint64_t envoy_api_v2_endpoint_ClusterStats_total_dropped_requests(const envoy_api_v2_endpoint_ClusterStats *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)); } +UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_endpoint_ClusterStats_load_report_interval(const envoy_api_v2_endpoint_ClusterStats *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(16, 24)); } +UPB_INLINE const envoy_api_v2_endpoint_ClusterStats_DroppedRequests* const* envoy_api_v2_endpoint_ClusterStats_dropped_requests(const envoy_api_v2_endpoint_ClusterStats *msg, size_t *len) { return (const envoy_api_v2_endpoint_ClusterStats_DroppedRequests* const*)_upb_array_accessor(msg, UPB_SIZE(24, 40), len); } + +UPB_INLINE void envoy_api_v2_endpoint_ClusterStats_set_cluster_name(envoy_api_v2_endpoint_ClusterStats *msg, upb_strview value) { + UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(8, 8)) = value; +} +UPB_INLINE envoy_api_v2_endpoint_UpstreamLocalityStats** envoy_api_v2_endpoint_ClusterStats_mutable_upstream_locality_stats(envoy_api_v2_endpoint_ClusterStats *msg, size_t *len) { + return (envoy_api_v2_endpoint_UpstreamLocalityStats**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 32), len); +} +UPB_INLINE envoy_api_v2_endpoint_UpstreamLocalityStats** envoy_api_v2_endpoint_ClusterStats_resize_upstream_locality_stats(envoy_api_v2_endpoint_ClusterStats *msg, size_t len, upb_arena *arena) { + return (envoy_api_v2_endpoint_UpstreamLocalityStats**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 32), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); +} +UPB_INLINE struct envoy_api_v2_endpoint_UpstreamLocalityStats* envoy_api_v2_endpoint_ClusterStats_add_upstream_locality_stats(envoy_api_v2_endpoint_ClusterStats *msg, upb_arena *arena) { + struct envoy_api_v2_endpoint_UpstreamLocalityStats* sub = (struct envoy_api_v2_endpoint_UpstreamLocalityStats*)upb_msg_new(&envoy_api_v2_endpoint_UpstreamLocalityStats_msginit, arena); + bool ok = _upb_array_append_accessor( + msg, UPB_SIZE(20, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void envoy_api_v2_endpoint_ClusterStats_set_total_dropped_requests(envoy_api_v2_endpoint_ClusterStats *msg, uint64_t value) { + UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)) = value; +} +UPB_INLINE void envoy_api_v2_endpoint_ClusterStats_set_load_report_interval(envoy_api_v2_endpoint_ClusterStats *msg, struct google_protobuf_Duration* value) { + UPB_FIELD_AT(msg, struct google_protobuf_Duration*, UPB_SIZE(16, 24)) = value; +} +UPB_INLINE struct google_protobuf_Duration* envoy_api_v2_endpoint_ClusterStats_mutable_load_report_interval(envoy_api_v2_endpoint_ClusterStats *msg, upb_arena *arena) { + struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_api_v2_endpoint_ClusterStats_load_report_interval(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Duration*)upb_msg_new(&google_protobuf_Duration_msginit, arena); + if (!sub) return NULL; + envoy_api_v2_endpoint_ClusterStats_set_load_report_interval(msg, sub); + } + return sub; +} +UPB_INLINE envoy_api_v2_endpoint_ClusterStats_DroppedRequests** envoy_api_v2_endpoint_ClusterStats_mutable_dropped_requests(envoy_api_v2_endpoint_ClusterStats *msg, size_t *len) { + return (envoy_api_v2_endpoint_ClusterStats_DroppedRequests**)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 40), len); +} +UPB_INLINE envoy_api_v2_endpoint_ClusterStats_DroppedRequests** envoy_api_v2_endpoint_ClusterStats_resize_dropped_requests(envoy_api_v2_endpoint_ClusterStats *msg, size_t len, upb_arena *arena) { + return (envoy_api_v2_endpoint_ClusterStats_DroppedRequests**)_upb_array_resize_accessor(msg, UPB_SIZE(24, 40), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); +} +UPB_INLINE struct envoy_api_v2_endpoint_ClusterStats_DroppedRequests* envoy_api_v2_endpoint_ClusterStats_add_dropped_requests(envoy_api_v2_endpoint_ClusterStats *msg, upb_arena *arena) { + struct envoy_api_v2_endpoint_ClusterStats_DroppedRequests* sub = (struct envoy_api_v2_endpoint_ClusterStats_DroppedRequests*)upb_msg_new(&envoy_api_v2_endpoint_ClusterStats_DroppedRequests_msginit, arena); + bool ok = _upb_array_append_accessor( + msg, UPB_SIZE(24, 40), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); + if (!ok) return NULL; + return sub; +} + + +/* envoy.api.v2.endpoint.ClusterStats.DroppedRequests */ + +UPB_INLINE envoy_api_v2_endpoint_ClusterStats_DroppedRequests *envoy_api_v2_endpoint_ClusterStats_DroppedRequests_new(upb_arena *arena) { + return (envoy_api_v2_endpoint_ClusterStats_DroppedRequests *)upb_msg_new(&envoy_api_v2_endpoint_ClusterStats_DroppedRequests_msginit, arena); +} +UPB_INLINE envoy_api_v2_endpoint_ClusterStats_DroppedRequests *envoy_api_v2_endpoint_ClusterStats_DroppedRequests_parsenew(upb_strview buf, upb_arena *arena) { + envoy_api_v2_endpoint_ClusterStats_DroppedRequests *ret = envoy_api_v2_endpoint_ClusterStats_DroppedRequests_new(arena); + return (ret && upb_decode(buf, ret, &envoy_api_v2_endpoint_ClusterStats_DroppedRequests_msginit)) ? ret : NULL; +} +UPB_INLINE char *envoy_api_v2_endpoint_ClusterStats_DroppedRequests_serialize(const envoy_api_v2_endpoint_ClusterStats_DroppedRequests *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_api_v2_endpoint_ClusterStats_DroppedRequests_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_api_v2_endpoint_ClusterStats_DroppedRequests_category(const envoy_api_v2_endpoint_ClusterStats_DroppedRequests *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(8, 8)); } +UPB_INLINE uint64_t envoy_api_v2_endpoint_ClusterStats_DroppedRequests_dropped_count(const envoy_api_v2_endpoint_ClusterStats_DroppedRequests *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)); } + +UPB_INLINE void envoy_api_v2_endpoint_ClusterStats_DroppedRequests_set_category(envoy_api_v2_endpoint_ClusterStats_DroppedRequests *msg, upb_strview value) { + UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(8, 8)) = value; +} +UPB_INLINE void envoy_api_v2_endpoint_ClusterStats_DroppedRequests_set_dropped_count(envoy_api_v2_endpoint_ClusterStats_DroppedRequests *msg, uint64_t value) { + UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)) = value; +} + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_API_V2_ENDPOINT_LOAD_REPORT_PROTO_UPB_H_ */ diff --git a/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c b/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c new file mode 100644 index 00000000000..a6e4bd2d18b --- /dev/null +++ b/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c @@ -0,0 +1,52 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/service/load_stats/v2/lrs.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include +#include "upb/msg.h" +#include "envoy/service/load_stats/v2/lrs.upb.h" +#include "envoy/api/v2/core/base.upb.h" +#include "envoy/api/v2/endpoint/load_report.upb.h" +#include "google/protobuf/duration.upb.h" +#include "validate/validate.upb.h" + +#include "upb/port_def.inc" + +static const upb_msglayout *const envoy_service_load_stats_v2_LoadStatsRequest_submsgs[2] = { + &envoy_api_v2_core_Node_msginit, + &envoy_api_v2_endpoint_ClusterStats_msginit, +}; + +static const upb_msglayout_field envoy_service_load_stats_v2_LoadStatsRequest__fields[2] = { + {1, UPB_SIZE(0, 0), 0, 0, 11, 1}, + {2, UPB_SIZE(4, 8), 0, 1, 11, 3}, +}; + +const upb_msglayout envoy_service_load_stats_v2_LoadStatsRequest_msginit = { + &envoy_service_load_stats_v2_LoadStatsRequest_submsgs[0], + &envoy_service_load_stats_v2_LoadStatsRequest__fields[0], + UPB_SIZE(8, 16), 2, false, +}; + +static const upb_msglayout *const envoy_service_load_stats_v2_LoadStatsResponse_submsgs[1] = { + &google_protobuf_Duration_msginit, +}; + +static const upb_msglayout_field envoy_service_load_stats_v2_LoadStatsResponse__fields[3] = { + {1, UPB_SIZE(8, 16), 0, 0, 9, 3}, + {2, UPB_SIZE(4, 8), 0, 0, 11, 1}, + {3, UPB_SIZE(0, 0), 0, 0, 8, 1}, +}; + +const upb_msglayout envoy_service_load_stats_v2_LoadStatsResponse_msginit = { + &envoy_service_load_stats_v2_LoadStatsResponse_submsgs[0], + &envoy_service_load_stats_v2_LoadStatsResponse__fields[0], + UPB_SIZE(12, 24), 3, false, +}; + +#include "upb/port_undef.inc" + diff --git a/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h b/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h new file mode 100644 index 00000000000..99db767a8a1 --- /dev/null +++ b/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h @@ -0,0 +1,132 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/service/load_stats/v2/lrs.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_SERVICE_LOAD_STATS_V2_LRS_PROTO_UPB_H_ +#define ENVOY_SERVICE_LOAD_STATS_V2_LRS_PROTO_UPB_H_ + +#include "upb/generated_util.h" + +#include "upb/msg.h" + +#include "upb/decode.h" +#include "upb/encode.h" +#include "upb/port_def.inc" +#ifdef __cplusplus +extern "C" { +#endif + +struct envoy_service_load_stats_v2_LoadStatsRequest; +struct envoy_service_load_stats_v2_LoadStatsResponse; +typedef struct envoy_service_load_stats_v2_LoadStatsRequest envoy_service_load_stats_v2_LoadStatsRequest; +typedef struct envoy_service_load_stats_v2_LoadStatsResponse envoy_service_load_stats_v2_LoadStatsResponse; +extern const upb_msglayout envoy_service_load_stats_v2_LoadStatsRequest_msginit; +extern const upb_msglayout envoy_service_load_stats_v2_LoadStatsResponse_msginit; +struct envoy_api_v2_core_Node; +struct envoy_api_v2_endpoint_ClusterStats; +struct google_protobuf_Duration; +extern const upb_msglayout envoy_api_v2_core_Node_msginit; +extern const upb_msglayout envoy_api_v2_endpoint_ClusterStats_msginit; +extern const upb_msglayout google_protobuf_Duration_msginit; + +/* Enums */ + + +/* envoy.service.load_stats.v2.LoadStatsRequest */ + +UPB_INLINE envoy_service_load_stats_v2_LoadStatsRequest *envoy_service_load_stats_v2_LoadStatsRequest_new(upb_arena *arena) { + return (envoy_service_load_stats_v2_LoadStatsRequest *)upb_msg_new(&envoy_service_load_stats_v2_LoadStatsRequest_msginit, arena); +} +UPB_INLINE envoy_service_load_stats_v2_LoadStatsRequest *envoy_service_load_stats_v2_LoadStatsRequest_parsenew(upb_strview buf, upb_arena *arena) { + envoy_service_load_stats_v2_LoadStatsRequest *ret = envoy_service_load_stats_v2_LoadStatsRequest_new(arena); + return (ret && upb_decode(buf, ret, &envoy_service_load_stats_v2_LoadStatsRequest_msginit)) ? ret : NULL; +} +UPB_INLINE char *envoy_service_load_stats_v2_LoadStatsRequest_serialize(const envoy_service_load_stats_v2_LoadStatsRequest *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_service_load_stats_v2_LoadStatsRequest_msginit, arena, len); +} + +UPB_INLINE const struct envoy_api_v2_core_Node* envoy_service_load_stats_v2_LoadStatsRequest_node(const envoy_service_load_stats_v2_LoadStatsRequest *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_Node*, UPB_SIZE(0, 0)); } +UPB_INLINE const struct envoy_api_v2_endpoint_ClusterStats* const* envoy_service_load_stats_v2_LoadStatsRequest_cluster_stats(const envoy_service_load_stats_v2_LoadStatsRequest *msg, size_t *len) { return (const struct envoy_api_v2_endpoint_ClusterStats* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } + +UPB_INLINE void envoy_service_load_stats_v2_LoadStatsRequest_set_node(envoy_service_load_stats_v2_LoadStatsRequest *msg, struct envoy_api_v2_core_Node* value) { + UPB_FIELD_AT(msg, struct envoy_api_v2_core_Node*, UPB_SIZE(0, 0)) = value; +} +UPB_INLINE struct envoy_api_v2_core_Node* envoy_service_load_stats_v2_LoadStatsRequest_mutable_node(envoy_service_load_stats_v2_LoadStatsRequest *msg, upb_arena *arena) { + struct envoy_api_v2_core_Node* sub = (struct envoy_api_v2_core_Node*)envoy_service_load_stats_v2_LoadStatsRequest_node(msg); + if (sub == NULL) { + sub = (struct envoy_api_v2_core_Node*)upb_msg_new(&envoy_api_v2_core_Node_msginit, arena); + if (!sub) return NULL; + envoy_service_load_stats_v2_LoadStatsRequest_set_node(msg, sub); + } + return sub; +} +UPB_INLINE struct envoy_api_v2_endpoint_ClusterStats** envoy_service_load_stats_v2_LoadStatsRequest_mutable_cluster_stats(envoy_service_load_stats_v2_LoadStatsRequest *msg, size_t *len) { + return (struct envoy_api_v2_endpoint_ClusterStats**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); +} +UPB_INLINE struct envoy_api_v2_endpoint_ClusterStats** envoy_service_load_stats_v2_LoadStatsRequest_resize_cluster_stats(envoy_service_load_stats_v2_LoadStatsRequest *msg, size_t len, upb_arena *arena) { + return (struct envoy_api_v2_endpoint_ClusterStats**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); +} +UPB_INLINE struct envoy_api_v2_endpoint_ClusterStats* envoy_service_load_stats_v2_LoadStatsRequest_add_cluster_stats(envoy_service_load_stats_v2_LoadStatsRequest *msg, upb_arena *arena) { + struct envoy_api_v2_endpoint_ClusterStats* sub = (struct envoy_api_v2_endpoint_ClusterStats*)upb_msg_new(&envoy_api_v2_endpoint_ClusterStats_msginit, arena); + bool ok = _upb_array_append_accessor( + msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); + if (!ok) return NULL; + return sub; +} + + +/* envoy.service.load_stats.v2.LoadStatsResponse */ + +UPB_INLINE envoy_service_load_stats_v2_LoadStatsResponse *envoy_service_load_stats_v2_LoadStatsResponse_new(upb_arena *arena) { + return (envoy_service_load_stats_v2_LoadStatsResponse *)upb_msg_new(&envoy_service_load_stats_v2_LoadStatsResponse_msginit, arena); +} +UPB_INLINE envoy_service_load_stats_v2_LoadStatsResponse *envoy_service_load_stats_v2_LoadStatsResponse_parsenew(upb_strview buf, upb_arena *arena) { + envoy_service_load_stats_v2_LoadStatsResponse *ret = envoy_service_load_stats_v2_LoadStatsResponse_new(arena); + return (ret && upb_decode(buf, ret, &envoy_service_load_stats_v2_LoadStatsResponse_msginit)) ? ret : NULL; +} +UPB_INLINE char *envoy_service_load_stats_v2_LoadStatsResponse_serialize(const envoy_service_load_stats_v2_LoadStatsResponse *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_service_load_stats_v2_LoadStatsResponse_msginit, arena, len); +} + +UPB_INLINE upb_strview const* envoy_service_load_stats_v2_LoadStatsResponse_clusters(const envoy_service_load_stats_v2_LoadStatsResponse *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); } +UPB_INLINE const struct google_protobuf_Duration* envoy_service_load_stats_v2_LoadStatsResponse_load_reporting_interval(const envoy_service_load_stats_v2_LoadStatsResponse *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(4, 8)); } +UPB_INLINE bool envoy_service_load_stats_v2_LoadStatsResponse_report_endpoint_granularity(const envoy_service_load_stats_v2_LoadStatsResponse *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(0, 0)); } + +UPB_INLINE upb_strview* envoy_service_load_stats_v2_LoadStatsResponse_mutable_clusters(envoy_service_load_stats_v2_LoadStatsResponse *msg, size_t *len) { + return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len); +} +UPB_INLINE upb_strview* envoy_service_load_stats_v2_LoadStatsResponse_resize_clusters(envoy_service_load_stats_v2_LoadStatsResponse *msg, size_t len, upb_arena *arena) { + return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(8, 16), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena); +} +UPB_INLINE bool envoy_service_load_stats_v2_LoadStatsResponse_add_clusters(envoy_service_load_stats_v2_LoadStatsResponse *msg, upb_strview val, upb_arena *arena) { + return _upb_array_append_accessor( + msg, UPB_SIZE(8, 16), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena); +} +UPB_INLINE void envoy_service_load_stats_v2_LoadStatsResponse_set_load_reporting_interval(envoy_service_load_stats_v2_LoadStatsResponse *msg, struct google_protobuf_Duration* value) { + UPB_FIELD_AT(msg, struct google_protobuf_Duration*, UPB_SIZE(4, 8)) = value; +} +UPB_INLINE struct google_protobuf_Duration* envoy_service_load_stats_v2_LoadStatsResponse_mutable_load_reporting_interval(envoy_service_load_stats_v2_LoadStatsResponse *msg, upb_arena *arena) { + struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_service_load_stats_v2_LoadStatsResponse_load_reporting_interval(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Duration*)upb_msg_new(&google_protobuf_Duration_msginit, arena); + if (!sub) return NULL; + envoy_service_load_stats_v2_LoadStatsResponse_set_load_reporting_interval(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_service_load_stats_v2_LoadStatsResponse_set_report_endpoint_granularity(envoy_service_load_stats_v2_LoadStatsResponse *msg, bool value) { + UPB_FIELD_AT(msg, bool, UPB_SIZE(0, 0)) = value; +} + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_SERVICE_LOAD_STATS_V2_LRS_PROTO_UPB_H_ */ diff --git a/tools/codegen/core/gen_upb_api.sh b/tools/codegen/core/gen_upb_api.sh index 2ca36b70661..ff21c49362c 100755 --- a/tools/codegen/core/gen_upb_api.sh +++ b/tools/codegen/core/gen_upb_api.sh @@ -52,7 +52,9 @@ proto_files=( \ "envoy/api/v2/cds.proto" \ "envoy/api/v2/eds.proto" \ "envoy/api/v2/endpoint/endpoint.proto" \ - "envoy/service/discovery/v2/ads.proto") + "envoy/api/v2/endpoint/load_report.proto" \ + "envoy/service/discovery/v2/ads.proto" \ + "envoy/service/load_stats/v2/lrs.proto") for i in "${proto_files[@]}" do From ab29cdd28e75733987529c06da47a68c461ef989 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Tue, 9 Apr 2019 12:50:39 -0700 Subject: [PATCH 227/242] Add test --- test/core/end2end/tests/simple_request.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/core/end2end/tests/simple_request.cc b/test/core/end2end/tests/simple_request.cc index 9c018962f83..a8c57899e2c 100644 --- a/test/core/end2end/tests/simple_request.cc +++ b/test/core/end2end/tests/simple_request.cc @@ -86,6 +86,14 @@ static void end_test(grpc_end2end_test_fixture* f) { grpc_completion_queue_destroy(f->shutdown_cq); } +static void check_peer(char* peer_name) { + // If the peer name is a uds path, then check if it is filled + if (strncmp(peer_name, "unix:/", strlen("unix:/")) == 0) { + GPR_ASSERT(strncmp(peer_name, "unix:/tmp/grpc_fullstack_test.", + strlen("unix:/tmp/grpc_fullstack_test.")) == 0); + } +} + static void simple_request_body(grpc_end2end_test_config config, grpc_end2end_test_fixture f) { grpc_call* c; @@ -166,10 +174,12 @@ static void simple_request_body(grpc_end2end_test_config config, peer = grpc_call_get_peer(s); GPR_ASSERT(peer != nullptr); gpr_log(GPR_DEBUG, "server_peer=%s", peer); + check_peer(peer); gpr_free(peer); peer = grpc_call_get_peer(c); GPR_ASSERT(peer != nullptr); gpr_log(GPR_DEBUG, "client_peer=%s", peer); + check_peer(peer); gpr_free(peer); memset(ops, 0, sizeof(ops)); From 5afd77398e7c8dc8175b7d06fac939659edecf7c Mon Sep 17 00:00:00 2001 From: Richard Belleville Date: Wed, 20 Mar 2019 16:04:33 -0700 Subject: [PATCH 228/242] Implement compression API within gRPC Python. --- .pylintrc | 4 +- doc/python/sphinx/grpc.rst | 6 + src/python/grpcio/grpc/BUILD.bazel | 8 + src/python/grpcio/grpc/__init__.py | 96 ++++- src/python/grpcio/grpc/_channel.py | 114 +++--- src/python/grpcio/grpc/_compression.py | 55 +++ .../grpcio/grpc/_cython/_cygrpc/grpc.pxi | 8 +- .../grpc/_cython/_cygrpc/records.pyx.pxi | 5 + src/python/grpcio/grpc/_interceptor.py | 139 ++++--- src/python/grpcio/grpc/_server.py | 88 +++- .../grpc_testing/_server/_servicer_context.py | 6 + src/python/grpcio_tests/commands.py | 1 + .../grpcio_tests/tests/unit/BUILD.bazel | 6 + .../grpcio_tests/tests/unit/_api_test.py | 1 + .../tests/unit/_compression_test.py | 375 +++++++++++++++--- .../grpcio_tests/tests/unit/_tcp_proxy.py | 164 ++++++++ 16 files changed, 887 insertions(+), 189 deletions(-) create mode 100644 src/python/grpcio/grpc/_compression.py create mode 100644 src/python/grpcio_tests/tests/unit/_tcp_proxy.py diff --git a/.pylintrc b/.pylintrc index ba74decb047..fcc8e73cb41 100644 --- a/.pylintrc +++ b/.pylintrc @@ -6,6 +6,8 @@ ignore= src/python/grpcio/grpc/framework/foundation, src/python/grpcio/grpc/framework/interfaces, +extension-pkg-whitelist=grpc._cython.cygrpc + [VARIABLES] # TODO(https://github.com/PyCQA/pylint/issues/1345): How does the inspection @@ -17,7 +19,7 @@ dummy-variables-rgx=^ignored_|^unused_ # NOTE(nathaniel): Not particularly attached to this value; it just seems to # be what works for us at the moment (excepting the dead-code-walking Beta # API). -max-args=6 +max-args=7 [MISCELLANEOUS] diff --git a/doc/python/sphinx/grpc.rst b/doc/python/sphinx/grpc.rst index f534d25c639..0934db7188b 100644 --- a/doc/python/sphinx/grpc.rst +++ b/doc/python/sphinx/grpc.rst @@ -172,3 +172,9 @@ Future Interfaces .. autoexception:: FutureTimeoutError .. autoexception:: FutureCancelledError .. autoclass:: Future + + +Compression +^^^^^^^^^^^ + +.. autoclass:: Compression diff --git a/src/python/grpcio/grpc/BUILD.bazel b/src/python/grpcio/grpc/BUILD.bazel index 27d5d2e4bb2..a2bedae4bea 100644 --- a/src/python/grpcio/grpc/BUILD.bazel +++ b/src/python/grpcio/grpc/BUILD.bazel @@ -12,6 +12,7 @@ py_library( ":channel", ":interceptor", ":server", + ":compression", "//src/python/grpcio/grpc/_cython:cygrpc", "//src/python/grpcio/grpc/experimental", "//src/python/grpcio/grpc/framework", @@ -31,12 +32,18 @@ py_library( srcs = ["_auth.py"], ) +py_library( + name = "compression", + srcs = ["_compression.py"], +) + py_library( name = "channel", srcs = ["_channel.py"], deps = [ ":common", ":grpcio_metadata", + ":compression", ], ) @@ -68,6 +75,7 @@ py_library( srcs = ["_server.py"], deps = [ ":common", + ":compression", ":interceptor", ], ) diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py index 76314106ca4..6175180e92a 100644 --- a/src/python/grpcio/grpc/__init__.py +++ b/src/python/grpcio/grpc/__init__.py @@ -21,6 +21,7 @@ import sys import six from grpc._cython import cygrpc as _cygrpc +from grpc import _compression logging.getLogger(__name__).addHandler(logging.NullHandler()) @@ -413,6 +414,8 @@ class ClientCallDetails(six.with_metaclass(abc.ABCMeta)): credentials: An optional CallCredentials for the RPC. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag t enable wait for ready mechanism. + compression: An element of grpc.compression, e.g. + grpc.compression.Gzip. This is an EXPERIMENTAL option. """ @@ -669,7 +672,8 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): """Synchronously invokes the underlying RPC. Args: @@ -681,6 +685,8 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): credentials: An optional CallCredentials for the RPC. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag to enable wait for ready mechanism + compression: An element of grpc.compression, e.g. + grpc.compression.Gzip. This is an EXPERIMENTAL option. Returns: The response value for the RPC. @@ -698,7 +704,8 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): """Synchronously invokes the underlying RPC. Args: @@ -710,6 +717,8 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): credentials: An optional CallCredentials for the RPC. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag to enable wait for ready mechanism + compression: An element of grpc.compression, e.g. + grpc.compression.Gzip. This is an EXPERIMENTAL option. Returns: The response value for the RPC and a Call value for the RPC. @@ -727,7 +736,8 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): """Asynchronously invokes the underlying RPC. Args: @@ -739,6 +749,8 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): credentials: An optional CallCredentials for the RPC. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag to enable wait for ready mechanism + compression: An element of grpc.compression, e.g. + grpc.compression.Gzip. This is an EXPERIMENTAL option. Returns: An object that is both a Call for the RPC and a Future. @@ -759,7 +771,8 @@ class UnaryStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): """Invokes the underlying RPC. Args: @@ -771,6 +784,8 @@ class UnaryStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): credentials: An optional CallCredentials for the RPC. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag to enable wait for ready mechanism + compression: An element of grpc.compression, e.g. + grpc.compression.Gzip. This is an EXPERIMENTAL option. Returns: An object that is both a Call for the RPC and an iterator of @@ -790,7 +805,8 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): """Synchronously invokes the underlying RPC. Args: @@ -803,6 +819,8 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): credentials: An optional CallCredentials for the RPC. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag to enable wait for ready mechanism + compression: An element of grpc.compression, e.g. + grpc.compression.Gzip. This is an EXPERIMENTAL option. Returns: The response value for the RPC. @@ -820,7 +838,8 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): """Synchronously invokes the underlying RPC on the client. Args: @@ -833,6 +852,8 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): credentials: An optional CallCredentials for the RPC. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag to enable wait for ready mechanism + compression: An element of grpc.compression, e.g. + grpc.compression.Gzip. This is an EXPERIMENTAL option. Returns: The response value for the RPC and a Call object for the RPC. @@ -850,7 +871,8 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): """Asynchronously invokes the underlying RPC on the client. Args: @@ -862,6 +884,8 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): credentials: An optional CallCredentials for the RPC. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag to enable wait for ready mechanism + compression: An element of grpc.compression, e.g. + grpc.compression.Gzip. This is an EXPERIMENTAL option. Returns: An object that is both a Call for the RPC and a Future. @@ -882,7 +906,8 @@ class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): """Invokes the underlying RPC on the client. Args: @@ -894,6 +919,8 @@ class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): credentials: An optional CallCredentials for the RPC. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag to enable wait for ready mechanism + compression: An element of grpc.compression, e.g. + grpc.compression.Gzip. This is an EXPERIMENTAL option. Returns: An object that is both a Call for the RPC and an iterator of @@ -1097,6 +1124,17 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): """ raise NotImplementedError() + def set_compression(self, compression): + """Set the compression algorithm to be used for the entire call. + + This is an EXPERIMENTAL method. + + Args: + compression: An element of grpc.compression, e.g. + grpc.compression.Gzip. + """ + raise NotImplementedError() + @abc.abstractmethod def send_initial_metadata(self, initial_metadata): """Sends the initial metadata value to the client. @@ -1184,6 +1222,16 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): """ raise NotImplementedError() + def disable_next_message_compression(self): + """Disables compression for the next response message. + + This is an EXPERIMENTAL method. + + This method will override any compression configuration set during + server creation or set on the call. + """ + raise NotImplementedError() + ##################### Service-Side Handler Interfaces ######################## @@ -1682,7 +1730,7 @@ def channel_ready_future(channel): return _utilities.channel_ready_future(channel) -def insecure_channel(target, options=None): +def insecure_channel(target, options=None, compression=None): """Creates an insecure Channel to a server. The returned Channel is thread-safe. @@ -1691,15 +1739,18 @@ def insecure_channel(target, options=None): target: The server address options: An optional list of key-value pairs (channel args in gRPC Core runtime) to configure the channel. + compression: An optional value indicating the compression method to be + used over the lifetime of the channel. This is an EXPERIMENTAL option. Returns: A Channel. """ from grpc import _channel # pylint: disable=cyclic-import - return _channel.Channel(target, () if options is None else options, None) + return _channel.Channel(target, () + if options is None else options, None, compression) -def secure_channel(target, credentials, options=None): +def secure_channel(target, credentials, options=None, compression=None): """Creates a secure Channel to a server. The returned Channel is thread-safe. @@ -1709,13 +1760,15 @@ def secure_channel(target, credentials, options=None): credentials: A ChannelCredentials instance. options: An optional list of key-value pairs (channel args in gRPC Core runtime) to configure the channel. + compression: An optional value indicating the compression method to be + used over the lifetime of the channel. This is an EXPERIMENTAL option. Returns: A Channel. """ from grpc import _channel # pylint: disable=cyclic-import return _channel.Channel(target, () if options is None else options, - credentials._credentials) + credentials._credentials, compression) def intercept_channel(channel, *interceptors): @@ -1750,7 +1803,8 @@ def server(thread_pool, handlers=None, interceptors=None, options=None, - maximum_concurrent_rpcs=None): + maximum_concurrent_rpcs=None, + compression=None): """Creates a Server with which RPCs can be serviced. Args: @@ -1768,6 +1822,9 @@ def server(thread_pool, maximum_concurrent_rpcs: The maximum number of concurrent RPCs this server will service before returning RESOURCE_EXHAUSTED status, or None to indicate no limit. + compression: An element of grpc.compression, e.g. + grpc.compression.Gzip. This compression algorithm will be used for the + lifetime of the server unless overridden. This is an EXPERIMENTAL option. Returns: A Server object. @@ -1777,7 +1834,7 @@ def server(thread_pool, if handlers is None else handlers, () if interceptors is None else interceptors, () if options is None else options, - maximum_concurrent_rpcs) + maximum_concurrent_rpcs, compression) @contextlib.contextmanager @@ -1788,6 +1845,16 @@ def _create_servicer_context(rpc_event, state, request_deserializer): context._finalize_state() # pylint: disable=protected-access +class Compression(enum.IntEnum): + """Indicates the compression method to be used for an RPC. + + This enumeration is part of an EXPERIMENTAL API. + """ + NoCompression = _compression.NoCompression + Deflate = _compression.Deflate + Gzip = _compression.Gzip + + ################################### __all__ ################################# __all__ = ( @@ -1805,6 +1872,7 @@ __all__ = ( 'AuthMetadataContext', 'AuthMetadataPluginCallback', 'AuthMetadataPlugin', + 'Compression', 'ClientCallDetails', 'ServerCertificateConfiguration', 'ServerCredentials', diff --git a/src/python/grpcio/grpc/_channel.py b/src/python/grpcio/grpc/_channel.py index ed4c871b684..1272ee802bc 100644 --- a/src/python/grpcio/grpc/_channel.py +++ b/src/python/grpcio/grpc/_channel.py @@ -19,6 +19,7 @@ import threading import time import grpc +from grpc import _compression from grpc import _common from grpc import _grpcio_metadata from grpc._cython import cygrpc @@ -512,17 +513,19 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): self._response_deserializer = response_deserializer self._context = cygrpc.build_census_context() - def _prepare(self, request, timeout, metadata, wait_for_ready): + def _prepare(self, request, timeout, metadata, wait_for_ready, compression): deadline, serialized_request, rendezvous = _start_unary_request( request, timeout, self._request_serializer) initial_metadata_flags = _InitialMetadataFlags().with_wait_for_ready( wait_for_ready) + augmented_metadata = _compression.augment_metadata( + metadata, compression) if serialized_request is None: return None, None, None, rendezvous else: state = _RPCState(_UNARY_UNARY_INITIAL_DUE, None, None, None, None) operations = ( - cygrpc.SendInitialMetadataOperation(metadata, + cygrpc.SendInitialMetadataOperation(augmented_metadata, initial_metadata_flags), cygrpc.SendMessageOperation(serialized_request, _EMPTY_FLAGS), cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS), @@ -532,18 +535,17 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): ) return state, operations, deadline, None - def _blocking(self, request, timeout, metadata, credentials, - wait_for_ready): + def _blocking(self, request, timeout, metadata, credentials, wait_for_ready, + compression): state, operations, deadline, rendezvous = self._prepare( - request, timeout, metadata, wait_for_ready) + request, timeout, metadata, wait_for_ready, compression) if state is None: raise rendezvous # pylint: disable-msg=raising-bad-type else: - deadline_to_propagate = _determine_deadline(deadline) call = self._channel.segregated_call( cygrpc.PropagationConstants.GRPC_PROPAGATE_DEFAULTS, - self._method, None, deadline_to_propagate, metadata, None - if credentials is None else credentials._credentials, (( + self._method, None, _determine_deadline(deadline), metadata, + None if credentials is None else credentials._credentials, (( operations, None, ),), self._context) @@ -556,9 +558,10 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): state, call, = self._blocking(request, timeout, metadata, credentials, - wait_for_ready) + wait_for_ready, compression) return _end_unary_response_blocking(state, call, False, None) def with_call(self, @@ -566,9 +569,10 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): state, call, = self._blocking(request, timeout, metadata, credentials, - wait_for_ready) + wait_for_ready, compression) return _end_unary_response_blocking(state, call, True, None) def future(self, @@ -576,9 +580,10 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): state, operations, deadline, rendezvous = self._prepare( - request, timeout, metadata, wait_for_ready) + request, timeout, metadata, wait_for_ready, compression) if state is None: raise rendezvous # pylint: disable-msg=raising-bad-type else: @@ -604,12 +609,14 @@ class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable): self._response_deserializer = response_deserializer self._context = cygrpc.build_census_context() - def __call__(self, - request, - timeout=None, - metadata=None, - credentials=None, - wait_for_ready=None): + def __call__( # pylint: disable=too-many-locals + self, + request, + timeout=None, + metadata=None, + credentials=None, + wait_for_ready=None, + compression=None): deadline, serialized_request, rendezvous = _start_unary_request( request, timeout, self._request_serializer) initial_metadata_flags = _InitialMetadataFlags().with_wait_for_ready( @@ -617,10 +624,12 @@ class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable): if serialized_request is None: raise rendezvous # pylint: disable-msg=raising-bad-type else: + augmented_metadata = _compression.augment_metadata( + metadata, compression) state = _RPCState(_UNARY_STREAM_INITIAL_DUE, None, None, None, None) operationses = ( ( - cygrpc.SendInitialMetadataOperation(metadata, + cygrpc.SendInitialMetadataOperation(augmented_metadata, initial_metadata_flags), cygrpc.SendMessageOperation(serialized_request, _EMPTY_FLAGS), @@ -629,12 +638,13 @@ class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable): ), (cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),), ) - event_handler = _event_handler(state, self._response_deserializer) call = self._managed_call( cygrpc.PropagationConstants.GRPC_PROPAGATE_DEFAULTS, self._method, None, _determine_deadline(deadline), metadata, - None if credentials is None else credentials._credentials, - operationses, event_handler, self._context) + None if credentials is None else + credentials._credentials, operationses, + _event_handler(state, + self._response_deserializer), self._context) return _Rendezvous(state, call, self._response_deserializer, deadline) @@ -652,18 +662,19 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): self._context = cygrpc.build_census_context() def _blocking(self, request_iterator, timeout, metadata, credentials, - wait_for_ready): + wait_for_ready, compression): deadline = _deadline(timeout) state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None) initial_metadata_flags = _InitialMetadataFlags().with_wait_for_ready( wait_for_ready) - deadline_to_propagate = _determine_deadline(deadline) + augmented_metadata = _compression.augment_metadata( + metadata, compression) call = self._channel.segregated_call( cygrpc.PropagationConstants.GRPC_PROPAGATE_DEFAULTS, self._method, - None, deadline_to_propagate, metadata, None + None, _determine_deadline(deadline), augmented_metadata, None if credentials is None else credentials._credentials, _stream_unary_invocation_operationses_and_tags( - metadata, initial_metadata_flags), self._context) + augmented_metadata, initial_metadata_flags), self._context) _consume_request_iterator(request_iterator, state, call, self._request_serializer, None) while True: @@ -680,9 +691,10 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): state, call, = self._blocking(request_iterator, timeout, metadata, - credentials, wait_for_ready) + credentials, wait_for_ready, compression) return _end_unary_response_blocking(state, call, False, None) def with_call(self, @@ -690,9 +702,10 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): state, call, = self._blocking(request_iterator, timeout, metadata, - credentials, wait_for_ready) + credentials, wait_for_ready, compression) return _end_unary_response_blocking(state, call, True, None) def future(self, @@ -700,15 +713,18 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): deadline = _deadline(timeout) state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None) event_handler = _event_handler(state, self._response_deserializer) initial_metadata_flags = _InitialMetadataFlags().with_wait_for_ready( wait_for_ready) + augmented_metadata = _compression.augment_metadata( + metadata, compression) call = self._managed_call( cygrpc.PropagationConstants.GRPC_PROPAGATE_DEFAULTS, self._method, - None, deadline, metadata, None + None, deadline, augmented_metadata, None if credentials is None else credentials._credentials, _stream_unary_invocation_operationses( metadata, initial_metadata_flags), event_handler, self._context) @@ -734,24 +750,26 @@ class _StreamStreamMultiCallable(grpc.StreamStreamMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): deadline = _deadline(timeout) state = _RPCState(_STREAM_STREAM_INITIAL_DUE, None, None, None, None) initial_metadata_flags = _InitialMetadataFlags().with_wait_for_ready( wait_for_ready) + augmented_metadata = _compression.augment_metadata( + metadata, compression) operationses = ( ( - cygrpc.SendInitialMetadataOperation(metadata, + cygrpc.SendInitialMetadataOperation(augmented_metadata, initial_metadata_flags), cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS), ), (cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),), ) event_handler = _event_handler(state, self._response_deserializer) - deadline_to_propagate = _determine_deadline(deadline) call = self._managed_call( cygrpc.PropagationConstants.GRPC_PROPAGATE_DEFAULTS, self._method, - None, deadline_to_propagate, metadata, None + None, _determine_deadline(deadline), augmented_metadata, None if credentials is None else credentials._credentials, operationses, event_handler, self._context) _consume_request_iterator(request_iterator, state, call, @@ -982,28 +1000,30 @@ def _unsubscribe(state, callback): break -def _options(options): - return list(options) + [ - ( - cygrpc.ChannelArgKey.primary_user_agent_string, - _USER_AGENT, - ), - ] +def _augment_options(base_options, compression): + compression_option = _compression.create_channel_option(compression) + return tuple(base_options) + compression_option + (( + cygrpc.ChannelArgKey.primary_user_agent_string, + _USER_AGENT, + ),) class Channel(grpc.Channel): """A cygrpc.Channel-backed implementation of grpc.Channel.""" - def __init__(self, target, options, credentials): + def __init__(self, target, options, credentials, compression): """Constructor. Args: target: The target to which to connect. options: Configuration options for the channel. credentials: A cygrpc.ChannelCredentials or None. + compression: An optional value indicating the compression method to be + used over the lifetime of the channel. """ self._channel = cygrpc.Channel( - _common.encode(target), _options(options), credentials) + _common.encode(target), _augment_options(options, compression), + credentials) self._call_state = _ChannelCallState(self._channel) self._connectivity_state = _ChannelConnectivityState(self._channel) cygrpc.fork_register_channel(self) diff --git a/src/python/grpcio/grpc/_compression.py b/src/python/grpcio/grpc/_compression.py new file mode 100644 index 00000000000..45339c3afe2 --- /dev/null +++ b/src/python/grpcio/grpc/_compression.py @@ -0,0 +1,55 @@ +# Copyright 2019 The gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from grpc._cython import cygrpc + +NoCompression = cygrpc.CompressionAlgorithm.none +Deflate = cygrpc.CompressionAlgorithm.deflate +Gzip = cygrpc.CompressionAlgorithm.gzip + +_METADATA_STRING_MAPPING = { + NoCompression: 'identity', + Deflate: 'deflate', + Gzip: 'gzip', +} + + +def _compression_algorithm_to_metadata_value(compression): + return _METADATA_STRING_MAPPING[compression] + + +def compression_algorithm_to_metadata(compression): + return (cygrpc.GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY, + _compression_algorithm_to_metadata_value(compression)) + + +def create_channel_option(compression): + return ((cygrpc.GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, + int(compression)),) if compression else () + + +def augment_metadata(metadata, compression): + if not metadata and not compression: + return None + base_metadata = tuple(metadata) if metadata else () + compression_metadata = ( + compression_algorithm_to_metadata(compression),) if compression else () + return base_metadata + compression_metadata + + +__all__ = ( + "NoCompression", + "Deflate", + "Gzip", +) diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi index 0a35002a9d4..057d0776983 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi @@ -140,7 +140,8 @@ cdef extern from "grpc/grpc.h": const char *GRPC_ARG_SECONDARY_USER_AGENT_STRING const char *GRPC_SSL_TARGET_NAME_OVERRIDE_ARG const char *GRPC_SSL_SESSION_CACHE_ARG - const char *GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM + const char *_GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM \ + "GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM" const char *GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL const char *GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET @@ -618,3 +619,8 @@ cdef extern from "grpc/compression.h": int grpc_compression_options_is_algorithm_enabled( const grpc_compression_options *opts, grpc_compression_algorithm algorithm) nogil + +cdef extern from "grpc/impl/codegen/compression_types.h": + + const char *_GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY \ + "GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY" diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi index 02c904b43fc..308d677695f 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi @@ -108,6 +108,11 @@ class OperationType: receive_status_on_client = GRPC_OP_RECV_STATUS_ON_CLIENT receive_close_on_server = GRPC_OP_RECV_CLOSE_ON_SERVER +GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM= ( + _GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM) + +GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY = ( + _GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY) class CompressionAlgorithm: none = GRPC_COMPRESS_NONE diff --git a/src/python/grpcio/grpc/_interceptor.py b/src/python/grpcio/grpc/_interceptor.py index 6c4e396ac23..4ec2e6bb733 100644 --- a/src/python/grpcio/grpc/_interceptor.py +++ b/src/python/grpcio/grpc/_interceptor.py @@ -44,9 +44,9 @@ def service_pipeline(interceptors): class _ClientCallDetails( - collections.namedtuple( - '_ClientCallDetails', - ('method', 'timeout', 'metadata', 'credentials', 'wait_for_ready')), + collections.namedtuple('_ClientCallDetails', + ('method', 'timeout', 'metadata', 'credentials', + 'wait_for_ready', 'compression')), grpc.ClientCallDetails): pass @@ -77,7 +77,12 @@ def _unwrap_client_call_details(call_details, default_details): except AttributeError: wait_for_ready = default_details.wait_for_ready - return method, timeout, metadata, credentials, wait_for_ready + try: + compression = call_details.compression + except AttributeError: + compression = default_details.compression + + return method, timeout, metadata, credentials, wait_for_ready, compression class _FailureOutcome(grpc.RpcError, grpc.Future, grpc.Call): # pylint: disable=too-many-ancestors @@ -206,13 +211,15 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): response, ignored_call = self._with_call( request, timeout=timeout, metadata=metadata, credentials=credentials, - wait_for_ready=wait_for_ready) + wait_for_ready=wait_for_ready, + compression=compression) return response def _with_call(self, @@ -220,20 +227,25 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): - client_call_details = _ClientCallDetails( - self._method, timeout, metadata, credentials, wait_for_ready) + wait_for_ready=None, + compression=None): + client_call_details = _ClientCallDetails(self._method, timeout, + metadata, credentials, + wait_for_ready, compression) def continuation(new_details, request): - new_method, new_timeout, new_metadata, new_credentials, new_wait_for_ready = ( - _unwrap_client_call_details(new_details, client_call_details)) + (new_method, new_timeout, new_metadata, new_credentials, + new_wait_for_ready, + new_compression) = (_unwrap_client_call_details( + new_details, client_call_details)) try: response, call = self._thunk(new_method).with_call( request, timeout=new_timeout, metadata=new_metadata, credentials=new_credentials, - wait_for_ready=new_wait_for_ready) + wait_for_ready=new_wait_for_ready, + compression=new_compression) return _UnaryOutcome(response, call) except grpc.RpcError as rpc_error: return rpc_error @@ -249,32 +261,39 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): return self._with_call( request, timeout=timeout, metadata=metadata, credentials=credentials, - wait_for_ready=wait_for_ready) + wait_for_ready=wait_for_ready, + compression=compression) def future(self, request, timeout=None, metadata=None, credentials=None, - wait_for_ready=None): - client_call_details = _ClientCallDetails( - self._method, timeout, metadata, credentials, wait_for_ready) + wait_for_ready=None, + compression=None): + client_call_details = _ClientCallDetails(self._method, timeout, + metadata, credentials, + wait_for_ready, compression) def continuation(new_details, request): - new_method, new_timeout, new_metadata, new_credentials, new_wait_for_ready = ( - _unwrap_client_call_details(new_details, client_call_details)) + (new_method, new_timeout, new_metadata, new_credentials, + new_wait_for_ready, + new_compression) = (_unwrap_client_call_details( + new_details, client_call_details)) return self._thunk(new_method).future( request, timeout=new_timeout, metadata=new_metadata, credentials=new_credentials, - wait_for_ready=new_wait_for_ready) + wait_for_ready=new_wait_for_ready, + compression=new_compression) try: return self._interceptor.intercept_unary_unary( @@ -295,19 +314,24 @@ class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): - client_call_details = _ClientCallDetails( - self._method, timeout, metadata, credentials, wait_for_ready) + wait_for_ready=None, + compression=None): + client_call_details = _ClientCallDetails(self._method, timeout, + metadata, credentials, + wait_for_ready, compression) def continuation(new_details, request): - new_method, new_timeout, new_metadata, new_credentials, new_wait_for_ready = ( - _unwrap_client_call_details(new_details, client_call_details)) + (new_method, new_timeout, new_metadata, new_credentials, + new_wait_for_ready, + new_compression) = (_unwrap_client_call_details( + new_details, client_call_details)) return self._thunk(new_method)( request, timeout=new_timeout, metadata=new_metadata, credentials=new_credentials, - wait_for_ready=new_wait_for_ready) + wait_for_ready=new_wait_for_ready, + compression=new_compression) try: return self._interceptor.intercept_unary_stream( @@ -328,13 +352,15 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): response, ignored_call = self._with_call( request_iterator, timeout=timeout, metadata=metadata, credentials=credentials, - wait_for_ready=wait_for_ready) + wait_for_ready=wait_for_ready, + compression=compression) return response def _with_call(self, @@ -342,20 +368,25 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): - client_call_details = _ClientCallDetails( - self._method, timeout, metadata, credentials, wait_for_ready) + wait_for_ready=None, + compression=None): + client_call_details = _ClientCallDetails(self._method, timeout, + metadata, credentials, + wait_for_ready, compression) def continuation(new_details, request_iterator): - new_method, new_timeout, new_metadata, new_credentials, new_wait_for_ready = ( - _unwrap_client_call_details(new_details, client_call_details)) + (new_method, new_timeout, new_metadata, new_credentials, + new_wait_for_ready, + new_compression) = (_unwrap_client_call_details( + new_details, client_call_details)) try: response, call = self._thunk(new_method).with_call( request_iterator, timeout=new_timeout, metadata=new_metadata, credentials=new_credentials, - wait_for_ready=new_wait_for_ready) + wait_for_ready=new_wait_for_ready, + compression=new_compression) return _UnaryOutcome(response, call) except grpc.RpcError as rpc_error: return rpc_error @@ -371,32 +402,39 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): + wait_for_ready=None, + compression=None): return self._with_call( request_iterator, timeout=timeout, metadata=metadata, credentials=credentials, - wait_for_ready=wait_for_ready) + wait_for_ready=wait_for_ready, + compression=compression) def future(self, request_iterator, timeout=None, metadata=None, credentials=None, - wait_for_ready=None): - client_call_details = _ClientCallDetails( - self._method, timeout, metadata, credentials, wait_for_ready) + wait_for_ready=None, + compression=None): + client_call_details = _ClientCallDetails(self._method, timeout, + metadata, credentials, + wait_for_ready, compression) def continuation(new_details, request_iterator): - new_method, new_timeout, new_metadata, new_credentials, new_wait_for_ready = ( - _unwrap_client_call_details(new_details, client_call_details)) + (new_method, new_timeout, new_metadata, new_credentials, + new_wait_for_ready, + new_compression) = (_unwrap_client_call_details( + new_details, client_call_details)) return self._thunk(new_method).future( request_iterator, timeout=new_timeout, metadata=new_metadata, credentials=new_credentials, - wait_for_ready=new_wait_for_ready) + wait_for_ready=new_wait_for_ready, + compression=new_compression) try: return self._interceptor.intercept_stream_unary( @@ -417,19 +455,24 @@ class _StreamStreamMultiCallable(grpc.StreamStreamMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None): - client_call_details = _ClientCallDetails( - self._method, timeout, metadata, credentials, wait_for_ready) + wait_for_ready=None, + compression=None): + client_call_details = _ClientCallDetails(self._method, timeout, + metadata, credentials, + wait_for_ready, compression) def continuation(new_details, request_iterator): - new_method, new_timeout, new_metadata, new_credentials, new_wait_for_ready = ( - _unwrap_client_call_details(new_details, client_call_details)) + (new_method, new_timeout, new_metadata, new_credentials, + new_wait_for_ready, + new_compression) = (_unwrap_client_call_details( + new_details, client_call_details)) return self._thunk(new_method)( request_iterator, timeout=new_timeout, metadata=new_metadata, credentials=new_credentials, - wait_for_ready=new_wait_for_ready) + wait_for_ready=new_wait_for_ready, + compression=new_compression) try: return self._interceptor.intercept_stream_stream( diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py index 90136aef3c2..370c81100af 100644 --- a/src/python/grpcio/grpc/_server.py +++ b/src/python/grpcio/grpc/_server.py @@ -24,6 +24,7 @@ import six import grpc from grpc import _common +from grpc import _compression from grpc import _interceptor from grpc._cython import cygrpc @@ -94,6 +95,7 @@ class _RPCState(object): self.request = None self.client = _OPEN self.initial_metadata_allowed = True + self.compression_algorithm = None self.disable_next_compression = False self.trailing_metadata = None self.code = None @@ -129,13 +131,33 @@ def _send_status_from_server(state, token): return send_status_from_server +def _get_initial_metadata(state, metadata): + with state.condition: + if state.compression_algorithm: + compression_metadata = ( + _compression.compression_algorithm_to_metadata( + state.compression_algorithm),) + if metadata is None: + return compression_metadata + else: + return compression_metadata + tuple(metadata) + else: + return metadata + + +def _get_initial_metadata_operation(state, metadata): + operation = cygrpc.SendInitialMetadataOperation( + _get_initial_metadata(state, metadata), _EMPTY_FLAGS) + return operation + + def _abort(state, call, code, details): if state.client is not _CANCELLED: effective_code = _abortion_code(state, code) effective_details = details if state.details is None else state.details if state.initial_metadata_allowed: operations = ( - cygrpc.SendInitialMetadataOperation(None, _EMPTY_FLAGS), + _get_initial_metadata_operation(state, None), cygrpc.SendStatusFromServerOperation( state.trailing_metadata, effective_code, effective_details, _EMPTY_FLAGS), @@ -259,14 +281,18 @@ class _Context(grpc.ServicerContext): cygrpc.auth_context(self._rpc_event.call)) } + def set_compression(self, compression): + with self._state.condition: + self._state.compression_algorithm = compression + def send_initial_metadata(self, initial_metadata): with self._state.condition: if self._state.client is _CANCELLED: _raise_rpc_error(self._state) else: if self._state.initial_metadata_allowed: - operation = cygrpc.SendInitialMetadataOperation( - initial_metadata, _EMPTY_FLAGS) + operation = _get_initial_metadata_operation( + self._state, initial_metadata) self._rpc_event.call.start_server_batch( (operation,), _send_initial_metadata(self._state)) self._state.initial_metadata_allowed = False @@ -400,10 +426,13 @@ def _call_behavior(rpc_event, with _create_servicer_context(rpc_event, state, request_deserializer) as context: try: + response_or_iterator = None if send_response_callback is not None: - return behavior(argument, context, send_response_callback), True + response_or_iterator = behavior(argument, context, + send_response_callback) else: - return behavior(argument, context), True + response_or_iterator = behavior(argument, context) + return response_or_iterator, True except Exception as exception: # pylint: disable=broad-except with state.condition: if state.aborted: @@ -447,6 +476,18 @@ def _serialize_response(rpc_event, state, response, response_serializer): return serialized_response +def _get_send_message_op_flags_from_state(state): + if state.disable_next_compression: + return cygrpc.WriteFlag.no_compress + else: + return _EMPTY_FLAGS + + +def _reset_per_message_state(state): + with state.condition: + state.disable_next_compression = False + + def _send_response(rpc_event, state, serialized_response): with state.condition: if not _is_rpc_state_active(state): @@ -454,19 +495,22 @@ def _send_response(rpc_event, state, serialized_response): else: if state.initial_metadata_allowed: operations = ( - cygrpc.SendInitialMetadataOperation(None, _EMPTY_FLAGS), - cygrpc.SendMessageOperation(serialized_response, - _EMPTY_FLAGS), + _get_initial_metadata_operation(state, None), + cygrpc.SendMessageOperation( + serialized_response, + _get_send_message_op_flags_from_state(state)), ) state.initial_metadata_allowed = False token = _SEND_INITIAL_METADATA_AND_SEND_MESSAGE_TOKEN else: operations = (cygrpc.SendMessageOperation( - serialized_response, _EMPTY_FLAGS),) + serialized_response, + _get_send_message_op_flags_from_state(state)),) token = _SEND_MESSAGE_TOKEN rpc_event.call.start_server_batch(operations, _send_message(state, token)) state.due.add(token) + _reset_per_message_state(state) while True: state.condition.wait() if token not in state.due: @@ -483,16 +527,17 @@ def _status(rpc_event, state, serialized_response): state.trailing_metadata, code, details, _EMPTY_FLAGS), ] if state.initial_metadata_allowed: - operations.append( - cygrpc.SendInitialMetadataOperation(None, _EMPTY_FLAGS)) + operations.append(_get_initial_metadata_operation(state, None)) if serialized_response is not None: operations.append( - cygrpc.SendMessageOperation(serialized_response, - _EMPTY_FLAGS)) + cygrpc.SendMessageOperation( + serialized_response, + _get_send_message_op_flags_from_state(state))) rpc_event.call.start_server_batch( operations, _send_status_from_server(state, _SEND_STATUS_FROM_SERVER_TOKEN)) state.statused = True + _reset_per_message_state(state) state.due.add(_SEND_STATUS_FROM_SERVER_TOKEN) @@ -639,13 +684,13 @@ def _find_method_handler(rpc_event, generic_handlers, interceptor_pipeline): def _reject_rpc(rpc_event, status, details): + rpc_state = _RPCState() operations = ( - cygrpc.SendInitialMetadataOperation(None, _EMPTY_FLAGS), + _get_initial_metadata_operation(rpc_state, None), cygrpc.ReceiveCloseOnServerOperation(_EMPTY_FLAGS), cygrpc.SendStatusFromServerOperation(None, status, details, _EMPTY_FLAGS), ) - rpc_state = _RPCState() rpc_event.call.start_server_batch(operations, lambda ignored_event: (rpc_state, (),)) return rpc_state @@ -883,13 +928,18 @@ def _validate_generic_rpc_handlers(generic_rpc_handlers): 'not have "service" method!'.format(generic_rpc_handler)) +def _augment_options(base_options, compression): + compression_option = _compression.create_channel_option(compression) + return tuple(base_options) + compression_option + + class _Server(grpc.Server): # pylint: disable=too-many-arguments def __init__(self, thread_pool, generic_handlers, interceptors, options, - maximum_concurrent_rpcs): + maximum_concurrent_rpcs, compression): completion_queue = cygrpc.CompletionQueue() - server = cygrpc.Server(options) + server = cygrpc.Server(_augment_options(options, compression)) server.register_completion_queue(completion_queue) self._state = _ServerState(completion_queue, server, generic_handlers, _interceptor.service_pipeline(interceptors), @@ -920,7 +970,7 @@ class _Server(grpc.Server): def create_server(thread_pool, generic_rpc_handlers, interceptors, options, - maximum_concurrent_rpcs): + maximum_concurrent_rpcs, compression): _validate_generic_rpc_handlers(generic_rpc_handlers) return _Server(thread_pool, generic_rpc_handlers, interceptors, options, - maximum_concurrent_rpcs) + maximum_concurrent_rpcs, compression) diff --git a/src/python/grpcio_testing/grpc_testing/_server/_servicer_context.py b/src/python/grpcio_testing/grpc_testing/_server/_servicer_context.py index 5b1dfeacdf5..63a1b1aec95 100644 --- a/src/python/grpcio_testing/grpc_testing/_server/_servicer_context.py +++ b/src/python/grpcio_testing/grpc_testing/_server/_servicer_context.py @@ -56,6 +56,9 @@ class ServicerContext(grpc.ServicerContext): def auth_context(self): raise NotImplementedError() + def set_compression(self): + raise NotImplementedError() + def send_initial_metadata(self, initial_metadata): initial_metadata_sent = self._rpc.send_initial_metadata( _common.fuss_with_metadata(initial_metadata)) @@ -63,6 +66,9 @@ class ServicerContext(grpc.ServicerContext): raise ValueError( 'ServicerContext.send_initial_metadata called too late!') + def disable_next_message_compression(self): + raise NotImplementedError() + def set_trailing_metadata(self, trailing_metadata): self._rpc.set_trailing_metadata( _common.fuss_with_metadata(trailing_metadata)) diff --git a/src/python/grpcio_tests/commands.py b/src/python/grpcio_tests/commands.py index 7a441feb84e..e9b6333c891 100644 --- a/src/python/grpcio_tests/commands.py +++ b/src/python/grpcio_tests/commands.py @@ -117,6 +117,7 @@ class TestGevent(setuptools.Command): # eventually succeed, but need to dig into performance issues. 'unit._cython._no_messages_server_completion_queue_per_call_test.Test.test_rpcs', 'unit._cython._no_messages_single_server_completion_queue_test.Test.test_rpcs', + 'unit._compression_test', # TODO(https://github.com/grpc/grpc/issues/16890) enable this test 'unit._cython._channel_test.ChannelTest.test_multiple_channels_lonely_connectivity', # I have no idea why this doesn't work in gevent, but it shouldn't even be diff --git a/src/python/grpcio_tests/tests/unit/BUILD.bazel b/src/python/grpcio_tests/tests/unit/BUILD.bazel index 54b3c9b6f6a..04f91e63a18 100644 --- a/src/python/grpcio_tests/tests/unit/BUILD.bazel +++ b/src/python/grpcio_tests/tests/unit/BUILD.bazel @@ -33,6 +33,11 @@ GRPCIO_TESTS_UNIT = [ "_session_cache_test.py", ] +py_library( + name = "_tcp_proxy", + srcs = ["_tcp_proxy.py"], +) + py_library( name = "resources", srcs = ["resources.py"], @@ -80,6 +85,7 @@ py_library( ":_exit_scenarios", ":_server_shutdown_scenarios", ":_from_grpc_import_star", + ":_tcp_proxy", "//src/python/grpcio_tests/tests/unit/framework/common", "//src/python/grpcio_tests/tests/testing", requirement('six'), diff --git a/src/python/grpcio_tests/tests/unit/_api_test.py b/src/python/grpcio_tests/tests/unit/_api_test.py index 0dc6a8718c3..127dab336bf 100644 --- a/src/python/grpcio_tests/tests/unit/_api_test.py +++ b/src/python/grpcio_tests/tests/unit/_api_test.py @@ -31,6 +31,7 @@ class AllTest(unittest.TestCase): 'FutureCancelledError', 'Future', 'ChannelConnectivity', + 'Compression', 'StatusCode', 'Status', 'RpcError', diff --git a/src/python/grpcio_tests/tests/unit/_compression_test.py b/src/python/grpcio_tests/tests/unit/_compression_test.py index 87884a19dc0..66f9f0ae40f 100644 --- a/src/python/grpcio_tests/tests/unit/_compression_test.py +++ b/src/python/grpcio_tests/tests/unit/_compression_test.py @@ -13,37 +13,130 @@ # limitations under the License. """Tests server and client side compression.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + import unittest +import contextlib +from concurrent import futures +import functools +import itertools import logging +import os + import grpc from grpc import _grpcio_metadata from tests.unit import test_common from tests.unit.framework.common import test_constants +from tests.unit import _tcp_proxy _UNARY_UNARY = '/test/UnaryUnary' +_UNARY_STREAM = '/test/UnaryStream' +_STREAM_UNARY = '/test/StreamUnary' _STREAM_STREAM = '/test/StreamStream' +# Cut down on test time. +_STREAM_LENGTH = test_constants.STREAM_LENGTH // 8 -def handle_unary(request, servicer_context): - servicer_context.send_initial_metadata([('grpc-internal-encoding-request', - 'gzip')]) - return request +_HOST = 'localhost' + +_REQUEST = b'\x00' * 100 +_COMPRESSION_RATIO_THRESHOLD = 0.1 +_COMPRESSION_METHODS = ( + None, + # Disabled for test tractability. + # grpc.Compression.NoCompression, + grpc.Compression.Deflate, + grpc.Compression.Gzip, +) +_COMPRESSION_NAMES = { + None: 'Uncompressed', + grpc.Compression.NoCompression: 'NoCompression', + grpc.Compression.Deflate: 'DeflateCompression', + grpc.Compression.Gzip: 'GzipCompression', +} + +_TEST_OPTIONS = { + 'client_streaming': (True, False), + 'server_streaming': (True, False), + 'channel_compression': _COMPRESSION_METHODS, + 'multicallable_compression': _COMPRESSION_METHODS, + 'server_compression': _COMPRESSION_METHODS, + 'server_call_compression': _COMPRESSION_METHODS, +} -def handle_stream(request_iterator, servicer_context): - # TODO(issue:#6891) We should be able to remove this loop, - # and replace with return; yield - servicer_context.send_initial_metadata([('grpc-internal-encoding-request', - 'gzip')]) - for request in request_iterator: - yield request +def _make_handle_unary_unary(pre_response_callback): + + def _handle_unary(request, servicer_context): + if pre_response_callback: + pre_response_callback(request, servicer_context) + return request + + return _handle_unary + + +def _make_handle_unary_stream(pre_response_callback): + + def _handle_unary_stream(request, servicer_context): + if pre_response_callback: + pre_response_callback(request, servicer_context) + for _ in range(_STREAM_LENGTH): + yield request + + return _handle_unary_stream + + +def _make_handle_stream_unary(pre_response_callback): + + def _handle_stream_unary(request_iterator, servicer_context): + if pre_response_callback: + pre_response_callback(request_iterator, servicer_context) + response = None + for request in request_iterator: + if not response: + response = request + return response + + return _handle_stream_unary + + +def _make_handle_stream_stream(pre_response_callback): + + def _handle_stream(request_iterator, servicer_context): + # TODO(issue:#6891) We should be able to remove this loop, + # and replace with return; yield + for request in request_iterator: + if pre_response_callback: + pre_response_callback(request, servicer_context) + yield request + + return _handle_stream + + +def set_call_compression(compression_method, request_or_iterator, + servicer_context): + del request_or_iterator + servicer_context.set_compression(compression_method) + + +def disable_next_compression(request, servicer_context): + del request + servicer_context.disable_next_message_compression() + + +def disable_first_compression(request, servicer_context): + if int(request.decode('ascii')) == 0: + servicer_context.disable_next_message_compression() class _MethodHandler(grpc.RpcMethodHandler): - def __init__(self, request_streaming, response_streaming): + def __init__(self, request_streaming, response_streaming, + pre_response_callback): self.request_streaming = request_streaming self.response_streaming = response_streaming self.request_deserializer = None @@ -52,75 +145,239 @@ class _MethodHandler(grpc.RpcMethodHandler): self.unary_stream = None self.stream_unary = None self.stream_stream = None + if self.request_streaming and self.response_streaming: - self.stream_stream = handle_stream + self.stream_stream = _make_handle_stream_stream( + pre_response_callback) elif not self.request_streaming and not self.response_streaming: - self.unary_unary = handle_unary + self.unary_unary = _make_handle_unary_unary(pre_response_callback) + elif not self.request_streaming and self.response_streaming: + self.unary_stream = _make_handle_unary_stream(pre_response_callback) + else: + self.stream_unary = _make_handle_stream_unary(pre_response_callback) class _GenericHandler(grpc.GenericRpcHandler): + def __init__(self, pre_response_callback): + self._pre_response_callback = pre_response_callback + def service(self, handler_call_details): if handler_call_details.method == _UNARY_UNARY: - return _MethodHandler(False, False) + return _MethodHandler(False, False, self._pre_response_callback) + elif handler_call_details.method == _UNARY_STREAM: + return _MethodHandler(False, True, self._pre_response_callback) + elif handler_call_details.method == _STREAM_UNARY: + return _MethodHandler(True, False, self._pre_response_callback) elif handler_call_details.method == _STREAM_STREAM: - return _MethodHandler(True, True) + return _MethodHandler(True, True, self._pre_response_callback) else: return None +@contextlib.contextmanager +def _instrumented_client_server_pair(channel_kwargs, server_kwargs, + server_handler): + server = grpc.server(futures.ThreadPoolExecutor(), **server_kwargs) + server.add_generic_rpc_handlers((server_handler,)) + server_port = server.add_insecure_port('{}:0'.format(_HOST)) + server.start() + with _tcp_proxy.TcpProxy(_HOST, _HOST, server_port) as proxy: + proxy_port = proxy.get_port() + with grpc.insecure_channel('{}:{}'.format(_HOST, proxy_port), + **channel_kwargs) as client_channel: + try: + yield client_channel, proxy, server + finally: + server.stop(None) + + +def _get_byte_counts(channel_kwargs, multicallable_kwargs, client_function, + server_kwargs, server_handler, message): + with _instrumented_client_server_pair(channel_kwargs, server_kwargs, + server_handler) as pipeline: + client_channel, proxy, server = pipeline + client_function(client_channel, multicallable_kwargs, message) + return proxy.get_byte_count() + + +def _get_compression_ratios(client_function, first_channel_kwargs, + first_multicallable_kwargs, first_server_kwargs, + first_server_handler, second_channel_kwargs, + second_multicallable_kwargs, second_server_kwargs, + second_server_handler, message): + try: + # This test requires the byte length of each connection to be deterministic. As + # it turns out, flow control puts bytes on the wire in a nondeterministic + # manner. We disable it here in order to measure compression ratios + # deterministically. + os.environ['GRPC_EXPERIMENTAL_DISABLE_FLOW_CONTROL'] = 'true' + first_bytes_sent, first_bytes_received = _get_byte_counts( + first_channel_kwargs, first_multicallable_kwargs, client_function, + first_server_kwargs, first_server_handler, message) + second_bytes_sent, second_bytes_received = _get_byte_counts( + second_channel_kwargs, second_multicallable_kwargs, client_function, + second_server_kwargs, second_server_handler, message) + return (( + second_bytes_sent - first_bytes_sent) / float(first_bytes_sent), + (second_bytes_received - first_bytes_received) / + float(first_bytes_received)) + finally: + del os.environ['GRPC_EXPERIMENTAL_DISABLE_FLOW_CONTROL'] + + +def _unary_unary_client(channel, multicallable_kwargs, message): + multi_callable = channel.unary_unary(_UNARY_UNARY) + response = multi_callable(message, **multicallable_kwargs) + if response != message: + raise RuntimeError("Request '{}' != Response '{}'".format( + message, response)) + + +def _unary_stream_client(channel, multicallable_kwargs, message): + multi_callable = channel.unary_stream(_UNARY_STREAM) + response_iterator = multi_callable(message, **multicallable_kwargs) + for response in response_iterator: + if response != message: + raise RuntimeError("Request '{}' != Response '{}'".format( + message, response)) + + +def _stream_unary_client(channel, multicallable_kwargs, message): + multi_callable = channel.stream_unary(_STREAM_UNARY) + requests = (_REQUEST for _ in range(_STREAM_LENGTH)) + response = multi_callable(requests, **multicallable_kwargs) + if response != message: + raise RuntimeError("Request '{}' != Response '{}'".format( + message, response)) + + +def _stream_stream_client(channel, multicallable_kwargs, message): + multi_callable = channel.stream_stream(_STREAM_STREAM) + request_prefix = str(0).encode('ascii') * 100 + requests = ( + request_prefix + str(i).encode('ascii') for i in range(_STREAM_LENGTH)) + response_iterator = multi_callable(requests, **multicallable_kwargs) + for i, response in enumerate(response_iterator): + if int(response.decode('ascii')) != i: + raise RuntimeError("Request '{}' != Response '{}'".format( + i, response)) + + class CompressionTest(unittest.TestCase): - def setUp(self): - self._server = test_common.test_server() - self._server.add_generic_rpc_handlers((_GenericHandler(),)) - self._port = self._server.add_insecure_port('[::]:0') - self._server.start() + def assertCompressed(self, compression_ratio): + self.assertLess( + compression_ratio, + -1.0 * _COMPRESSION_RATIO_THRESHOLD, + msg='Actual compression ratio: {}'.format(compression_ratio)) - def tearDown(self): - self._server.stop(None) + def assertNotCompressed(self, compression_ratio): + self.assertGreaterEqual( + compression_ratio, + -1.0 * _COMPRESSION_RATIO_THRESHOLD, + msg='Actual compession ratio: {}'.format(compression_ratio)) - def testUnary(self): - request = b'\x00' * 100 + def assertConfigurationCompressed( + self, client_streaming, server_streaming, channel_compression, + multicallable_compression, server_compression, + server_call_compression): + client_side_compressed = channel_compression or multicallable_compression + server_side_compressed = server_compression or server_call_compression + channel_kwargs = { + 'compression': channel_compression, + } if channel_compression else {} + multicallable_kwargs = { + 'compression': multicallable_compression, + } if multicallable_compression else {} - # Client -> server compressed through default client channel compression - # settings. Server -> client compressed via server-side metadata setting. - # TODO(https://github.com/grpc/grpc/issues/4078): replace the "1" integer - # literal with proper use of the public API. - compressed_channel = grpc.insecure_channel( - 'localhost:%d' % self._port, - options=[('grpc.default_compression_algorithm', 1)]) - multi_callable = compressed_channel.unary_unary(_UNARY_UNARY) - response = multi_callable(request) - self.assertEqual(request, response) + client_function = None + if not client_streaming and not server_streaming: + client_function = _unary_unary_client + elif not client_streaming and server_streaming: + client_function = _unary_stream_client + elif client_streaming and not server_streaming: + client_function = _stream_unary_client + else: + client_function = _stream_stream_client - # Client -> server compressed through client metadata setting. Server -> - # client compressed via server-side metadata setting. - # TODO(https://github.com/grpc/grpc/issues/4078): replace the "0" integer - # literal with proper use of the public API. - uncompressed_channel = grpc.insecure_channel( - 'localhost:%d' % self._port, - options=[('grpc.default_compression_algorithm', 0)]) - multi_callable = compressed_channel.unary_unary(_UNARY_UNARY) - response = multi_callable( - request, metadata=[('grpc-internal-encoding-request', 'gzip')]) - self.assertEqual(request, response) - compressed_channel.close() + server_kwargs = { + 'compression': server_compression, + } if server_compression else {} + server_handler = _GenericHandler( + functools.partial(set_call_compression, grpc.Compression.Gzip) + ) if server_call_compression else _GenericHandler(None) + sent_ratio, received_ratio = _get_compression_ratios( + client_function, {}, {}, {}, _GenericHandler(None), channel_kwargs, + multicallable_kwargs, server_kwargs, server_handler, _REQUEST) - def testStreaming(self): - request = b'\x00' * 100 + if client_side_compressed: + self.assertCompressed(sent_ratio) + else: + self.assertNotCompressed(sent_ratio) - # TODO(https://github.com/grpc/grpc/issues/4078): replace the "1" integer - # literal with proper use of the public API. - compressed_channel = grpc.insecure_channel( - 'localhost:%d' % self._port, - options=[('grpc.default_compression_algorithm', 1)]) - multi_callable = compressed_channel.stream_stream(_STREAM_STREAM) - call = multi_callable(iter([request] * test_constants.STREAM_LENGTH)) - for response in call: - self.assertEqual(request, response) - compressed_channel.close() + if server_side_compressed: + self.assertCompressed(received_ratio) + else: + self.assertNotCompressed(received_ratio) + def testDisableNextCompressionStreaming(self): + server_kwargs = { + 'compression': grpc.Compression.Deflate, + } + _, received_ratio = _get_compression_ratios( + _stream_stream_client, {}, {}, {}, _GenericHandler(None), {}, {}, + server_kwargs, _GenericHandler(disable_next_compression), _REQUEST) + self.assertNotCompressed(received_ratio) + + def testDisableNextCompressionStreamingResets(self): + server_kwargs = { + 'compression': grpc.Compression.Deflate, + } + _, received_ratio = _get_compression_ratios( + _stream_stream_client, {}, {}, {}, _GenericHandler(None), {}, {}, + server_kwargs, _GenericHandler(disable_first_compression), _REQUEST) + self.assertCompressed(received_ratio) + + +def _get_compression_str(name, value): + return '{}{}'.format(name, _COMPRESSION_NAMES[value]) + + +def _get_compression_test_name(client_streaming, server_streaming, + channel_compression, multicallable_compression, + server_compression, server_call_compression): + client_arity = 'Stream' if client_streaming else 'Unary' + server_arity = 'Stream' if server_streaming else 'Unary' + arity = '{}{}'.format(client_arity, server_arity) + channel_compression_str = _get_compression_str('Channel', + channel_compression) + multicallable_compression_str = _get_compression_str( + 'Multicallable', multicallable_compression) + server_compression_str = _get_compression_str('Server', server_compression) + server_call_compression_str = _get_compression_str('ServerCall', + server_call_compression) + return 'test{}{}{}{}{}'.format( + arity, channel_compression_str, multicallable_compression_str, + server_compression_str, server_call_compression_str) + + +def _test_options(): + for test_parameters in itertools.product(*_TEST_OPTIONS.values()): + yield dict(zip(_TEST_OPTIONS.keys(), test_parameters)) + + +for options in _test_options(): + + def test_compression(**kwargs): + + def _test_compression(self): + self.assertConfigurationCompressed(**kwargs) + + return _test_compression + + setattr(CompressionTest, _get_compression_test_name(**options), + test_compression(**options)) if __name__ == '__main__': logging.basicConfig() diff --git a/src/python/grpcio_tests/tests/unit/_tcp_proxy.py b/src/python/grpcio_tests/tests/unit/_tcp_proxy.py new file mode 100644 index 00000000000..5ad0bf8f028 --- /dev/null +++ b/src/python/grpcio_tests/tests/unit/_tcp_proxy.py @@ -0,0 +1,164 @@ +# Copyright 2019 the gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" Proxies a TCP connection between a single client-server pair. + +This proxy is not suitable for production, but should work well for cases in +which a test needs to spy on the bytes put on the wire between a server and +a client. +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import datetime +import select +import socket +import threading + +_TCP_PROXY_BUFFER_SIZE = 1024 +_TCP_PROXY_TIMEOUT = datetime.timedelta(milliseconds=500) + + +def _create_socket_ipv6(bind_address): + listen_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + listen_socket.bind((bind_address, 0, 0, 0)) + return listen_socket + + +def _create_socket_ipv4(bind_address): + listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + listen_socket.bind((bind_address, 0)) + return listen_socket + + +def _init_listen_socket(bind_address): + listen_socket = None + if socket.has_ipv6: + try: + listen_socket = _create_socket_ipv6(bind_address) + except socket.error: + listen_socket = _create_socket_ipv4(bind_address) + else: + listen_socket = _create_socket_ipv4(bind_address) + listen_socket.listen(1) + return listen_socket, listen_socket.getsockname()[1] + + +def _init_proxy_socket(gateway_address, gateway_port): + proxy_socket = socket.create_connection((gateway_address, gateway_port)) + return proxy_socket + + +class TcpProxy(object): + """Proxies a TCP connection between one client and one server.""" + + def __init__(self, bind_address, gateway_address, gateway_port): + self._bind_address = bind_address + self._gateway_address = gateway_address + self._gateway_port = gateway_port + + self._byte_count_lock = threading.RLock() + self._sent_byte_count = 0 + self._received_byte_count = 0 + + self._stop_event = threading.Event() + + self._port = None + self._listen_socket = None + self._proxy_socket = None + + # The following three attributes are owned by the serving thread. + self._northbound_data = b"" + self._southbound_data = b"" + self._client_sockets = [] + + self._thread = threading.Thread(target=self._run_proxy) + + def start(self): + self._listen_socket, self._port = _init_listen_socket( + self._bind_address) + self._proxy_socket = _init_proxy_socket(self._gateway_address, + self._gateway_port) + self._thread.start() + + def get_port(self): + return self._port + + def _handle_reads(self, sockets_to_read): + for socket_to_read in sockets_to_read: + if socket_to_read is self._listen_socket: + client_socket, client_address = socket_to_read.accept() + self._client_sockets.append(client_socket) + elif socket_to_read is self._proxy_socket: + data = socket_to_read.recv(_TCP_PROXY_BUFFER_SIZE) + with self._byte_count_lock: + self._received_byte_count += len(data) + self._northbound_data += data + elif socket_to_read in self._client_sockets: + data = socket_to_read.recv(_TCP_PROXY_BUFFER_SIZE) + if data: + with self._byte_count_lock: + self._sent_byte_count += len(data) + self._southbound_data += data + else: + self._client_sockets.remove(socket_to_read) + else: + raise RuntimeError('Unidentified socket appeared in read set.') + + def _handle_writes(self, sockets_to_write): + for socket_to_write in sockets_to_write: + if socket_to_write is self._proxy_socket: + if self._southbound_data: + self._proxy_socket.sendall(self._southbound_data) + self._southbound_data = b"" + elif socket_to_write in self._client_sockets: + if self._northbound_data: + socket_to_write.sendall(self._northbound_data) + self._northbound_data = b"" + + def _run_proxy(self): + while not self._stop_event.is_set(): + expected_reads = (self._listen_socket, self._proxy_socket) + tuple( + self._client_sockets) + expected_writes = expected_reads + sockets_to_read, sockets_to_write, _ = select.select( + expected_reads, expected_writes, (), + _TCP_PROXY_TIMEOUT.total_seconds()) + self._handle_reads(sockets_to_read) + self._handle_writes(sockets_to_write) + for client_socket in self._client_sockets: + client_socket.close() + + def stop(self): + self._stop_event.set() + self._thread.join() + self._listen_socket.close() + self._proxy_socket.close() + + def get_byte_count(self): + with self._byte_count_lock: + return self._sent_byte_count, self._received_byte_count + + def reset_byte_count(self): + with self._byte_count_lock: + self._byte_count = 0 + self._received_byte_count = 0 + + def __enter__(self): + self.start() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.stop() From 05529154e75b9a5b99134092f89cd7bb5f2cd588 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 26 Mar 2019 12:16:11 -0700 Subject: [PATCH 229/242] move Async*Call classes to Grpc.Core.Api --- .../{Grpc.Core => Grpc.Core.Api}/AsyncClientStreamingCall.cs | 0 .../{Grpc.Core => Grpc.Core.Api}/AsyncDuplexStreamingCall.cs | 0 .../{Grpc.Core => Grpc.Core.Api}/AsyncServerStreamingCall.cs | 0 src/csharp/{Grpc.Core => Grpc.Core.Api}/AsyncUnaryCall.cs | 0 .../{Grpc.Core => Grpc.Core.Api}/IClientStreamWriter.cs | 0 src/csharp/Grpc.Core/ForwardedTypes.cs | 5 +++++ 6 files changed, 5 insertions(+) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/AsyncClientStreamingCall.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/AsyncDuplexStreamingCall.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/AsyncServerStreamingCall.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/AsyncUnaryCall.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/IClientStreamWriter.cs (100%) diff --git a/src/csharp/Grpc.Core/AsyncClientStreamingCall.cs b/src/csharp/Grpc.Core.Api/AsyncClientStreamingCall.cs similarity index 100% rename from src/csharp/Grpc.Core/AsyncClientStreamingCall.cs rename to src/csharp/Grpc.Core.Api/AsyncClientStreamingCall.cs diff --git a/src/csharp/Grpc.Core/AsyncDuplexStreamingCall.cs b/src/csharp/Grpc.Core.Api/AsyncDuplexStreamingCall.cs similarity index 100% rename from src/csharp/Grpc.Core/AsyncDuplexStreamingCall.cs rename to src/csharp/Grpc.Core.Api/AsyncDuplexStreamingCall.cs diff --git a/src/csharp/Grpc.Core/AsyncServerStreamingCall.cs b/src/csharp/Grpc.Core.Api/AsyncServerStreamingCall.cs similarity index 100% rename from src/csharp/Grpc.Core/AsyncServerStreamingCall.cs rename to src/csharp/Grpc.Core.Api/AsyncServerStreamingCall.cs diff --git a/src/csharp/Grpc.Core/AsyncUnaryCall.cs b/src/csharp/Grpc.Core.Api/AsyncUnaryCall.cs similarity index 100% rename from src/csharp/Grpc.Core/AsyncUnaryCall.cs rename to src/csharp/Grpc.Core.Api/AsyncUnaryCall.cs diff --git a/src/csharp/Grpc.Core/IClientStreamWriter.cs b/src/csharp/Grpc.Core.Api/IClientStreamWriter.cs similarity index 100% rename from src/csharp/Grpc.Core/IClientStreamWriter.cs rename to src/csharp/Grpc.Core.Api/IClientStreamWriter.cs diff --git a/src/csharp/Grpc.Core/ForwardedTypes.cs b/src/csharp/Grpc.Core/ForwardedTypes.cs index 39221925392..3a39560a936 100644 --- a/src/csharp/Grpc.Core/ForwardedTypes.cs +++ b/src/csharp/Grpc.Core/ForwardedTypes.cs @@ -27,12 +27,17 @@ using Grpc.Core.Utils; // TODO(jtattermusch): move types needed for implementing a client [assembly:TypeForwardedToAttribute(typeof(GrpcPreconditions))] +[assembly:TypeForwardedToAttribute(typeof(AsyncClientStreamingCall<,>))] +[assembly:TypeForwardedToAttribute(typeof(AsyncDuplexStreamingCall<,>))] +[assembly:TypeForwardedToAttribute(typeof(AsyncServerStreamingCall<>))] +[assembly:TypeForwardedToAttribute(typeof(AsyncUnaryCall<>))] [assembly:TypeForwardedToAttribute(typeof(AuthContext))] [assembly:TypeForwardedToAttribute(typeof(ContextPropagationOptions))] [assembly:TypeForwardedToAttribute(typeof(ContextPropagationToken))] [assembly:TypeForwardedToAttribute(typeof(DeserializationContext))] [assembly:TypeForwardedToAttribute(typeof(IAsyncStreamReader<>))] [assembly:TypeForwardedToAttribute(typeof(IAsyncStreamWriter<>))] +[assembly:TypeForwardedToAttribute(typeof(IClientStreamWriter<>))] [assembly:TypeForwardedToAttribute(typeof(IServerStreamWriter<>))] [assembly:TypeForwardedToAttribute(typeof(Marshaller<>))] [assembly:TypeForwardedToAttribute(typeof(Marshallers))] From 5a973832830fd9854a2a9e62e4345a4a485413d1 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 26 Mar 2019 19:51:22 -0700 Subject: [PATCH 230/242] move CallInvoker and its prerequisites to Grpc.Core.Api --- .../AsyncAuthInterceptor.cs | 0 .../CallCredentials.cs | 0 .../CallCredentialsConfiguratorBase.cs | 1 + .../Internal => Grpc.Core.Api}/CallFlags.cs | 0 .../CallInvoker.cs | 2 - .../CallOptions.cs | 32 ----------- src/csharp/Grpc.Core/ForwardedTypes.cs | 4 ++ .../Internal/CallOptionsExtensions.cs | 57 +++++++++++++++++++ 8 files changed, 62 insertions(+), 34 deletions(-) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/AsyncAuthInterceptor.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/CallCredentials.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/CallCredentialsConfiguratorBase.cs (94%) rename src/csharp/{Grpc.Core/Internal => Grpc.Core.Api}/CallFlags.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/CallInvoker.cs (98%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/CallOptions.cs (84%) create mode 100644 src/csharp/Grpc.Core/Internal/CallOptionsExtensions.cs diff --git a/src/csharp/Grpc.Core/AsyncAuthInterceptor.cs b/src/csharp/Grpc.Core.Api/AsyncAuthInterceptor.cs similarity index 100% rename from src/csharp/Grpc.Core/AsyncAuthInterceptor.cs rename to src/csharp/Grpc.Core.Api/AsyncAuthInterceptor.cs diff --git a/src/csharp/Grpc.Core/CallCredentials.cs b/src/csharp/Grpc.Core.Api/CallCredentials.cs similarity index 100% rename from src/csharp/Grpc.Core/CallCredentials.cs rename to src/csharp/Grpc.Core.Api/CallCredentials.cs diff --git a/src/csharp/Grpc.Core/CallCredentialsConfiguratorBase.cs b/src/csharp/Grpc.Core.Api/CallCredentialsConfiguratorBase.cs similarity index 94% rename from src/csharp/Grpc.Core/CallCredentialsConfiguratorBase.cs rename to src/csharp/Grpc.Core.Api/CallCredentialsConfiguratorBase.cs index 40a33bbf599..51f8d729a11 100644 --- a/src/csharp/Grpc.Core/CallCredentialsConfiguratorBase.cs +++ b/src/csharp/Grpc.Core.Api/CallCredentialsConfiguratorBase.cs @@ -22,6 +22,7 @@ namespace Grpc.Core { /// /// Base class for objects that can consume configuration from CallCredentials objects. + /// Note: experimental API that can change or be removed without any prior notice. /// public abstract class CallCredentialsConfiguratorBase { diff --git a/src/csharp/Grpc.Core/Internal/CallFlags.cs b/src/csharp/Grpc.Core.Api/CallFlags.cs similarity index 100% rename from src/csharp/Grpc.Core/Internal/CallFlags.cs rename to src/csharp/Grpc.Core.Api/CallFlags.cs diff --git a/src/csharp/Grpc.Core/CallInvoker.cs b/src/csharp/Grpc.Core.Api/CallInvoker.cs similarity index 98% rename from src/csharp/Grpc.Core/CallInvoker.cs rename to src/csharp/Grpc.Core.Api/CallInvoker.cs index 09fbf0b1e8d..8a84a5215ce 100644 --- a/src/csharp/Grpc.Core/CallInvoker.cs +++ b/src/csharp/Grpc.Core.Api/CallInvoker.cs @@ -17,14 +17,12 @@ #endregion using System.Threading.Tasks; -using Grpc.Core.Internal; namespace Grpc.Core { /// /// Abstraction of client-side RPC invocation. /// - /// public abstract class CallInvoker { /// diff --git a/src/csharp/Grpc.Core/CallOptions.cs b/src/csharp/Grpc.Core.Api/CallOptions.cs similarity index 84% rename from src/csharp/Grpc.Core/CallOptions.cs rename to src/csharp/Grpc.Core.Api/CallOptions.cs index a92caae917d..c0b732a1005 100644 --- a/src/csharp/Grpc.Core/CallOptions.cs +++ b/src/csharp/Grpc.Core.Api/CallOptions.cs @@ -20,7 +20,6 @@ using System; using System.Threading; using Grpc.Core.Internal; -using Grpc.Core.Utils; namespace Grpc.Core { @@ -227,36 +226,5 @@ namespace Grpc.Core newOptions.flags = flags; return newOptions; } - - /// - /// Returns a new instance of with - /// all previously unset values set to their defaults and deadline and cancellation - /// token propagated when appropriate. - /// - internal CallOptions Normalize() - { - var newOptions = this; - // silently ignore the context propagation token if it wasn't produced by "us" - var propagationTokenImpl = propagationToken.AsImplOrNull(); - if (propagationTokenImpl != null) - { - if (propagationTokenImpl.Options.IsPropagateDeadline) - { - GrpcPreconditions.CheckArgument(!newOptions.deadline.HasValue, - "Cannot propagate deadline from parent call. The deadline has already been set explicitly."); - newOptions.deadline = propagationTokenImpl.ParentDeadline; - } - if (propagationTokenImpl.Options.IsPropagateCancellation) - { - GrpcPreconditions.CheckArgument(!newOptions.cancellationToken.CanBeCanceled, - "Cannot propagate cancellation token from parent call. The cancellation token has already been set to a non-default value."); - newOptions.cancellationToken = propagationTokenImpl.ParentCancellationToken; - } - } - - newOptions.headers = newOptions.headers ?? Metadata.Empty; - newOptions.deadline = newOptions.deadline ?? DateTime.MaxValue; - return newOptions; - } } } diff --git a/src/csharp/Grpc.Core/ForwardedTypes.cs b/src/csharp/Grpc.Core/ForwardedTypes.cs index 3a39560a936..ec47d423141 100644 --- a/src/csharp/Grpc.Core/ForwardedTypes.cs +++ b/src/csharp/Grpc.Core/ForwardedTypes.cs @@ -26,6 +26,10 @@ using Grpc.Core.Utils; // TODO(jtattermusch): move types needed for implementing a client +// TODO: problematic areas: +// - CallOptions depends on CallCredentials (publicly) and on CallFlags (internally) & CallOptions is a struct +// - internal method CallOptions.Normalize() uses internal method propagationToken.AsImplOrNull() + [assembly:TypeForwardedToAttribute(typeof(GrpcPreconditions))] [assembly:TypeForwardedToAttribute(typeof(AsyncClientStreamingCall<,>))] [assembly:TypeForwardedToAttribute(typeof(AsyncDuplexStreamingCall<,>))] diff --git a/src/csharp/Grpc.Core/Internal/CallOptionsExtensions.cs b/src/csharp/Grpc.Core/Internal/CallOptionsExtensions.cs new file mode 100644 index 00000000000..b58b041297f --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/CallOptionsExtensions.cs @@ -0,0 +1,57 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#endregion + +using System; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + internal static class CallOptionsExtensions + { + /// + /// Returns a new instance of with + /// all previously unset values set to their defaults and deadline and cancellation + /// token propagated when appropriate. + /// + internal static CallOptions Normalize(this CallOptions options) + { + var newOptions = options; + // silently ignore the context propagation token if it wasn't produced by "us" + var propagationTokenImpl = options.PropagationToken.AsImplOrNull(); + if (propagationTokenImpl != null) + { + if (propagationTokenImpl.Options.IsPropagateDeadline) + { + GrpcPreconditions.CheckArgument(!newOptions.Deadline.HasValue, + "Cannot propagate deadline from parent call. The deadline has already been set explicitly."); + newOptions = newOptions.WithDeadline(propagationTokenImpl.ParentDeadline); + } + if (propagationTokenImpl.Options.IsPropagateCancellation) + { + GrpcPreconditions.CheckArgument(!newOptions.CancellationToken.CanBeCanceled, + "Cannot propagate cancellation token from parent call. The cancellation token has already been set to a non-default value."); + newOptions = newOptions.WithCancellationToken(propagationTokenImpl.ParentCancellationToken); + } + } + + newOptions = newOptions.WithHeaders(newOptions.Headers ?? Metadata.Empty); + newOptions = newOptions.WithDeadline(newOptions.Deadline ?? DateTime.MaxValue); + return newOptions; + } + } +} From ef4ee8eca8c3dc923e68e6d8faee511ca179a25e Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 5 Apr 2019 16:54:43 +0200 Subject: [PATCH 231/242] update ForwardedTypes.cs --- src/csharp/Grpc.Core/ForwardedTypes.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/csharp/Grpc.Core/ForwardedTypes.cs b/src/csharp/Grpc.Core/ForwardedTypes.cs index ec47d423141..712c25e103e 100644 --- a/src/csharp/Grpc.Core/ForwardedTypes.cs +++ b/src/csharp/Grpc.Core/ForwardedTypes.cs @@ -18,24 +18,23 @@ using System.Runtime.CompilerServices; using Grpc.Core; -using Grpc.Core.Logging; +using Grpc.Core.Internal; using Grpc.Core.Utils; // API types that used to be in Grpc.Core package, but were moved to Grpc.Core.Api // https://docs.microsoft.com/en-us/dotnet/framework/app-domains/type-forwarding-in-the-common-language-runtime -// TODO(jtattermusch): move types needed for implementing a client - -// TODO: problematic areas: -// - CallOptions depends on CallCredentials (publicly) and on CallFlags (internally) & CallOptions is a struct -// - internal method CallOptions.Normalize() uses internal method propagationToken.AsImplOrNull() - [assembly:TypeForwardedToAttribute(typeof(GrpcPreconditions))] [assembly:TypeForwardedToAttribute(typeof(AsyncClientStreamingCall<,>))] [assembly:TypeForwardedToAttribute(typeof(AsyncDuplexStreamingCall<,>))] [assembly:TypeForwardedToAttribute(typeof(AsyncServerStreamingCall<>))] [assembly:TypeForwardedToAttribute(typeof(AsyncUnaryCall<>))] [assembly:TypeForwardedToAttribute(typeof(AuthContext))] +[assembly:TypeForwardedToAttribute(typeof(AuthInterceptorContext))] +[assembly: TypeForwardedToAttribute(typeof(CallCredentials))] +[assembly: TypeForwardedToAttribute(typeof(CallFlags))] +[assembly: TypeForwardedToAttribute(typeof(CallInvoker))] +[assembly: TypeForwardedToAttribute(typeof(CallOptions))] [assembly:TypeForwardedToAttribute(typeof(ContextPropagationOptions))] [assembly:TypeForwardedToAttribute(typeof(ContextPropagationToken))] [assembly:TypeForwardedToAttribute(typeof(DeserializationContext))] From e0d2ffe3258d94e38c1f683bdadb7d254b5cefcc Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 10 Apr 2019 09:50:20 +0200 Subject: [PATCH 232/242] fixup ForwardedTypes.cs --- src/csharp/Grpc.Core/ForwardedTypes.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/csharp/Grpc.Core/ForwardedTypes.cs b/src/csharp/Grpc.Core/ForwardedTypes.cs index 712c25e103e..3df44d167be 100644 --- a/src/csharp/Grpc.Core/ForwardedTypes.cs +++ b/src/csharp/Grpc.Core/ForwardedTypes.cs @@ -30,6 +30,7 @@ using Grpc.Core.Utils; [assembly:TypeForwardedToAttribute(typeof(AsyncServerStreamingCall<>))] [assembly:TypeForwardedToAttribute(typeof(AsyncUnaryCall<>))] [assembly:TypeForwardedToAttribute(typeof(AuthContext))] +[assembly:TypeForwardedToAttribute(typeof(AsyncAuthInterceptor))] [assembly:TypeForwardedToAttribute(typeof(AuthInterceptorContext))] [assembly: TypeForwardedToAttribute(typeof(CallCredentials))] [assembly: TypeForwardedToAttribute(typeof(CallFlags))] From 891b6cf7aea6e0638c80f6d23af7f53e2cd59c9b Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Wed, 10 Apr 2019 10:22:59 -0700 Subject: [PATCH 233/242] Revert "Folding CompletionQueue and ServerCompletionQueue." --- BUILD | 1 - BUILD.gn | 1 - CMakeLists.txt | 5 - Makefile | 5 - build.yaml | 1 - gRPC-C++.podspec | 1 - include/grpcpp/channel_impl.h | 13 +- include/grpcpp/create_channel_impl.h | 6 +- include/grpcpp/generic/generic_stub_impl.h | 2 +- include/grpcpp/impl/codegen/async_stream.h | 2 + .../grpcpp/impl/codegen/async_unary_call.h | 1 + include/grpcpp/impl/codegen/call.h | 16 +- include/grpcpp/impl/codegen/call_op_set.h | 1 + .../grpcpp/impl/codegen/channel_interface.h | 16 +- include/grpcpp/impl/codegen/client_callback.h | 1 + include/grpcpp/impl/codegen/client_context.h | 1 + .../grpcpp/impl/codegen/client_unary_call.h | 2 + .../grpcpp/impl/codegen/completion_queue.h | 379 +++++++++++++++- .../impl/codegen/completion_queue_impl.h | 422 ------------------ .../grpcpp/impl/codegen/intercepted_channel.h | 13 +- include/grpcpp/impl/codegen/server_context.h | 6 +- .../grpcpp/impl/codegen/server_interface.h | 72 ++- include/grpcpp/impl/codegen/service_type.h | 2 + include/grpcpp/server_builder.h | 7 + include/grpcpp/server_builder_impl.h | 4 +- src/compiler/cpp_generator.cc | 4 +- src/cpp/common/completion_queue_cc.cc | 12 +- test/cpp/codegen/compiler_test_golden | 4 +- tools/doxygen/Doxyfile.c++ | 1 - tools/doxygen/Doxyfile.c++.internal | 1 - .../generated/sources_and_headers.json | 2 - 31 files changed, 467 insertions(+), 537 deletions(-) delete mode 100644 include/grpcpp/impl/codegen/completion_queue_impl.h diff --git a/BUILD b/BUILD index ec9f58dbed1..74cf5413ba1 100644 --- a/BUILD +++ b/BUILD @@ -2130,7 +2130,6 @@ grpc_cc_library( "include/grpcpp/impl/codegen/client_interceptor.h", "include/grpcpp/impl/codegen/client_unary_call.h", "include/grpcpp/impl/codegen/completion_queue.h", - "include/grpcpp/impl/codegen/completion_queue_impl.h", "include/grpcpp/impl/codegen/completion_queue_tag.h", "include/grpcpp/impl/codegen/config.h", "include/grpcpp/impl/codegen/core_codegen_interface.h", diff --git a/BUILD.gn b/BUILD.gn index 78e434477b8..081de0cbfeb 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1035,7 +1035,6 @@ config("grpc_config") { "include/grpcpp/impl/codegen/client_interceptor.h", "include/grpcpp/impl/codegen/client_unary_call.h", "include/grpcpp/impl/codegen/completion_queue.h", - "include/grpcpp/impl/codegen/completion_queue_impl.h", "include/grpcpp/impl/codegen/completion_queue_tag.h", "include/grpcpp/impl/codegen/config.h", "include/grpcpp/impl/codegen/config_protobuf.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d5e448d688..1a6aa0307bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3157,7 +3157,6 @@ foreach(_hdr include/grpcpp/impl/codegen/client_interceptor.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h - include/grpcpp/impl/codegen/completion_queue_impl.h include/grpcpp/impl/codegen/completion_queue_tag.h include/grpcpp/impl/codegen/config.h include/grpcpp/impl/codegen/core_codegen_interface.h @@ -3763,7 +3762,6 @@ foreach(_hdr include/grpcpp/impl/codegen/client_interceptor.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h - include/grpcpp/impl/codegen/completion_queue_impl.h include/grpcpp/impl/codegen/completion_queue_tag.h include/grpcpp/impl/codegen/config.h include/grpcpp/impl/codegen/core_codegen_interface.h @@ -4197,7 +4195,6 @@ foreach(_hdr include/grpcpp/impl/codegen/client_interceptor.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h - include/grpcpp/impl/codegen/completion_queue_impl.h include/grpcpp/impl/codegen/completion_queue_tag.h include/grpcpp/impl/codegen/config.h include/grpcpp/impl/codegen/core_codegen_interface.h @@ -4395,7 +4392,6 @@ foreach(_hdr include/grpcpp/impl/codegen/client_interceptor.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h - include/grpcpp/impl/codegen/completion_queue_impl.h include/grpcpp/impl/codegen/completion_queue_tag.h include/grpcpp/impl/codegen/config.h include/grpcpp/impl/codegen/core_codegen_interface.h @@ -4747,7 +4743,6 @@ foreach(_hdr include/grpcpp/impl/codegen/client_interceptor.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h - include/grpcpp/impl/codegen/completion_queue_impl.h include/grpcpp/impl/codegen/completion_queue_tag.h include/grpcpp/impl/codegen/config.h include/grpcpp/impl/codegen/core_codegen_interface.h diff --git a/Makefile b/Makefile index c3c7412590d..4cbcc0be757 100644 --- a/Makefile +++ b/Makefile @@ -5492,7 +5492,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/client_interceptor.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ - include/grpcpp/impl/codegen/completion_queue_impl.h \ include/grpcpp/impl/codegen/completion_queue_tag.h \ include/grpcpp/impl/codegen/config.h \ include/grpcpp/impl/codegen/core_codegen_interface.h \ @@ -6106,7 +6105,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/client_interceptor.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ - include/grpcpp/impl/codegen/completion_queue_impl.h \ include/grpcpp/impl/codegen/completion_queue_tag.h \ include/grpcpp/impl/codegen/config.h \ include/grpcpp/impl/codegen/core_codegen_interface.h \ @@ -6512,7 +6510,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/client_interceptor.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ - include/grpcpp/impl/codegen/completion_queue_impl.h \ include/grpcpp/impl/codegen/completion_queue_tag.h \ include/grpcpp/impl/codegen/config.h \ include/grpcpp/impl/codegen/core_codegen_interface.h \ @@ -6681,7 +6678,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/client_interceptor.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ - include/grpcpp/impl/codegen/completion_queue_impl.h \ include/grpcpp/impl/codegen/completion_queue_tag.h \ include/grpcpp/impl/codegen/config.h \ include/grpcpp/impl/codegen/core_codegen_interface.h \ @@ -7039,7 +7035,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/client_interceptor.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ - include/grpcpp/impl/codegen/completion_queue_impl.h \ include/grpcpp/impl/codegen/completion_queue_tag.h \ include/grpcpp/impl/codegen/config.h \ include/grpcpp/impl/codegen/core_codegen_interface.h \ diff --git a/build.yaml b/build.yaml index 8752447f125..51422e22adb 100644 --- a/build.yaml +++ b/build.yaml @@ -1248,7 +1248,6 @@ filegroups: - include/grpcpp/impl/codegen/client_interceptor.h - include/grpcpp/impl/codegen/client_unary_call.h - include/grpcpp/impl/codegen/completion_queue.h - - include/grpcpp/impl/codegen/completion_queue_impl.h - include/grpcpp/impl/codegen/completion_queue_tag.h - include/grpcpp/impl/codegen/config.h - include/grpcpp/impl/codegen/core_codegen_interface.h diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 7c90454f1a9..e9a41c9e758 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -160,7 +160,6 @@ Pod::Spec.new do |s| 'include/grpcpp/impl/codegen/client_interceptor.h', 'include/grpcpp/impl/codegen/client_unary_call.h', 'include/grpcpp/impl/codegen/completion_queue.h', - 'include/grpcpp/impl/codegen/completion_queue_impl.h', 'include/grpcpp/impl/codegen/completion_queue_tag.h', 'include/grpcpp/impl/codegen/config.h', 'include/grpcpp/impl/codegen/core_codegen_interface.h', diff --git a/include/grpcpp/channel_impl.h b/include/grpcpp/channel_impl.h index 19422d8d30b..26850f8d30f 100644 --- a/include/grpcpp/channel_impl.h +++ b/include/grpcpp/channel_impl.h @@ -34,7 +34,6 @@ struct grpc_channel; namespace grpc_impl { -class CompletionQueue; namespace experimental { /// Resets the channel's connection backoff. /// TODO(roth): Once we see whether this proves useful, either create a gRFC @@ -78,22 +77,22 @@ class Channel final : public ::grpc::ChannelInterface, ::grpc::internal::Call CreateCall(const ::grpc::internal::RpcMethod& method, ::grpc::ClientContext* context, - CompletionQueue* cq) override; + ::grpc::CompletionQueue* cq) override; void PerformOpsOnCall(::grpc::internal::CallOpSetInterface* ops, ::grpc::internal::Call* call) override; void* RegisterMethod(const char* method) override; void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, - gpr_timespec deadline, CompletionQueue* cq, - void* tag) override; + gpr_timespec deadline, + ::grpc::CompletionQueue* cq, void* tag) override; bool WaitForStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline) override; - CompletionQueue* CallbackCQ() override; + ::grpc::CompletionQueue* CallbackCQ() override; ::grpc::internal::Call CreateCallInternal( const ::grpc::internal::RpcMethod& method, ::grpc::ClientContext* context, - CompletionQueue* cq, size_t interceptor_pos) override; + ::grpc::CompletionQueue* cq, size_t interceptor_pos) override; const grpc::string host_; grpc_channel* const c_channel_; // owned @@ -105,7 +104,7 @@ class Channel final : public ::grpc::ChannelInterface, // with this channel (if any). It is set on the first call to CallbackCQ(). // It is _not owned_ by the channel; ownership belongs with its internal // shutdown callback tag (invoked when the CQ is fully shutdown). - CompletionQueue* callback_cq_ = nullptr; + ::grpc::CompletionQueue* callback_cq_ = nullptr; std::vector< std::unique_ptr<::grpc::experimental::ClientInterceptorFactoryInterface>> diff --git a/include/grpcpp/create_channel_impl.h b/include/grpcpp/create_channel_impl.h index 84b6c0e643d..214a537a3cb 100644 --- a/include/grpcpp/create_channel_impl.h +++ b/include/grpcpp/create_channel_impl.h @@ -35,7 +35,7 @@ namespace grpc_impl { /// \param creds Credentials to use for the created channel. If it does not /// hold an object or is invalid, a lame channel (one on which all operations /// fail) is returned. -std::shared_ptr CreateChannel( +std::shared_ptr CreateChannel( const grpc::string& target, const std::shared_ptr& creds); @@ -49,7 +49,7 @@ std::shared_ptr CreateChannel( /// hold an object or is invalid, a lame channel (one on which all operations /// fail) is returned. /// \param args Options for channel creation. -std::shared_ptr CreateCustomChannel( +std::shared_ptr CreateCustomChannel( const grpc::string& target, const std::shared_ptr& creds, const grpc::ChannelArguments& args); @@ -66,7 +66,7 @@ namespace experimental { /// hold an object or is invalid, a lame channel (one on which all operations /// fail) is returned. /// \param args Options for channel creation. -std::shared_ptr CreateCustomChannelWithInterceptors( +std::shared_ptr CreateCustomChannelWithInterceptors( const grpc::string& target, const std::shared_ptr& creds, const grpc::ChannelArguments& args, diff --git a/include/grpcpp/generic/generic_stub_impl.h b/include/grpcpp/generic/generic_stub_impl.h index ff1223453c1..2d6a11de923 100644 --- a/include/grpcpp/generic/generic_stub_impl.h +++ b/include/grpcpp/generic/generic_stub_impl.h @@ -29,12 +29,12 @@ namespace grpc { +class CompletionQueue; typedef ClientAsyncReaderWriter GenericClientAsyncReaderWriter; typedef ClientAsyncResponseReader GenericClientAsyncResponseReader; } // namespace grpc namespace grpc_impl { -class CompletionQueue; /// Generic stubs provide a type-unsafe interface to call gRPC methods /// by name. diff --git a/include/grpcpp/impl/codegen/async_stream.h b/include/grpcpp/impl/codegen/async_stream.h index 6b8a9df7b29..e12923ea02c 100644 --- a/include/grpcpp/impl/codegen/async_stream.h +++ b/include/grpcpp/impl/codegen/async_stream.h @@ -28,6 +28,8 @@ namespace grpc { +class CompletionQueue; + namespace internal { /// Common interface for all client side asynchronous streaming. class ClientAsyncStreamingInterface { diff --git a/include/grpcpp/impl/codegen/async_unary_call.h b/include/grpcpp/impl/codegen/async_unary_call.h index 4b97cf29018..89dcb124189 100644 --- a/include/grpcpp/impl/codegen/async_unary_call.h +++ b/include/grpcpp/impl/codegen/async_unary_call.h @@ -29,6 +29,7 @@ namespace grpc { +class CompletionQueue; extern CoreCodegenInterface* g_core_codegen_interface; /// An interface relevant for async client side unary RPCs (which send diff --git a/include/grpcpp/impl/codegen/call.h b/include/grpcpp/impl/codegen/call.h index eefa4a7f9cd..c040c30dd9d 100644 --- a/include/grpcpp/impl/codegen/call.h +++ b/include/grpcpp/impl/codegen/call.h @@ -21,11 +21,9 @@ #include #include -namespace grpc_impl { -class CompletionQueue; -} - namespace grpc { +class CompletionQueue; + namespace experimental { class ClientRpcInfo; class ServerRpcInfo; @@ -43,13 +41,13 @@ class Call final { call_(nullptr), max_receive_message_size_(-1) {} /** call is owned by the caller */ - Call(grpc_call* call, CallHook* call_hook, ::grpc_impl::CompletionQueue* cq) + Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq) : call_hook_(call_hook), cq_(cq), call_(call), max_receive_message_size_(-1) {} - Call(grpc_call* call, CallHook* call_hook, ::grpc_impl::CompletionQueue* cq, + Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq, experimental::ClientRpcInfo* rpc_info) : call_hook_(call_hook), cq_(cq), @@ -57,7 +55,7 @@ class Call final { max_receive_message_size_(-1), client_rpc_info_(rpc_info) {} - Call(grpc_call* call, CallHook* call_hook, ::grpc_impl::CompletionQueue* cq, + Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq, int max_receive_message_size, experimental::ServerRpcInfo* rpc_info) : call_hook_(call_hook), cq_(cq), @@ -70,7 +68,7 @@ class Call final { } grpc_call* call() const { return call_; } - ::grpc_impl::CompletionQueue* cq() const { return cq_; } + CompletionQueue* cq() const { return cq_; } int max_receive_message_size() const { return max_receive_message_size_; } @@ -84,7 +82,7 @@ class Call final { private: CallHook* call_hook_; - ::grpc_impl::CompletionQueue* cq_; + CompletionQueue* cq_; grpc_call* call_; int max_receive_message_size_; experimental::ClientRpcInfo* client_rpc_info_ = nullptr; diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index d810625b3e4..4ca87a99fca 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -48,6 +48,7 @@ namespace grpc { +class CompletionQueue; extern CoreCodegenInterface* g_core_codegen_interface; namespace internal { diff --git a/include/grpcpp/impl/codegen/channel_interface.h b/include/grpcpp/impl/codegen/channel_interface.h index faa5e41cef9..5353f5feaa6 100644 --- a/include/grpcpp/impl/codegen/channel_interface.h +++ b/include/grpcpp/impl/codegen/channel_interface.h @@ -24,13 +24,10 @@ #include #include -namespace grpc_impl { -class CompletionQueue; -} - namespace grpc { class ChannelInterface; class ClientContext; +class CompletionQueue; template class ClientReader; @@ -76,7 +73,7 @@ class ChannelInterface { /// deadline expires. \a GetState needs to called to get the current state. template void NotifyOnStateChange(grpc_connectivity_state last_observed, T deadline, - ::grpc_impl::CompletionQueue* cq, void* tag) { + CompletionQueue* cq, void* tag) { TimePoint deadline_tp(deadline); NotifyOnStateChangeImpl(last_observed, deadline_tp.raw_time(), cq, tag); } @@ -128,14 +125,13 @@ class ChannelInterface { friend class ::grpc::internal::InterceptedChannel; virtual internal::Call CreateCall(const internal::RpcMethod& method, ClientContext* context, - ::grpc_impl::CompletionQueue* cq) = 0; + CompletionQueue* cq) = 0; virtual void PerformOpsOnCall(internal::CallOpSetInterface* ops, internal::Call* call) = 0; virtual void* RegisterMethod(const char* method) = 0; virtual void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline, - ::grpc_impl::CompletionQueue* cq, - void* tag) = 0; + CompletionQueue* cq, void* tag) = 0; virtual bool WaitForStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline) = 0; @@ -148,7 +144,7 @@ class ChannelInterface { // change (even though this is private and non-API) virtual internal::Call CreateCallInternal(const internal::RpcMethod& method, ClientContext* context, - ::grpc_impl::CompletionQueue* cq, + CompletionQueue* cq, size_t interceptor_pos) { return internal::Call(); } @@ -161,7 +157,7 @@ class ChannelInterface { // Returns nullptr (rather than being pure) since this is a post-1.0 method // and adding a new pure method to an interface would be a breaking change // (even though this is private and non-API) - virtual ::grpc_impl::CompletionQueue* CallbackCQ() { return nullptr; } + virtual CompletionQueue* CallbackCQ() { return nullptr; } }; } // namespace grpc diff --git a/include/grpcpp/impl/codegen/client_callback.h b/include/grpcpp/impl/codegen/client_callback.h index a00d49ef30c..836200b5915 100644 --- a/include/grpcpp/impl/codegen/client_callback.h +++ b/include/grpcpp/impl/codegen/client_callback.h @@ -36,6 +36,7 @@ class Channel; namespace grpc { class ClientContext; +class CompletionQueue; namespace internal { class RpcMethod; diff --git a/include/grpcpp/impl/codegen/client_context.h b/include/grpcpp/impl/codegen/client_context.h index 19e96d3589f..3b74a1367d1 100644 --- a/include/grpcpp/impl/codegen/client_context.h +++ b/include/grpcpp/impl/codegen/client_context.h @@ -65,6 +65,7 @@ class Channel; namespace grpc { class ChannelInterface; +class CompletionQueue; class CallCredentials; class ClientContext; diff --git a/include/grpcpp/impl/codegen/client_unary_call.h b/include/grpcpp/impl/codegen/client_unary_call.h index e0f692b1783..b9f8e1663f1 100644 --- a/include/grpcpp/impl/codegen/client_unary_call.h +++ b/include/grpcpp/impl/codegen/client_unary_call.h @@ -27,7 +27,9 @@ namespace grpc { +class Channel; class ClientContext; +class CompletionQueue; namespace internal { class RpcMethod; diff --git a/include/grpcpp/impl/codegen/completion_queue.h b/include/grpcpp/impl/codegen/completion_queue.h index edd1c2e97c8..508ab05815d 100644 --- a/include/grpcpp/impl/codegen/completion_queue.h +++ b/include/grpcpp/impl/codegen/completion_queue.h @@ -32,12 +32,385 @@ #ifndef GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H #define GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H -#include +#include +#include +#include +#include +#include +#include +struct grpc_completion_queue; + +namespace grpc_impl { + +class Channel; +class Server; +class ServerBuilder; +} // namespace grpc_impl namespace grpc { -typedef ::grpc_impl::CompletionQueue CompletionQueue; -typedef ::grpc_impl::ServerCompletionQueue ServerCompletionQueue; +template +class ClientReader; +template +class ClientWriter; +template +class ClientReaderWriter; +template +class ServerReader; +template +class ServerWriter; +namespace internal { +template +class ServerReaderWriterBody; +} // namespace internal + +class ChannelInterface; +class ClientContext; +class CompletionQueue; +class ServerContext; +class ServerInterface; + +namespace internal { +class CompletionQueueTag; +class RpcMethod; +template +class RpcMethodHandler; +template +class ClientStreamingHandler; +template +class ServerStreamingHandler; +template +class BidiStreamingHandler; +template +class TemplatedBidiStreamingHandler; +template +class ErrorMethodHandler; +template +class BlockingUnaryCallImpl; +template +class CallOpSet; +} // namespace internal + +extern CoreCodegenInterface* g_core_codegen_interface; + +/// A thin wrapper around \ref grpc_completion_queue (see \ref +/// src/core/lib/surface/completion_queue.h). +/// See \ref doc/cpp/perf_notes.md for notes on best practices for high +/// performance servers. +class CompletionQueue : private GrpcLibraryCodegen { + public: + /// Default constructor. Implicitly creates a \a grpc_completion_queue + /// instance. + CompletionQueue() + : CompletionQueue(grpc_completion_queue_attributes{ + GRPC_CQ_CURRENT_VERSION, GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, + nullptr}) {} + + /// Wrap \a take, taking ownership of the instance. + /// + /// \param take The completion queue instance to wrap. Ownership is taken. + explicit CompletionQueue(grpc_completion_queue* take); + + /// Destructor. Destroys the owned wrapped completion queue / instance. + ~CompletionQueue() { + g_core_codegen_interface->grpc_completion_queue_destroy(cq_); + } + + /// Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT. + enum NextStatus { + SHUTDOWN, ///< The completion queue has been shutdown and fully-drained + GOT_EVENT, ///< Got a new event; \a tag will be filled in with its + ///< associated value; \a ok indicating its success. + TIMEOUT ///< deadline was reached. + }; + + /// Read from the queue, blocking until an event is available or the queue is + /// shutting down. + /// + /// \param tag [out] Updated to point to the read event's tag. + /// \param ok [out] true if read a successful event, false otherwise. + /// + /// Note that each tag sent to the completion queue (through RPC operations + /// or alarms) will be delivered out of the completion queue by a call to + /// Next (or a related method), regardless of whether the operation succeeded + /// or not. Success here means that this operation completed in the normal + /// valid manner. + /// + /// Server-side RPC request: \a ok indicates that the RPC has indeed + /// been started. If it is false, the server has been Shutdown + /// before this particular call got matched to an incoming RPC. + /// + /// Client-side StartCall/RPC invocation: \a ok indicates that the RPC is + /// going to go to the wire. If it is false, it not going to the wire. This + /// would happen if the channel is either permanently broken or + /// transiently broken but with the fail-fast option. (Note that async unary + /// RPCs don't post a CQ tag at this point, nor do client-streaming + /// or bidi-streaming RPCs that have the initial metadata corked option set.) + /// + /// Client-side Write, Client-side WritesDone, Server-side Write, + /// Server-side Finish, Server-side SendInitialMetadata (which is + /// typically included in Write or Finish when not done explicitly): + /// \a ok means that the data/metadata/status/etc is going to go to the + /// wire. If it is false, it not going to the wire because the call + /// is already dead (i.e., canceled, deadline expired, other side + /// dropped the channel, etc). + /// + /// Client-side Read, Server-side Read, Client-side + /// RecvInitialMetadata (which is typically included in Read if not + /// done explicitly): \a ok indicates whether there is a valid message + /// that got read. If not, you know that there are certainly no more + /// messages that can ever be read from this stream. For the client-side + /// operations, this only happens because the call is dead. For the + /// server-sider operation, though, this could happen because the client + /// has done a WritesDone already. + /// + /// Client-side Finish: \a ok should always be true + /// + /// Server-side AsyncNotifyWhenDone: \a ok should always be true + /// + /// Alarm: \a ok is true if it expired, false if it was canceled + /// + /// \return true if got an event, false if the queue is fully drained and + /// shut down. + bool Next(void** tag, bool* ok) { + return (AsyncNextInternal(tag, ok, + g_core_codegen_interface->gpr_inf_future( + GPR_CLOCK_REALTIME)) != SHUTDOWN); + } + + /// Read from the queue, blocking up to \a deadline (or the queue's shutdown). + /// Both \a tag and \a ok are updated upon success (if an event is available + /// within the \a deadline). A \a tag points to an arbitrary location usually + /// employed to uniquely identify an event. + /// + /// \param tag [out] Upon sucess, updated to point to the event's tag. + /// \param ok [out] Upon sucess, true if a successful event, false otherwise + /// See documentation for CompletionQueue::Next for explanation of ok + /// \param deadline [in] How long to block in wait for an event. + /// + /// \return The type of event read. + template + NextStatus AsyncNext(void** tag, bool* ok, const T& deadline) { + TimePoint deadline_tp(deadline); + return AsyncNextInternal(tag, ok, deadline_tp.raw_time()); + } + + /// EXPERIMENTAL + /// First executes \a F, then reads from the queue, blocking up to + /// \a deadline (or the queue's shutdown). + /// Both \a tag and \a ok are updated upon success (if an event is available + /// within the \a deadline). A \a tag points to an arbitrary location usually + /// employed to uniquely identify an event. + /// + /// \param f [in] Function to execute before calling AsyncNext on this queue. + /// \param tag [out] Upon sucess, updated to point to the event's tag. + /// \param ok [out] Upon sucess, true if read a regular event, false + /// otherwise. + /// \param deadline [in] How long to block in wait for an event. + /// + /// \return The type of event read. + template + NextStatus DoThenAsyncNext(F&& f, void** tag, bool* ok, const T& deadline) { + CompletionQueueTLSCache cache = CompletionQueueTLSCache(this); + f(); + if (cache.Flush(tag, ok)) { + return GOT_EVENT; + } else { + return AsyncNext(tag, ok, deadline); + } + } + + /// Request the shutdown of the queue. + /// + /// \warning This method must be called at some point if this completion queue + /// is accessed with Next or AsyncNext. \a Next will not return false + /// until this method has been called and all pending tags have been drained. + /// (Likewise for \a AsyncNext returning \a NextStatus::SHUTDOWN .) + /// Only once either one of these methods does that (that is, once the queue + /// has been \em drained) can an instance of this class be destroyed. + /// Also note that applications must ensure that no work is enqueued on this + /// completion queue after this method is called. + void Shutdown(); + + /// Returns a \em raw pointer to the underlying \a grpc_completion_queue + /// instance. + /// + /// \warning Remember that the returned instance is owned. No transfer of + /// owership is performed. + grpc_completion_queue* cq() { return cq_; } + + protected: + /// Private constructor of CompletionQueue only visible to friend classes + CompletionQueue(const grpc_completion_queue_attributes& attributes) { + cq_ = g_core_codegen_interface->grpc_completion_queue_create( + g_core_codegen_interface->grpc_completion_queue_factory_lookup( + &attributes), + &attributes, NULL); + InitialAvalanching(); // reserve this for the future shutdown + } + + private: + // Friend synchronous wrappers so that they can access Pluck(), which is + // a semi-private API geared towards the synchronous implementation. + template + friend class ::grpc::ClientReader; + template + friend class ::grpc::ClientWriter; + template + friend class ::grpc::ClientReaderWriter; + template + friend class ::grpc::ServerReader; + template + friend class ::grpc::ServerWriter; + template + friend class ::grpc::internal::ServerReaderWriterBody; + template + friend class ::grpc::internal::RpcMethodHandler; + template + friend class ::grpc::internal::ClientStreamingHandler; + template + friend class ::grpc::internal::ServerStreamingHandler; + template + friend class ::grpc::internal::TemplatedBidiStreamingHandler; + template + friend class ::grpc::internal::ErrorMethodHandler; + friend class ::grpc_impl::Server; + friend class ::grpc::ServerContext; + friend class ::grpc::ServerInterface; + template + friend class ::grpc::internal::BlockingUnaryCallImpl; + + // Friends that need access to constructor for callback CQ + friend class ::grpc_impl::Channel; + + // For access to Register/CompleteAvalanching + template + friend class ::grpc::internal::CallOpSet; + + /// EXPERIMENTAL + /// Creates a Thread Local cache to store the first event + /// On this completion queue queued from this thread. Once + /// initialized, it must be flushed on the same thread. + class CompletionQueueTLSCache { + public: + CompletionQueueTLSCache(CompletionQueue* cq); + ~CompletionQueueTLSCache(); + bool Flush(void** tag, bool* ok); + + private: + CompletionQueue* cq_; + bool flushed_; + }; + + NextStatus AsyncNextInternal(void** tag, bool* ok, gpr_timespec deadline); + + /// Wraps \a grpc_completion_queue_pluck. + /// \warning Must not be mixed with calls to \a Next. + bool Pluck(internal::CompletionQueueTag* tag) { + auto deadline = + g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME); + while (true) { + auto ev = g_core_codegen_interface->grpc_completion_queue_pluck( + cq_, tag, deadline, nullptr); + bool ok = ev.success != 0; + void* ignored = tag; + if (tag->FinalizeResult(&ignored, &ok)) { + GPR_CODEGEN_ASSERT(ignored == tag); + return ok; + } + } + } + + /// Performs a single polling pluck on \a tag. + /// \warning Must not be mixed with calls to \a Next. + /// + /// TODO: sreek - This calls tag->FinalizeResult() even if the cq_ is already + /// shutdown. This is most likely a bug and if it is a bug, then change this + /// implementation to simple call the other TryPluck function with a zero + /// timeout. i.e: + /// TryPluck(tag, gpr_time_0(GPR_CLOCK_REALTIME)) + void TryPluck(internal::CompletionQueueTag* tag) { + auto deadline = g_core_codegen_interface->gpr_time_0(GPR_CLOCK_REALTIME); + auto ev = g_core_codegen_interface->grpc_completion_queue_pluck( + cq_, tag, deadline, nullptr); + if (ev.type == GRPC_QUEUE_TIMEOUT) return; + bool ok = ev.success != 0; + void* ignored = tag; + // the tag must be swallowed if using TryPluck + GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok)); + } + + /// Performs a single polling pluck on \a tag. Calls tag->FinalizeResult if + /// the pluck() was successful and returned the tag. + /// + /// This exects tag->FinalizeResult (if called) to return 'false' i.e expects + /// that the tag is internal not something that is returned to the user. + void TryPluck(internal::CompletionQueueTag* tag, gpr_timespec deadline) { + auto ev = g_core_codegen_interface->grpc_completion_queue_pluck( + cq_, tag, deadline, nullptr); + if (ev.type == GRPC_QUEUE_TIMEOUT || ev.type == GRPC_QUEUE_SHUTDOWN) { + return; + } + + bool ok = ev.success != 0; + void* ignored = tag; + GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok)); + } + + /// Manage state of avalanching operations : completion queue tags that + /// trigger other completion queue operations. The underlying core completion + /// queue should not really shutdown until all avalanching operations have + /// been finalized. Note that we maintain the requirement that an avalanche + /// registration must take place before CQ shutdown (which must be maintained + /// elsehwere) + void InitialAvalanching() { + gpr_atm_rel_store(&avalanches_in_flight_, static_cast(1)); + } + void RegisterAvalanching() { + gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_, + static_cast(1)); + } + void CompleteAvalanching() { + if (gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_, + static_cast(-1)) == 1) { + g_core_codegen_interface->grpc_completion_queue_shutdown(cq_); + } + } + + grpc_completion_queue* cq_; // owned + + gpr_atm avalanches_in_flight_; +}; + +/// A specific type of completion queue used by the processing of notifications +/// by servers. Instantiated by \a ServerBuilder. +class ServerCompletionQueue : public CompletionQueue { + public: + bool IsFrequentlyPolled() { return polling_type_ != GRPC_CQ_NON_LISTENING; } + + protected: + /// Default constructor + ServerCompletionQueue() : polling_type_(GRPC_CQ_DEFAULT_POLLING) {} + + private: + /// \param completion_type indicates whether this is a NEXT or CALLBACK + /// completion queue. + /// \param polling_type Informs the GRPC library about the type of polling + /// allowed on this completion queue. See grpc_cq_polling_type's description + /// in grpc_types.h for more details. + /// \param shutdown_cb is the shutdown callback used for CALLBACK api queues + ServerCompletionQueue(grpc_cq_completion_type completion_type, + grpc_cq_polling_type polling_type, + grpc_experimental_completion_queue_functor* shutdown_cb) + : CompletionQueue(grpc_completion_queue_attributes{ + GRPC_CQ_CURRENT_VERSION, completion_type, polling_type, + shutdown_cb}), + polling_type_(polling_type) {} + + grpc_cq_polling_type polling_type_; + friend class grpc_impl::ServerBuilder; + friend class grpc_impl::Server; +}; } // namespace grpc diff --git a/include/grpcpp/impl/codegen/completion_queue_impl.h b/include/grpcpp/impl/codegen/completion_queue_impl.h deleted file mode 100644 index 5435f2fa165..00000000000 --- a/include/grpcpp/impl/codegen/completion_queue_impl.h +++ /dev/null @@ -1,422 +0,0 @@ -/* - * - * Copyright 2015-2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/// A completion queue implements a concurrent producer-consumer queue, with -/// two main API-exposed methods: \a Next and \a AsyncNext. These -/// methods are the essential component of the gRPC C++ asynchronous API. -/// There is also a \a Shutdown method to indicate that a given completion queue -/// will no longer have regular events. This must be called before the -/// completion queue is destroyed. -/// All completion queue APIs are thread-safe and may be used concurrently with -/// any other completion queue API invocation; it is acceptable to have -/// multiple threads calling \a Next or \a AsyncNext on the same or different -/// completion queues, or to call these methods concurrently with a \a Shutdown -/// elsewhere. -/// \remark{All other API calls on completion queue should be completed before -/// a completion queue destructor is called.} -#ifndef GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_IMPL_H -#define GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_IMPL_H - -#include -#include -#include -#include -#include -#include - -struct grpc_completion_queue; - -namespace grpc_impl { - -class Channel; -class Server; -class ServerBuilder; -} // namespace grpc_impl -namespace grpc { - -template -class ClientReader; -template -class ClientWriter; -template -class ClientReaderWriter; -template -class ServerReader; -template -class ServerWriter; -namespace internal { -template -class ServerReaderWriterBody; -} // namespace internal - -class ChannelInterface; -class ClientContext; -class ServerContext; -class ServerInterface; - -namespace internal { -class CompletionQueueTag; -class RpcMethod; -template -class RpcMethodHandler; -template -class ClientStreamingHandler; -template -class ServerStreamingHandler; -template -class BidiStreamingHandler; -template -class TemplatedBidiStreamingHandler; -template -class ErrorMethodHandler; -template -class BlockingUnaryCallImpl; -template -class CallOpSet; -} // namespace internal - -extern CoreCodegenInterface* g_core_codegen_interface; - -} // namespace grpc - -namespace grpc_impl { - -/// A thin wrapper around \ref grpc_completion_queue (see \ref -/// src/core/lib/surface/completion_queue.h). -/// See \ref doc/cpp/perf_notes.md for notes on best practices for high -/// performance servers. -class CompletionQueue : private ::grpc::GrpcLibraryCodegen { - public: - /// Default constructor. Implicitly creates a \a grpc_completion_queue - /// instance. - CompletionQueue() - : CompletionQueue(grpc_completion_queue_attributes{ - GRPC_CQ_CURRENT_VERSION, GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING, - nullptr}) {} - - /// Wrap \a take, taking ownership of the instance. - /// - /// \param take The completion queue instance to wrap. Ownership is taken. - explicit CompletionQueue(grpc_completion_queue* take); - - /// Destructor. Destroys the owned wrapped completion queue / instance. - ~CompletionQueue() { - ::grpc::g_core_codegen_interface->grpc_completion_queue_destroy(cq_); - } - - /// Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT. - enum NextStatus { - SHUTDOWN, ///< The completion queue has been shutdown and fully-drained - GOT_EVENT, ///< Got a new event; \a tag will be filled in with its - ///< associated value; \a ok indicating its success. - TIMEOUT ///< deadline was reached. - }; - - /// Read from the queue, blocking until an event is available or the queue is - /// shutting down. - /// - /// \param tag [out] Updated to point to the read event's tag. - /// \param ok [out] true if read a successful event, false otherwise. - /// - /// Note that each tag sent to the completion queue (through RPC operations - /// or alarms) will be delivered out of the completion queue by a call to - /// Next (or a related method), regardless of whether the operation succeeded - /// or not. Success here means that this operation completed in the normal - /// valid manner. - /// - /// Server-side RPC request: \a ok indicates that the RPC has indeed - /// been started. If it is false, the server has been Shutdown - /// before this particular call got matched to an incoming RPC. - /// - /// Client-side StartCall/RPC invocation: \a ok indicates that the RPC is - /// going to go to the wire. If it is false, it not going to the wire. This - /// would happen if the channel is either permanently broken or - /// transiently broken but with the fail-fast option. (Note that async unary - /// RPCs don't post a CQ tag at this point, nor do client-streaming - /// or bidi-streaming RPCs that have the initial metadata corked option set.) - /// - /// Client-side Write, Client-side WritesDone, Server-side Write, - /// Server-side Finish, Server-side SendInitialMetadata (which is - /// typically included in Write or Finish when not done explicitly): - /// \a ok means that the data/metadata/status/etc is going to go to the - /// wire. If it is false, it not going to the wire because the call - /// is already dead (i.e., canceled, deadline expired, other side - /// dropped the channel, etc). - /// - /// Client-side Read, Server-side Read, Client-side - /// RecvInitialMetadata (which is typically included in Read if not - /// done explicitly): \a ok indicates whether there is a valid message - /// that got read. If not, you know that there are certainly no more - /// messages that can ever be read from this stream. For the client-side - /// operations, this only happens because the call is dead. For the - /// server-sider operation, though, this could happen because the client - /// has done a WritesDone already. - /// - /// Client-side Finish: \a ok should always be true - /// - /// Server-side AsyncNotifyWhenDone: \a ok should always be true - /// - /// Alarm: \a ok is true if it expired, false if it was canceled - /// - /// \return true if got an event, false if the queue is fully drained and - /// shut down. - bool Next(void** tag, bool* ok) { - return (AsyncNextInternal(tag, ok, - ::grpc::g_core_codegen_interface->gpr_inf_future( - GPR_CLOCK_REALTIME)) != SHUTDOWN); - } - - /// Read from the queue, blocking up to \a deadline (or the queue's shutdown). - /// Both \a tag and \a ok are updated upon success (if an event is available - /// within the \a deadline). A \a tag points to an arbitrary location usually - /// employed to uniquely identify an event. - /// - /// \param tag [out] Upon sucess, updated to point to the event's tag. - /// \param ok [out] Upon sucess, true if a successful event, false otherwise - /// See documentation for CompletionQueue::Next for explanation of ok - /// \param deadline [in] How long to block in wait for an event. - /// - /// \return The type of event read. - template - NextStatus AsyncNext(void** tag, bool* ok, const T& deadline) { - ::grpc::TimePoint deadline_tp(deadline); - return AsyncNextInternal(tag, ok, deadline_tp.raw_time()); - } - - /// EXPERIMENTAL - /// First executes \a F, then reads from the queue, blocking up to - /// \a deadline (or the queue's shutdown). - /// Both \a tag and \a ok are updated upon success (if an event is available - /// within the \a deadline). A \a tag points to an arbitrary location usually - /// employed to uniquely identify an event. - /// - /// \param f [in] Function to execute before calling AsyncNext on this queue. - /// \param tag [out] Upon sucess, updated to point to the event's tag. - /// \param ok [out] Upon sucess, true if read a regular event, false - /// otherwise. - /// \param deadline [in] How long to block in wait for an event. - /// - /// \return The type of event read. - template - NextStatus DoThenAsyncNext(F&& f, void** tag, bool* ok, const T& deadline) { - CompletionQueueTLSCache cache = CompletionQueueTLSCache(this); - f(); - if (cache.Flush(tag, ok)) { - return GOT_EVENT; - } else { - return AsyncNext(tag, ok, deadline); - } - } - - /// Request the shutdown of the queue. - /// - /// \warning This method must be called at some point if this completion queue - /// is accessed with Next or AsyncNext. \a Next will not return false - /// until this method has been called and all pending tags have been drained. - /// (Likewise for \a AsyncNext returning \a NextStatus::SHUTDOWN .) - /// Only once either one of these methods does that (that is, once the queue - /// has been \em drained) can an instance of this class be destroyed. - /// Also note that applications must ensure that no work is enqueued on this - /// completion queue after this method is called. - void Shutdown(); - - /// Returns a \em raw pointer to the underlying \a grpc_completion_queue - /// instance. - /// - /// \warning Remember that the returned instance is owned. No transfer of - /// owership is performed. - grpc_completion_queue* cq() { return cq_; } - - protected: - /// Private constructor of CompletionQueue only visible to friend classes - CompletionQueue(const grpc_completion_queue_attributes& attributes) { - cq_ = ::grpc::g_core_codegen_interface->grpc_completion_queue_create( - ::grpc::g_core_codegen_interface->grpc_completion_queue_factory_lookup( - &attributes), - &attributes, NULL); - InitialAvalanching(); // reserve this for the future shutdown - } - - private: - // Friend synchronous wrappers so that they can access Pluck(), which is - // a semi-private API geared towards the synchronous implementation. - template - friend class ::grpc::ClientReader; - template - friend class ::grpc::ClientWriter; - template - friend class ::grpc::ClientReaderWriter; - template - friend class ::grpc::ServerReader; - template - friend class ::grpc::ServerWriter; - template - friend class ::grpc::internal::ServerReaderWriterBody; - template - friend class ::grpc::internal::RpcMethodHandler; - template - friend class ::grpc::internal::ClientStreamingHandler; - template - friend class ::grpc::internal::ServerStreamingHandler; - template - friend class ::grpc::internal::TemplatedBidiStreamingHandler; - template <::grpc::StatusCode code> - friend class ::grpc::internal::ErrorMethodHandler; - friend class ::grpc_impl::Server; - friend class ::grpc::ServerContext; - friend class ::grpc::ServerInterface; - template - friend class ::grpc::internal::BlockingUnaryCallImpl; - - // Friends that need access to constructor for callback CQ - friend class ::grpc_impl::Channel; - - // For access to Register/CompleteAvalanching - template - friend class ::grpc::internal::CallOpSet; - - /// EXPERIMENTAL - /// Creates a Thread Local cache to store the first event - /// On this completion queue queued from this thread. Once - /// initialized, it must be flushed on the same thread. - class CompletionQueueTLSCache { - public: - CompletionQueueTLSCache(CompletionQueue* cq); - ~CompletionQueueTLSCache(); - bool Flush(void** tag, bool* ok); - - private: - CompletionQueue* cq_; - bool flushed_; - }; - - NextStatus AsyncNextInternal(void** tag, bool* ok, gpr_timespec deadline); - - /// Wraps \a grpc_completion_queue_pluck. - /// \warning Must not be mixed with calls to \a Next. - bool Pluck(::grpc::internal::CompletionQueueTag* tag) { - auto deadline = - ::grpc::g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME); - while (true) { - auto ev = ::grpc::g_core_codegen_interface->grpc_completion_queue_pluck( - cq_, tag, deadline, nullptr); - bool ok = ev.success != 0; - void* ignored = tag; - if (tag->FinalizeResult(&ignored, &ok)) { - GPR_CODEGEN_ASSERT(ignored == tag); - return ok; - } - } - } - - /// Performs a single polling pluck on \a tag. - /// \warning Must not be mixed with calls to \a Next. - /// - /// TODO: sreek - This calls tag->FinalizeResult() even if the cq_ is already - /// shutdown. This is most likely a bug and if it is a bug, then change this - /// implementation to simple call the other TryPluck function with a zero - /// timeout. i.e: - /// TryPluck(tag, gpr_time_0(GPR_CLOCK_REALTIME)) - void TryPluck(::grpc::internal::CompletionQueueTag* tag) { - auto deadline = - ::grpc::g_core_codegen_interface->gpr_time_0(GPR_CLOCK_REALTIME); - auto ev = ::grpc::g_core_codegen_interface->grpc_completion_queue_pluck( - cq_, tag, deadline, nullptr); - if (ev.type == GRPC_QUEUE_TIMEOUT) return; - bool ok = ev.success != 0; - void* ignored = tag; - // the tag must be swallowed if using TryPluck - GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok)); - } - - /// Performs a single polling pluck on \a tag. Calls tag->FinalizeResult if - /// the pluck() was successful and returned the tag. - /// - /// This exects tag->FinalizeResult (if called) to return 'false' i.e expects - /// that the tag is internal not something that is returned to the user. - void TryPluck(::grpc::internal::CompletionQueueTag* tag, - gpr_timespec deadline) { - auto ev = ::grpc::g_core_codegen_interface->grpc_completion_queue_pluck( - cq_, tag, deadline, nullptr); - if (ev.type == GRPC_QUEUE_TIMEOUT || ev.type == GRPC_QUEUE_SHUTDOWN) { - return; - } - - bool ok = ev.success != 0; - void* ignored = tag; - GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok)); - } - - /// Manage state of avalanching operations : completion queue tags that - /// trigger other completion queue operations. The underlying core completion - /// queue should not really shutdown until all avalanching operations have - /// been finalized. Note that we maintain the requirement that an avalanche - /// registration must take place before CQ shutdown (which must be maintained - /// elsehwere) - void InitialAvalanching() { - gpr_atm_rel_store(&avalanches_in_flight_, static_cast(1)); - } - void RegisterAvalanching() { - gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_, - static_cast(1)); - } - void CompleteAvalanching() { - if (gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_, - static_cast(-1)) == 1) { - ::grpc::g_core_codegen_interface->grpc_completion_queue_shutdown(cq_); - } - } - - grpc_completion_queue* cq_; // owned - - gpr_atm avalanches_in_flight_; -}; - -/// A specific type of completion queue used by the processing of notifications -/// by servers. Instantiated by \a ServerBuilder. -class ServerCompletionQueue : public CompletionQueue { - public: - bool IsFrequentlyPolled() { return polling_type_ != GRPC_CQ_NON_LISTENING; } - - protected: - /// Default constructor - ServerCompletionQueue() : polling_type_(GRPC_CQ_DEFAULT_POLLING) {} - - private: - /// \param completion_type indicates whether this is a NEXT or CALLBACK - /// completion queue. - /// \param polling_type Informs the GRPC library about the type of polling - /// allowed on this completion queue. See grpc_cq_polling_type's description - /// in grpc_types.h for more details. - /// \param shutdown_cb is the shutdown callback used for CALLBACK api queues - ServerCompletionQueue(grpc_cq_completion_type completion_type, - grpc_cq_polling_type polling_type, - grpc_experimental_completion_queue_functor* shutdown_cb) - : CompletionQueue(grpc_completion_queue_attributes{ - GRPC_CQ_CURRENT_VERSION, completion_type, polling_type, - shutdown_cb}), - polling_type_(polling_type) {} - - grpc_cq_polling_type polling_type_; - friend class ::grpc_impl::ServerBuilder; - friend class ::grpc_impl::Server; -}; - -} // namespace grpc_impl - -#endif // GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_IMPL_H diff --git a/include/grpcpp/impl/codegen/intercepted_channel.h b/include/grpcpp/impl/codegen/intercepted_channel.h index cd0fcc06753..5255a6d1472 100644 --- a/include/grpcpp/impl/codegen/intercepted_channel.h +++ b/include/grpcpp/impl/codegen/intercepted_channel.h @@ -21,10 +21,6 @@ #include -namespace grpc_impl { -class CompletionQueue; -} - namespace grpc { namespace internal { @@ -50,7 +46,7 @@ class InterceptedChannel : public ChannelInterface { : channel_(channel), interceptor_pos_(pos) {} Call CreateCall(const RpcMethod& method, ClientContext* context, - ::grpc_impl::CompletionQueue* cq) override { + CompletionQueue* cq) override { return channel_->CreateCallInternal(method, context, cq, interceptor_pos_); } @@ -62,8 +58,7 @@ class InterceptedChannel : public ChannelInterface { } void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, - gpr_timespec deadline, - ::grpc_impl::CompletionQueue* cq, + gpr_timespec deadline, CompletionQueue* cq, void* tag) override { return channel_->NotifyOnStateChangeImpl(last_observed, deadline, cq, tag); } @@ -72,9 +67,7 @@ class InterceptedChannel : public ChannelInterface { return channel_->WaitForStateChangeImpl(last_observed, deadline); } - ::grpc_impl::CompletionQueue* CallbackCQ() override { - return channel_->CallbackCQ(); - } + CompletionQueue* CallbackCQ() override { return channel_->CallbackCQ(); } ChannelInterface* channel_; size_t interceptor_pos_; diff --git a/include/grpcpp/impl/codegen/server_context.h b/include/grpcpp/impl/codegen/server_context.h index fe5a0097d0a..f65598db41f 100644 --- a/include/grpcpp/impl/codegen/server_context.h +++ b/include/grpcpp/impl/codegen/server_context.h @@ -42,12 +42,13 @@ struct grpc_call; struct census_context; namespace grpc_impl { -class CompletionQueue; + class Server; } // namespace grpc_impl namespace grpc { class ClientContext; class GenericServerContext; +class CompletionQueue; class ServerInterface; template class ServerAsyncReader; @@ -89,7 +90,6 @@ class Call; class ServerReactor; } // namespace internal -class ServerInterface; namespace testing { class InteropServerContextInspector; class ServerContextTestSpouse; @@ -354,7 +354,7 @@ class ServerContext { gpr_timespec deadline_; grpc_call* call_; - ::grpc_impl::CompletionQueue* cq_; + CompletionQueue* cq_; bool sent_initial_metadata_; mutable std::shared_ptr auth_context_; mutable internal::MetadataMap client_metadata_; diff --git a/include/grpcpp/impl/codegen/server_interface.h b/include/grpcpp/impl/codegen/server_interface.h index 9e96a66c8af..9299fdb20e1 100644 --- a/include/grpcpp/impl/codegen/server_interface.h +++ b/include/grpcpp/impl/codegen/server_interface.h @@ -29,14 +29,14 @@ #include namespace grpc_impl { -class CompletionQueue; -class ServerCompletionQueue; +class Channel; class ServerCredentials; } // namespace grpc_impl namespace grpc { class AsyncGenericService; class GenericServerContext; +class ServerCompletionQueue; class ServerContext; class Service; @@ -160,8 +160,7 @@ class ServerInterface : public internal::CallHook { /// caller is required to keep all completion queues live until the server is /// destroyed. /// \param num_cqs How many completion queues does \a cqs hold. - virtual void Start(::grpc_impl::ServerCompletionQueue** cqs, - size_t num_cqs) = 0; + virtual void Start(ServerCompletionQueue** cqs, size_t num_cqs) = 0; virtual void ShutdownInternal(gpr_timespec deadline) = 0; @@ -176,9 +175,9 @@ class ServerInterface : public internal::CallHook { public: BaseAsyncRequest(ServerInterface* server, ServerContext* context, internal::ServerAsyncStreamingInterface* stream, - ::grpc_impl::CompletionQueue* call_cq, - ::grpc_impl::ServerCompletionQueue* notification_cq, - void* tag, bool delete_on_finalize); + CompletionQueue* call_cq, + ServerCompletionQueue* notification_cq, void* tag, + bool delete_on_finalize); virtual ~BaseAsyncRequest(); bool FinalizeResult(void** tag, bool* status) override; @@ -190,8 +189,8 @@ class ServerInterface : public internal::CallHook { ServerInterface* const server_; ServerContext* const context_; internal::ServerAsyncStreamingInterface* const stream_; - ::grpc_impl::CompletionQueue* const call_cq_; - ::grpc_impl::ServerCompletionQueue* const notification_cq_; + CompletionQueue* const call_cq_; + ServerCompletionQueue* const notification_cq_; void* const tag_; const bool delete_on_finalize_; grpc_call* call_; @@ -205,17 +204,16 @@ class ServerInterface : public internal::CallHook { public: RegisteredAsyncRequest(ServerInterface* server, ServerContext* context, internal::ServerAsyncStreamingInterface* stream, - ::grpc_impl::CompletionQueue* call_cq, - ::grpc_impl::ServerCompletionQueue* notification_cq, - void* tag, const char* name, - internal::RpcMethod::RpcType type); + CompletionQueue* call_cq, + ServerCompletionQueue* notification_cq, void* tag, + const char* name, internal::RpcMethod::RpcType type); virtual bool FinalizeResult(void** tag, bool* status) override { /* If we are done intercepting, then there is nothing more for us to do */ if (done_intercepting_) { return BaseAsyncRequest::FinalizeResult(tag, status); } - call_wrapper_ = ::grpc::internal::Call( + call_wrapper_ = internal::Call( call_, server_, call_cq_, server_->max_receive_message_size(), context_->set_server_rpc_info(name_, type_, *server_->interceptor_creators())); @@ -224,7 +222,7 @@ class ServerInterface : public internal::CallHook { protected: void IssueRequest(void* registered_method, grpc_byte_buffer** payload, - ::grpc_impl::ServerCompletionQueue* notification_cq); + ServerCompletionQueue* notification_cq); const char* name_; const internal::RpcMethod::RpcType type_; }; @@ -234,9 +232,8 @@ class ServerInterface : public internal::CallHook { NoPayloadAsyncRequest(internal::RpcServiceMethod* registered_method, ServerInterface* server, ServerContext* context, internal::ServerAsyncStreamingInterface* stream, - ::grpc_impl::CompletionQueue* call_cq, - ::grpc_impl::ServerCompletionQueue* notification_cq, - void* tag) + CompletionQueue* call_cq, + ServerCompletionQueue* notification_cq, void* tag) : RegisteredAsyncRequest( server, context, stream, call_cq, notification_cq, tag, registered_method->name(), registered_method->method_type()) { @@ -252,9 +249,9 @@ class ServerInterface : public internal::CallHook { PayloadAsyncRequest(internal::RpcServiceMethod* registered_method, ServerInterface* server, ServerContext* context, internal::ServerAsyncStreamingInterface* stream, - ::grpc_impl::CompletionQueue* call_cq, - ::grpc_impl::ServerCompletionQueue* notification_cq, - void* tag, Message* request) + CompletionQueue* call_cq, + ServerCompletionQueue* notification_cq, void* tag, + Message* request) : RegisteredAsyncRequest( server, context, stream, call_cq, notification_cq, tag, registered_method->name(), registered_method->method_type()), @@ -309,9 +306,9 @@ class ServerInterface : public internal::CallHook { ServerInterface* const server_; ServerContext* const context_; internal::ServerAsyncStreamingInterface* const stream_; - ::grpc_impl::CompletionQueue* const call_cq_; + CompletionQueue* const call_cq_; - ::grpc_impl::ServerCompletionQueue* const notification_cq_; + ServerCompletionQueue* const notification_cq_; void* const tag_; Message* const request_; ByteBuffer payload_; @@ -321,9 +318,9 @@ class ServerInterface : public internal::CallHook { public: GenericAsyncRequest(ServerInterface* server, GenericServerContext* context, internal::ServerAsyncStreamingInterface* stream, - ::grpc_impl::CompletionQueue* call_cq, - ::grpc_impl::ServerCompletionQueue* notification_cq, - void* tag, bool delete_on_finalize); + CompletionQueue* call_cq, + ServerCompletionQueue* notification_cq, void* tag, + bool delete_on_finalize); bool FinalizeResult(void** tag, bool* status) override; @@ -335,9 +332,9 @@ class ServerInterface : public internal::CallHook { void RequestAsyncCall(internal::RpcServiceMethod* method, ServerContext* context, internal::ServerAsyncStreamingInterface* stream, - ::grpc_impl::CompletionQueue* call_cq, - ::grpc_impl::ServerCompletionQueue* notification_cq, - void* tag, Message* message) { + CompletionQueue* call_cq, + ServerCompletionQueue* notification_cq, void* tag, + Message* message) { GPR_CODEGEN_ASSERT(method); new PayloadAsyncRequest(method, this, context, stream, call_cq, notification_cq, tag, message); @@ -346,19 +343,18 @@ class ServerInterface : public internal::CallHook { void RequestAsyncCall(internal::RpcServiceMethod* method, ServerContext* context, internal::ServerAsyncStreamingInterface* stream, - ::grpc_impl::CompletionQueue* call_cq, - ::grpc_impl::ServerCompletionQueue* notification_cq, - void* tag) { + CompletionQueue* call_cq, + ServerCompletionQueue* notification_cq, void* tag) { GPR_CODEGEN_ASSERT(method); new NoPayloadAsyncRequest(method, this, context, stream, call_cq, notification_cq, tag); } - void RequestAsyncGenericCall( - GenericServerContext* context, - internal::ServerAsyncStreamingInterface* stream, - ::grpc_impl::CompletionQueue* call_cq, - ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag) { + void RequestAsyncGenericCall(GenericServerContext* context, + internal::ServerAsyncStreamingInterface* stream, + CompletionQueue* call_cq, + ServerCompletionQueue* notification_cq, + void* tag) { new GenericAsyncRequest(this, context, stream, call_cq, notification_cq, tag, true); } @@ -383,7 +379,7 @@ class ServerInterface : public internal::CallHook { // Returns nullptr (rather than being pure) since this is a post-1.0 method // and adding a new pure method to an interface would be a breaking change // (even though this is private and non-API) - virtual ::grpc_impl::CompletionQueue* CallbackCQ() { return nullptr; } + virtual CompletionQueue* CallbackCQ() { return nullptr; } }; } // namespace grpc diff --git a/include/grpcpp/impl/codegen/service_type.h b/include/grpcpp/impl/codegen/service_type.h index 0e0fc8d5aa7..1d94abe12dd 100644 --- a/include/grpcpp/impl/codegen/service_type.h +++ b/include/grpcpp/impl/codegen/service_type.h @@ -32,7 +32,9 @@ class Server; } // namespace grpc_impl namespace grpc { +class CompletionQueue; class ServerInterface; +class ServerCompletionQueue; class ServerContext; namespace internal { diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h index d9ec7c42f3d..89c4eba1d95 100644 --- a/include/grpcpp/server_builder.h +++ b/include/grpcpp/server_builder.h @@ -21,6 +21,13 @@ #include +namespace grpc_impl { + +class Server; +class ServerCredentials; +class ResourceQuota; +} // namespace grpc_impl + namespace grpc { typedef ::grpc_impl::ServerBuilder ServerBuilder; diff --git a/include/grpcpp/server_builder_impl.h b/include/grpcpp/server_builder_impl.h index be21ed024ea..f7624deba5f 100644 --- a/include/grpcpp/server_builder_impl.h +++ b/include/grpcpp/server_builder_impl.h @@ -38,14 +38,14 @@ struct grpc_resource_quota; namespace grpc_impl { -class CompletionQueue; class ResourceQuota; -class ServerCompletionQueue; class ServerCredentials; } // namespace grpc_impl namespace grpc { class AsyncGenericService; +class CompletionQueue; +class ServerCompletionQueue; class Service; namespace testing { diff --git a/src/compiler/cpp_generator.cc b/src/compiler/cpp_generator.cc index 19837d2c264..6b53b3f64ce 100644 --- a/src/compiler/cpp_generator.cc +++ b/src/compiler/cpp_generator.cc @@ -147,10 +147,10 @@ grpc::string GetHeaderIncludes(grpc_generator::File* file, printer->Print(vars, "\n"); printer->Print(vars, "namespace grpc_impl {\n"); printer->Print(vars, "class Channel;\n"); - printer->Print(vars, "class CompletionQueue;\n"); - printer->Print(vars, "class ServerCompletionQueue;\n"); printer->Print(vars, "} // namespace grpc_impl\n\n"); printer->Print(vars, "namespace grpc {\n"); + printer->Print(vars, "class CompletionQueue;\n"); + printer->Print(vars, "class ServerCompletionQueue;\n"); printer->Print(vars, "class ServerContext;\n"); printer->Print(vars, "} // namespace grpc\n\n"); diff --git a/src/cpp/common/completion_queue_cc.cc b/src/cpp/common/completion_queue_cc.cc index 43c2eee96f8..4bb3bcbd8b6 100644 --- a/src/cpp/common/completion_queue_cc.cc +++ b/src/cpp/common/completion_queue_cc.cc @@ -24,9 +24,9 @@ #include #include -namespace grpc_impl { +namespace grpc { -static ::grpc::internal::GrpcLibraryInitializer g_gli_initializer; +static internal::GrpcLibraryInitializer g_gli_initializer; // 'CompletionQueue' constructor can safely call GrpcLibraryCodegen(false) here // i.e not have GrpcLibraryCodegen call grpc_init(). This is because, to create @@ -52,8 +52,7 @@ CompletionQueue::NextStatus CompletionQueue::AsyncNextInternal( case GRPC_QUEUE_SHUTDOWN: return SHUTDOWN; case GRPC_OP_COMPLETE: - auto core_cq_tag = - static_cast<::grpc::internal::CompletionQueueTag*>(ev.tag); + auto core_cq_tag = static_cast(ev.tag); *ok = ev.success != 0; *tag = core_cq_tag; if (core_cq_tag->FinalizeResult(tag, ok)) { @@ -80,8 +79,7 @@ bool CompletionQueue::CompletionQueueTLSCache::Flush(void** tag, bool* ok) { flushed_ = true; if (grpc_completion_queue_thread_local_cache_flush(cq_->cq_, &res_tag, &res)) { - auto core_cq_tag = - static_cast<::grpc::internal::CompletionQueueTag*>(res_tag); + auto core_cq_tag = static_cast(res_tag); *ok = res == 1; if (core_cq_tag->FinalizeResult(tag, ok)) { return true; @@ -90,4 +88,4 @@ bool CompletionQueue::CompletionQueueTLSCache::Flush(void** tag, bool* ok) { return false; } -} // namespace grpc_impl +} // namespace grpc diff --git a/test/cpp/codegen/compiler_test_golden b/test/cpp/codegen/compiler_test_golden index 5dc00a85c3a..9202585535b 100644 --- a/test/cpp/codegen/compiler_test_golden +++ b/test/cpp/codegen/compiler_test_golden @@ -42,11 +42,11 @@ namespace grpc_impl { class Channel; -class CompletionQueue; -class ServerCompletionQueue; } // namespace grpc_impl namespace grpc { +class CompletionQueue; +class ServerCompletionQueue; class ServerContext; } // namespace grpc diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 885c1427247..8659a7d7381 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -959,7 +959,6 @@ include/grpcpp/impl/codegen/client_context.h \ include/grpcpp/impl/codegen/client_interceptor.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ -include/grpcpp/impl/codegen/completion_queue_impl.h \ include/grpcpp/impl/codegen/completion_queue_tag.h \ include/grpcpp/impl/codegen/config.h \ include/grpcpp/impl/codegen/config_protobuf.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index e87914569ce..65369aa0e43 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -960,7 +960,6 @@ include/grpcpp/impl/codegen/client_context.h \ include/grpcpp/impl/codegen/client_interceptor.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ -include/grpcpp/impl/codegen/completion_queue_impl.h \ include/grpcpp/impl/codegen/completion_queue_tag.h \ include/grpcpp/impl/codegen/config.h \ include/grpcpp/impl/codegen/config_protobuf.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 1782e18eb1d..27b2909a690 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -9909,7 +9909,6 @@ "include/grpcpp/impl/codegen/client_interceptor.h", "include/grpcpp/impl/codegen/client_unary_call.h", "include/grpcpp/impl/codegen/completion_queue.h", - "include/grpcpp/impl/codegen/completion_queue_impl.h", "include/grpcpp/impl/codegen/completion_queue_tag.h", "include/grpcpp/impl/codegen/config.h", "include/grpcpp/impl/codegen/core_codegen_interface.h", @@ -9986,7 +9985,6 @@ "include/grpcpp/impl/codegen/client_interceptor.h", "include/grpcpp/impl/codegen/client_unary_call.h", "include/grpcpp/impl/codegen/completion_queue.h", - "include/grpcpp/impl/codegen/completion_queue_impl.h", "include/grpcpp/impl/codegen/completion_queue_tag.h", "include/grpcpp/impl/codegen/config.h", "include/grpcpp/impl/codegen/core_codegen_interface.h", From 41c6cba9f55b8104a9f5068e5418f689e00e6f65 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Mon, 8 Apr 2019 09:03:13 -0700 Subject: [PATCH 234/242] Make sure that OnCancel happens after OnStarted --- include/grpcpp/impl/codegen/server_callback.h | 38 +++++++++ src/cpp/server/server_context.cc | 11 ++- test/cpp/end2end/end2end_test.cc | 8 +- test/cpp/end2end/test_service_impl.cc | 79 +++++++++++-------- 4 files changed, 97 insertions(+), 39 deletions(-) diff --git a/include/grpcpp/impl/codegen/server_callback.h b/include/grpcpp/impl/codegen/server_callback.h index 4c6b189214e..ce27b156283 100644 --- a/include/grpcpp/impl/codegen/server_callback.h +++ b/include/grpcpp/impl/codegen/server_callback.h @@ -37,11 +37,43 @@ namespace grpc { // Declare base class of all reactors as internal namespace internal { +// Forward declarations +template +class CallbackClientStreamingHandler; +template +class CallbackServerStreamingHandler; +template +class CallbackBidiHandler; + class ServerReactor { public: virtual ~ServerReactor() = default; virtual void OnDone() = 0; virtual void OnCancel() = 0; + + private: + friend class ::grpc::ServerContext; + template + friend class CallbackClientStreamingHandler; + template + friend class CallbackServerStreamingHandler; + template + friend class CallbackBidiHandler; + + // The ServerReactor is responsible for tracking when it is safe to call + // OnCancel. This function should not be called until after OnStarted is done + // and the RPC has completed with a cancellation. This is tracked by counting + // how many of these conditions have been met and calling OnCancel when none + // remain unmet. + + void MaybeCallOnCancel() { + if (on_cancel_conditions_remaining_.fetch_sub( + 1, std::memory_order_acq_rel) == 1) { + OnCancel(); + } + } + + std::atomic_int on_cancel_conditions_remaining_{2}; }; } // namespace internal @@ -590,6 +622,8 @@ class CallbackClientStreamingHandler : public MethodHandler { reader->BindReactor(reactor); reactor->OnStarted(param.server_context, reader->response()); + // The earliest that OnCancel can be called is after OnStarted is done. + reactor->MaybeCallOnCancel(); reader->MaybeDone(); } @@ -732,6 +766,8 @@ class CallbackServerStreamingHandler : public MethodHandler { std::move(param.call_requester), reactor); writer->BindReactor(reactor); reactor->OnStarted(param.server_context, writer->request()); + // The earliest that OnCancel can be called is after OnStarted is done. + reactor->MaybeCallOnCancel(); writer->MaybeDone(); } @@ -908,6 +944,8 @@ class CallbackBidiHandler : public MethodHandler { stream->BindReactor(reactor); reactor->OnStarted(param.server_context); + // The earliest that OnCancel can be called is after OnStarted is done. + reactor->MaybeCallOnCancel(); stream->MaybeDone(); } diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc index 70c5cd8861e..eced89d1a79 100644 --- a/src/cpp/server/server_context.cc +++ b/src/cpp/server/server_context.cc @@ -210,17 +210,20 @@ bool ServerContext::CompletionOp::FinalizeResult(void** tag, bool* status) { bool call_cancel = (cancelled_ != 0); // If it's a unary cancel callback, call it under the lock so that it doesn't - // race with ClearCancelCallback + // race with ClearCancelCallback. Although we don't normally call callbacks + // under a lock, this is a special case since the user needs a guarantee that + // the callback won't issue or run after ClearCancelCallback has returned. + // This requirement imposes certain restrictions on the callback, documented + // in the API comments of SetCancelCallback. if (cancel_callback_) { cancel_callback_(); } - // Release the lock since we are going to be calling a callback and - // interceptors now + // Release the lock since we may call a callback and interceptors now. lock.Unlock(); if (call_cancel && reactor_ != nullptr) { - reactor_->OnCancel(); + reactor_->MaybeCallOnCancel(); } /* Add interception point and run through interceptors */ interceptor_methods_.AddInterceptionHookPoint( diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 40023c72f62..fb951fd44e6 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -1420,18 +1420,18 @@ TEST_P(End2endTest, DelayedRpcLateCanceledUsingCancelCallback) { EchoResponse response; request.set_message("Hello"); request.mutable_param()->set_skip_cancelled_check(true); - // Let server sleep for 80 ms first to give the cancellation a chance. - // This is split into 40 ms to start the cancel and 40 ms extra time for + // Let server sleep for 200 ms first to give the cancellation a chance. + // This is split into 100 ms to start the cancel and 100 ms extra time for // it to make it to the server, to make it highly probable that the server // RPC would have already started by the time the cancellation is sent // and the server-side gets enough time to react to it. - request.mutable_param()->set_server_sleep_us(80 * 1000); + request.mutable_param()->set_server_sleep_us(200000); std::thread echo_thread{[this, &context, &request, &response] { Status s = stub_->Echo(&context, request, &response); EXPECT_EQ(StatusCode::CANCELLED, s.error_code()); }}; - std::this_thread::sleep_for(std::chrono::microseconds(40000)); + std::this_thread::sleep_for(std::chrono::microseconds(100000)); context.TryCancel(); echo_thread.join(); } diff --git a/test/cpp/end2end/test_service_impl.cc b/test/cpp/end2end/test_service_impl.cc index 1cbbc703076..048715300ad 100644 --- a/test/cpp/end2end/test_service_impl.cc +++ b/test/cpp/end2end/test_service_impl.cc @@ -589,8 +589,9 @@ CallbackTestServiceImpl::RequestStream() { public: Reactor() {} void OnStarted(ServerContext* context, EchoResponse* response) override { - ctx_ = context; - response_ = response; + // Assign ctx_ and response_ as late as possible to increase likelihood of + // catching any races + // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by // the server by calling ServerContext::TryCancel() depending on the // value: @@ -602,22 +603,26 @@ CallbackTestServiceImpl::RequestStream() { server_try_cancel_ = GetIntValueFromMetadata( kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); - response_->set_message(""); + response->set_message(""); if (server_try_cancel_ == CANCEL_BEFORE_PROCESSING) { - ServerTryCancelNonblocking(ctx_); - return; + ServerTryCancelNonblocking(context); + ctx_ = context; + } else { + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + context->TryCancel(); + // Don't wait for it here + } + ctx_ = context; + response_ = response; + StartRead(&request_); } - if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { - ctx_->TryCancel(); - // Don't wait for it here - } - - StartRead(&request_); + on_started_done_ = true; } void OnDone() override { delete this; } void OnCancel() override { + EXPECT_TRUE(on_started_done_); EXPECT_TRUE(ctx_->IsCancelled()); FinishOnce(Status::CANCELLED); } @@ -657,6 +662,7 @@ CallbackTestServiceImpl::RequestStream() { int server_try_cancel_; std::mutex finish_mu_; bool finished_{false}; + bool on_started_done_{false}; }; return new Reactor; @@ -673,8 +679,9 @@ CallbackTestServiceImpl::ResponseStream() { Reactor() {} void OnStarted(ServerContext* context, const EchoRequest* request) override { - ctx_ = context; - request_ = request; + // Assign ctx_ and request_ as late as possible to increase likelihood of + // catching any races + // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by // the server by calling ServerContext::TryCancel() depending on the // value: @@ -691,19 +698,23 @@ CallbackTestServiceImpl::ResponseStream() { kServerResponseStreamsToSend, context->client_metadata(), kServerDefaultResponseStreamsToSend); if (server_try_cancel_ == CANCEL_BEFORE_PROCESSING) { - ServerTryCancelNonblocking(ctx_); - return; - } - - if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { - ctx_->TryCancel(); - } - if (num_msgs_sent_ < server_responses_to_send_) { - NextWrite(); + ServerTryCancelNonblocking(context); + ctx_ = context; + } else { + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + context->TryCancel(); + } + ctx_ = context; + request_ = request; + if (num_msgs_sent_ < server_responses_to_send_) { + NextWrite(); + } } + on_started_done_ = true; } void OnDone() override { delete this; } void OnCancel() override { + EXPECT_TRUE(on_started_done_); EXPECT_TRUE(ctx_->IsCancelled()); FinishOnce(Status::CANCELLED); } @@ -753,6 +764,7 @@ CallbackTestServiceImpl::ResponseStream() { int server_responses_to_send_; std::mutex finish_mu_; bool finished_{false}; + bool on_started_done_{false}; }; return new Reactor; } @@ -764,7 +776,9 @@ CallbackTestServiceImpl::BidiStream() { public: Reactor() {} void OnStarted(ServerContext* context) override { - ctx_ = context; + // Assign ctx_ as late as possible to increase likelihood of catching any + // races + // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by // the server by calling ServerContext::TryCancel() depending on the // value: @@ -778,18 +792,20 @@ CallbackTestServiceImpl::BidiStream() { server_write_last_ = GetIntValueFromMetadata( kServerFinishAfterNReads, context->client_metadata(), 0); if (server_try_cancel_ == CANCEL_BEFORE_PROCESSING) { - ServerTryCancelNonblocking(ctx_); - return; + ServerTryCancelNonblocking(context); + ctx_ = context; + } else { + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + context->TryCancel(); + } + ctx_ = context; + StartRead(&request_); } - - if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { - ctx_->TryCancel(); - } - - StartRead(&request_); + on_started_done_ = true; } void OnDone() override { delete this; } void OnCancel() override { + EXPECT_TRUE(on_started_done_); EXPECT_TRUE(ctx_->IsCancelled()); FinishOnce(Status::CANCELLED); } @@ -839,6 +855,7 @@ CallbackTestServiceImpl::BidiStream() { int server_write_last_; std::mutex finish_mu_; bool finished_{false}; + bool on_started_done_{false}; }; return new Reactor; From dad3f3420739df25e89aa259110579ea54094a7b Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Wed, 10 Apr 2019 12:14:04 -0700 Subject: [PATCH 235/242] Revert "Revert "Revert "Folding the Channel class into the grpc_impl namespace.""" --- BUILD | 1 - BUILD.gn | 1 - CMakeLists.txt | 3 - Makefile | 3 - build.yaml | 1 - gRPC-C++.podspec | 1 - include/grpcpp/channel.h | 88 ++++++++++++- include/grpcpp/channel_impl.h | 116 ------------------ include/grpcpp/impl/codegen/client_callback.h | 5 +- include/grpcpp/impl/codegen/client_context.h | 13 +- .../grpcpp/impl/codegen/client_interceptor.h | 6 +- .../grpcpp/impl/codegen/completion_queue.h | 4 +- .../grpcpp/impl/codegen/server_interface.h | 5 +- include/grpcpp/security/credentials.h | 19 ++- include/grpcpp/server_impl.h | 1 - src/compiler/cpp_generator.cc | 4 +- src/cpp/client/channel_cc.cc | 60 +++++---- src/cpp/client/client_context.cc | 9 +- src/cpp/client/create_channel.cc | 4 +- src/cpp/client/create_channel_internal.cc | 9 +- src/cpp/client/create_channel_internal.h | 9 +- src/cpp/client/create_channel_posix.cc | 6 +- src/cpp/client/cronet_credentials.cc | 2 +- src/cpp/client/insecure_credentials.cc | 2 +- src/cpp/client/secure_credentials.cc | 2 +- src/cpp/client/secure_credentials.h | 9 +- src/cpp/server/server_cc.cc | 4 +- test/cpp/codegen/compiler_test_golden | 5 +- test/cpp/codegen/golden_file_test.cc | 2 +- test/cpp/microbenchmarks/bm_call_create.cc | 2 +- test/cpp/microbenchmarks/fullstack_fixtures.h | 2 +- test/cpp/performance/writes_per_rpc_test.cc | 2 +- test/cpp/util/create_test_channel.h | 26 ++-- tools/doxygen/Doxyfile.c++ | 1 - tools/doxygen/Doxyfile.c++.internal | 1 - .../generated/sources_and_headers.json | 2 - 36 files changed, 170 insertions(+), 260 deletions(-) delete mode 100644 include/grpcpp/channel_impl.h diff --git a/BUILD b/BUILD index 74cf5413ba1..f5aa62627c2 100644 --- a/BUILD +++ b/BUILD @@ -216,7 +216,6 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/alarm.h", "include/grpcpp/alarm_impl.h", "include/grpcpp/channel.h", - "include/grpcpp/channel_impl.h", "include/grpcpp/client_context.h", "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", diff --git a/BUILD.gn b/BUILD.gn index 081de0cbfeb..57e15800e20 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1003,7 +1003,6 @@ config("grpc_config") { "include/grpcpp/alarm.h", "include/grpcpp/alarm_impl.h", "include/grpcpp/channel.h", - "include/grpcpp/channel_impl.h", "include/grpcpp/client_context.h", "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a6aa0307bc..86dcbb320d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2998,7 +2998,6 @@ foreach(_hdr include/grpcpp/alarm.h include/grpcpp/alarm_impl.h include/grpcpp/channel.h - include/grpcpp/channel_impl.h include/grpcpp/client_context.h include/grpcpp/completion_queue.h include/grpcpp/create_channel.h @@ -3603,7 +3602,6 @@ foreach(_hdr include/grpcpp/alarm.h include/grpcpp/alarm_impl.h include/grpcpp/channel.h - include/grpcpp/channel_impl.h include/grpcpp/client_context.h include/grpcpp/completion_queue.h include/grpcpp/create_channel.h @@ -4584,7 +4582,6 @@ foreach(_hdr include/grpcpp/alarm.h include/grpcpp/alarm_impl.h include/grpcpp/channel.h - include/grpcpp/channel_impl.h include/grpcpp/client_context.h include/grpcpp/completion_queue.h include/grpcpp/create_channel.h diff --git a/Makefile b/Makefile index 4cbcc0be757..66f96985bdb 100644 --- a/Makefile +++ b/Makefile @@ -5333,7 +5333,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/alarm.h \ include/grpcpp/alarm_impl.h \ include/grpcpp/channel.h \ - include/grpcpp/channel_impl.h \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ @@ -5946,7 +5945,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/alarm.h \ include/grpcpp/alarm_impl.h \ include/grpcpp/channel.h \ - include/grpcpp/channel_impl.h \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ @@ -6876,7 +6874,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/alarm.h \ include/grpcpp/alarm_impl.h \ include/grpcpp/channel.h \ - include/grpcpp/channel_impl.h \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ diff --git a/build.yaml b/build.yaml index 51422e22adb..a786546c231 100644 --- a/build.yaml +++ b/build.yaml @@ -1344,7 +1344,6 @@ filegroups: - include/grpcpp/alarm.h - include/grpcpp/alarm_impl.h - include/grpcpp/channel.h - - include/grpcpp/channel_impl.h - include/grpcpp/client_context.h - include/grpcpp/completion_queue.h - include/grpcpp/create_channel.h diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index e9a41c9e758..7f1ae557537 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -82,7 +82,6 @@ Pod::Spec.new do |s| ss.source_files = 'include/grpcpp/alarm.h', 'include/grpcpp/alarm_impl.h', 'include/grpcpp/channel.h', - 'include/grpcpp/channel_impl.h', 'include/grpcpp/client_context.h', 'include/grpcpp/completion_queue.h', 'include/grpcpp/create_channel.h', diff --git a/include/grpcpp/channel.h b/include/grpcpp/channel.h index d2e52ffa5bc..c4d5ab1177b 100644 --- a/include/grpcpp/channel.h +++ b/include/grpcpp/channel.h @@ -19,15 +19,97 @@ #ifndef GRPCPP_CHANNEL_H #define GRPCPP_CHANNEL_H -#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +struct grpc_channel; namespace grpc { -typedef ::grpc_impl::Channel Channel; - namespace experimental { +/// Resets the channel's connection backoff. +/// TODO(roth): Once we see whether this proves useful, either create a gRFC +/// and change this to be a method of the Channel class, or remove it. void ChannelResetConnectionBackoff(Channel* channel); } // namespace experimental +/// Channels represent a connection to an endpoint. Created by \a CreateChannel. +class Channel final : public ChannelInterface, + public internal::CallHook, + public std::enable_shared_from_this, + private GrpcLibraryCodegen { + public: + ~Channel(); + + /// Get the current channel state. If the channel is in IDLE and + /// \a try_to_connect is set to true, try to connect. + grpc_connectivity_state GetState(bool try_to_connect) override; + + /// Returns the LB policy name, or the empty string if not yet available. + grpc::string GetLoadBalancingPolicyName() const; + + /// Returns the service config in JSON form, or the empty string if + /// not available. + grpc::string GetServiceConfigJSON() const; + + private: + template + friend class internal::BlockingUnaryCallImpl; + friend void experimental::ChannelResetConnectionBackoff(Channel* channel); + friend std::shared_ptr CreateChannelInternal( + const grpc::string& host, grpc_channel* c_channel, + std::vector< + std::unique_ptr> + interceptor_creators); + friend class internal::InterceptedChannel; + Channel(const grpc::string& host, grpc_channel* c_channel, + std::vector< + std::unique_ptr> + interceptor_creators); + + internal::Call CreateCall(const internal::RpcMethod& method, + ClientContext* context, + CompletionQueue* cq) override; + void PerformOpsOnCall(internal::CallOpSetInterface* ops, + internal::Call* call) override; + void* RegisterMethod(const char* method) override; + + void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, + gpr_timespec deadline, CompletionQueue* cq, + void* tag) override; + bool WaitForStateChangeImpl(grpc_connectivity_state last_observed, + gpr_timespec deadline) override; + + CompletionQueue* CallbackCQ() override; + + internal::Call CreateCallInternal(const internal::RpcMethod& method, + ClientContext* context, CompletionQueue* cq, + size_t interceptor_pos) override; + + const grpc::string host_; + grpc_channel* const c_channel_; // owned + + // mu_ protects callback_cq_ (the per-channel callbackable completion queue) + grpc::internal::Mutex mu_; + + // callback_cq_ references the callbackable completion queue associated + // with this channel (if any). It is set on the first call to CallbackCQ(). + // It is _not owned_ by the channel; ownership belongs with its internal + // shutdown callback tag (invoked when the CQ is fully shutdown). + CompletionQueue* callback_cq_ = nullptr; + + std::vector> + interceptor_creators_; +}; + } // namespace grpc + #endif // GRPCPP_CHANNEL_H diff --git a/include/grpcpp/channel_impl.h b/include/grpcpp/channel_impl.h deleted file mode 100644 index 26850f8d30f..00000000000 --- a/include/grpcpp/channel_impl.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef GRPCPP_CHANNEL_IMPL_H -#define GRPCPP_CHANNEL_IMPL_H - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -struct grpc_channel; - -namespace grpc_impl { - -namespace experimental { -/// Resets the channel's connection backoff. -/// TODO(roth): Once we see whether this proves useful, either create a gRFC -/// and change this to be a method of the Channel class, or remove it. -void ChannelResetConnectionBackoff(Channel* channel); -} // namespace experimental - -/// Channels represent a connection to an endpoint. Created by \a CreateChannel. -class Channel final : public ::grpc::ChannelInterface, - public ::grpc::internal::CallHook, - public std::enable_shared_from_this, - private ::grpc::GrpcLibraryCodegen { - public: - ~Channel(); - - /// Get the current channel state. If the channel is in IDLE and - /// \a try_to_connect is set to true, try to connect. - grpc_connectivity_state GetState(bool try_to_connect) override; - - /// Returns the LB policy name, or the empty string if not yet available. - grpc::string GetLoadBalancingPolicyName() const; - - /// Returns the service config in JSON form, or the empty string if - /// not available. - grpc::string GetServiceConfigJSON() const; - - private: - template - friend class ::grpc::internal::BlockingUnaryCallImpl; - friend void experimental::ChannelResetConnectionBackoff(Channel* channel); - friend std::shared_ptr CreateChannelInternal( - const grpc::string& host, grpc_channel* c_channel, - std::vector> - interceptor_creators); - friend class ::grpc::internal::InterceptedChannel; - Channel(const grpc::string& host, grpc_channel* c_channel, - std::vector> - interceptor_creators); - - ::grpc::internal::Call CreateCall(const ::grpc::internal::RpcMethod& method, - ::grpc::ClientContext* context, - ::grpc::CompletionQueue* cq) override; - void PerformOpsOnCall(::grpc::internal::CallOpSetInterface* ops, - ::grpc::internal::Call* call) override; - void* RegisterMethod(const char* method) override; - - void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, - gpr_timespec deadline, - ::grpc::CompletionQueue* cq, void* tag) override; - bool WaitForStateChangeImpl(grpc_connectivity_state last_observed, - gpr_timespec deadline) override; - - ::grpc::CompletionQueue* CallbackCQ() override; - - ::grpc::internal::Call CreateCallInternal( - const ::grpc::internal::RpcMethod& method, ::grpc::ClientContext* context, - ::grpc::CompletionQueue* cq, size_t interceptor_pos) override; - - const grpc::string host_; - grpc_channel* const c_channel_; // owned - - // mu_ protects callback_cq_ (the per-channel callbackable completion queue) - grpc::internal::Mutex mu_; - - // callback_cq_ references the callbackable completion queue associated - // with this channel (if any). It is set on the first call to CallbackCQ(). - // It is _not owned_ by the channel; ownership belongs with its internal - // shutdown callback tag (invoked when the CQ is fully shutdown). - ::grpc::CompletionQueue* callback_cq_ = nullptr; - - std::vector< - std::unique_ptr<::grpc::experimental::ClientInterceptorFactoryInterface>> - interceptor_creators_; -}; - -} // namespace grpc_impl - -#endif // GRPCPP_CHANNEL_IMPL_H diff --git a/include/grpcpp/impl/codegen/client_callback.h b/include/grpcpp/impl/codegen/client_callback.h index 836200b5915..53c57b55f7e 100644 --- a/include/grpcpp/impl/codegen/client_callback.h +++ b/include/grpcpp/impl/codegen/client_callback.h @@ -29,12 +29,9 @@ #include #include -namespace grpc_impl { -class Channel; -} - namespace grpc { +class Channel; class ClientContext; class CompletionQueue; diff --git a/include/grpcpp/impl/codegen/client_context.h b/include/grpcpp/impl/codegen/client_context.h index 3b74a1367d1..85bbf36f06d 100644 --- a/include/grpcpp/impl/codegen/client_context.h +++ b/include/grpcpp/impl/codegen/client_context.h @@ -57,13 +57,9 @@ struct census_context; struct grpc_call; -namespace grpc_impl { - -class Channel; -} - namespace grpc { +class Channel; class ChannelInterface; class CompletionQueue; class CallCredentials; @@ -396,7 +392,7 @@ class ClientContext { friend class ::grpc::testing::InteropClientContextInspector; friend class ::grpc::internal::CallOpClientRecvStatus; friend class ::grpc::internal::CallOpRecvInitialMetadata; - friend class ::grpc_impl::Channel; + friend class Channel; template friend class ::grpc::ClientReader; template @@ -428,8 +424,7 @@ class ClientContext { } grpc_call* call() const { return call_; } - void set_call(grpc_call* call, - const std::shared_ptr<::grpc_impl::Channel>& channel); + void set_call(grpc_call* call, const std::shared_ptr& channel); experimental::ClientRpcInfo* set_client_rpc_info( const char* method, internal::RpcMethod::RpcType type, @@ -462,7 +457,7 @@ class ClientContext { bool wait_for_ready_explicitly_set_; bool idempotent_; bool cacheable_; - std::shared_ptr<::grpc_impl::Channel> channel_; + std::shared_ptr channel_; grpc::internal::Mutex mu_; grpc_call* call_; bool call_canceled_; diff --git a/include/grpcpp/impl/codegen/client_interceptor.h b/include/grpcpp/impl/codegen/client_interceptor.h index a4c85a76da5..19106545089 100644 --- a/include/grpcpp/impl/codegen/client_interceptor.h +++ b/include/grpcpp/impl/codegen/client_interceptor.h @@ -26,14 +26,10 @@ #include #include -namespace grpc_impl { - -class Channel; -} - namespace grpc { class ClientContext; +class Channel; namespace internal { class InterceptorBatchMethodsImpl; diff --git a/include/grpcpp/impl/codegen/completion_queue.h b/include/grpcpp/impl/codegen/completion_queue.h index 508ab05815d..85eee6f34bf 100644 --- a/include/grpcpp/impl/codegen/completion_queue.h +++ b/include/grpcpp/impl/codegen/completion_queue.h @@ -43,7 +43,6 @@ struct grpc_completion_queue; namespace grpc_impl { -class Channel; class Server; class ServerBuilder; } // namespace grpc_impl @@ -64,6 +63,7 @@ template class ServerReaderWriterBody; } // namespace internal +class Channel; class ChannelInterface; class ClientContext; class CompletionQueue; @@ -281,7 +281,7 @@ class CompletionQueue : private GrpcLibraryCodegen { friend class ::grpc::internal::BlockingUnaryCallImpl; // Friends that need access to constructor for callback CQ - friend class ::grpc_impl::Channel; + friend class ::grpc::Channel; // For access to Register/CompleteAvalanching template diff --git a/include/grpcpp/impl/codegen/server_interface.h b/include/grpcpp/impl/codegen/server_interface.h index 9299fdb20e1..a0b0a580979 100644 --- a/include/grpcpp/impl/codegen/server_interface.h +++ b/include/grpcpp/impl/codegen/server_interface.h @@ -29,12 +29,13 @@ #include namespace grpc_impl { -class Channel; + class ServerCredentials; -} // namespace grpc_impl +} namespace grpc { class AsyncGenericService; +class Channel; class GenericServerContext; class ServerCompletionQueue; class ServerContext; diff --git a/include/grpcpp/security/credentials.h b/include/grpcpp/security/credentials.h index 5846da106d5..34d2e2ea463 100644 --- a/include/grpcpp/security/credentials.h +++ b/include/grpcpp/security/credentials.h @@ -32,26 +32,20 @@ struct grpc_call; -namespace grpc_impl { - -class Channel; -} // namespace grpc_impl namespace grpc { class CallCredentials; class ChannelArguments; class ChannelCredentials; -class SecureCallCredentials; -class SecureChannelCredentials; } // namespace grpc namespace grpc_impl { -std::shared_ptr CreateCustomChannel( +std::shared_ptr CreateCustomChannel( const grpc::string& target, const std::shared_ptr& creds, const grpc::ChannelArguments& args); namespace experimental { -std::shared_ptr CreateCustomChannelWithInterceptors( +std::shared_ptr CreateCustomChannelWithInterceptors( const grpc::string& target, const std::shared_ptr& creds, const grpc::ChannelArguments& args, @@ -61,6 +55,7 @@ std::shared_ptr CreateCustomChannelWithInterceptors( } // namespace experimental } // namespace grpc_impl namespace grpc { +class Channel; class SecureChannelCredentials; class SecureCallCredentials; @@ -83,12 +78,12 @@ class ChannelCredentials : private GrpcLibraryCodegen { virtual SecureChannelCredentials* AsSecureCredentials() = 0; private: - friend std::shared_ptr<::grpc_impl::Channel> grpc_impl::CreateCustomChannel( + friend std::shared_ptr grpc_impl::CreateCustomChannel( const grpc::string& target, const std::shared_ptr& creds, const grpc::ChannelArguments& args); - friend std::shared_ptr<::grpc_impl::Channel> + friend std::shared_ptr grpc_impl::experimental::CreateCustomChannelWithInterceptors( const grpc::string& target, const std::shared_ptr& creds, @@ -97,12 +92,12 @@ class ChannelCredentials : private GrpcLibraryCodegen { grpc::experimental::ClientInterceptorFactoryInterface>> interceptor_creators); - virtual std::shared_ptr<::grpc_impl::Channel> CreateChannel( + virtual std::shared_ptr CreateChannel( const grpc::string& target, const ChannelArguments& args) = 0; // This function should have been a pure virtual function, but it is // implemented as a virtual function so that it does not break API. - virtual std::shared_ptr<::grpc_impl::Channel> CreateChannelWithInterceptors( + virtual std::shared_ptr CreateChannelWithInterceptors( const grpc::string& target, const ChannelArguments& args, std::vector< std::unique_ptr> diff --git a/include/grpcpp/server_impl.h b/include/grpcpp/server_impl.h index 9f07d5f7cb7..14b16a06f4e 100644 --- a/include/grpcpp/server_impl.h +++ b/include/grpcpp/server_impl.h @@ -27,7 +27,6 @@ #include #include -#include #include #include #include diff --git a/src/compiler/cpp_generator.cc b/src/compiler/cpp_generator.cc index 6b53b3f64ce..96e9ab8dcfb 100644 --- a/src/compiler/cpp_generator.cc +++ b/src/compiler/cpp_generator.cc @@ -145,11 +145,9 @@ grpc::string GetHeaderIncludes(grpc_generator::File* file, PrintIncludes(printer.get(), headers, params.use_system_headers, params.grpc_search_path); printer->Print(vars, "\n"); - printer->Print(vars, "namespace grpc_impl {\n"); - printer->Print(vars, "class Channel;\n"); - printer->Print(vars, "} // namespace grpc_impl\n\n"); printer->Print(vars, "namespace grpc {\n"); printer->Print(vars, "class CompletionQueue;\n"); + printer->Print(vars, "class Channel;\n"); printer->Print(vars, "class ServerCompletionQueue;\n"); printer->Print(vars, "class ServerContext;\n"); printer->Print(vars, "} // namespace grpc\n\n"); diff --git a/src/cpp/client/channel_cc.cc b/src/cpp/client/channel_cc.cc index 58f012d8c82..2d5e74163a9 100644 --- a/src/cpp/client/channel_cc.cc +++ b/src/cpp/client/channel_cc.cc @@ -42,18 +42,14 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/surface/completion_queue.h" -void grpc::experimental::ChannelResetConnectionBackoff( - ::grpc::Channel* channel) { - grpc_impl::experimental::ChannelResetConnectionBackoff(channel); -} +namespace grpc { -namespace grpc_impl { - -static ::grpc::internal::GrpcLibraryInitializer g_gli_initializer; -Channel::Channel(const grpc::string& host, grpc_channel* channel, - std::vector> - interceptor_creators) +static internal::GrpcLibraryInitializer g_gli_initializer; +Channel::Channel( + const grpc::string& host, grpc_channel* channel, + std::vector< + std::unique_ptr> + interceptor_creators) : host_(host), c_channel_(channel) { interceptor_creators_ = std::move(interceptor_creators); g_gli_initializer.summon(); @@ -69,8 +65,7 @@ Channel::~Channel() { namespace { inline grpc_slice SliceFromArray(const char* arr, size_t len) { - return ::grpc::g_core_codegen_interface->grpc_slice_from_copied_buffer(arr, - len); + return g_core_codegen_interface->grpc_slice_from_copied_buffer(arr, len); } grpc::string GetChannelInfoField(grpc_channel* channel, @@ -108,9 +103,10 @@ void ChannelResetConnectionBackoff(Channel* channel) { } // namespace experimental -::grpc::internal::Call Channel::CreateCallInternal( - const ::grpc::internal::RpcMethod& method, ::grpc::ClientContext* context, - ::grpc::CompletionQueue* cq, size_t interceptor_pos) { +internal::Call Channel::CreateCallInternal(const internal::RpcMethod& method, + ClientContext* context, + CompletionQueue* cq, + size_t interceptor_pos) { const bool kRegistered = method.channel_tag() && context->authority().empty(); grpc_call* c_call = nullptr; if (kRegistered) { @@ -119,7 +115,7 @@ void ChannelResetConnectionBackoff(Channel* channel) { context->propagation_options_.c_bitmask(), cq->cq(), method.channel_tag(), context->raw_deadline(), nullptr); } else { - const ::grpc::string* host_str = nullptr; + const string* host_str = nullptr; if (!context->authority_.empty()) { host_str = &context->authority_; } else if (!host_.empty()) { @@ -129,7 +125,7 @@ void ChannelResetConnectionBackoff(Channel* channel) { SliceFromArray(method.name(), strlen(method.name())); grpc_slice host_slice; if (host_str != nullptr) { - host_slice = ::grpc::SliceFromCopiedString(*host_str); + host_slice = SliceFromCopiedString(*host_str); } c_call = grpc_channel_create_call( c_channel_, context->propagate_from_call_, @@ -151,17 +147,17 @@ void ChannelResetConnectionBackoff(Channel* channel) { interceptor_creators_, interceptor_pos); context->set_call(c_call, shared_from_this()); - return ::grpc::internal::Call(c_call, this, cq, info); + return internal::Call(c_call, this, cq, info); } -::grpc::internal::Call Channel::CreateCall( - const ::grpc::internal::RpcMethod& method, ::grpc::ClientContext* context, - ::grpc::CompletionQueue* cq) { +internal::Call Channel::CreateCall(const internal::RpcMethod& method, + ClientContext* context, + CompletionQueue* cq) { return CreateCallInternal(method, context, cq, 0); } -void Channel::PerformOpsOnCall(::grpc::internal::CallOpSetInterface* ops, - ::grpc::internal::Call* call) { +void Channel::PerformOpsOnCall(internal::CallOpSetInterface* ops, + internal::Call* call) { ops->FillOps( call); // Make a copy of call. It's fine since Call just has pointers } @@ -177,7 +173,7 @@ grpc_connectivity_state Channel::GetState(bool try_to_connect) { namespace { -class TagSaver final : public ::grpc::internal::CompletionQueueTag { +class TagSaver final : public internal::CompletionQueueTag { public: explicit TagSaver(void* tag) : tag_(tag) {} ~TagSaver() override {} @@ -195,7 +191,7 @@ class TagSaver final : public ::grpc::internal::CompletionQueueTag { void Channel::NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline, - ::grpc::CompletionQueue* cq, void* tag) { + CompletionQueue* cq, void* tag) { TagSaver* tag_saver = new TagSaver(tag); grpc_channel_watch_connectivity_state(c_channel_, last_observed, deadline, cq->cq(), tag_saver); @@ -203,7 +199,7 @@ void Channel::NotifyOnStateChangeImpl(grpc_connectivity_state last_observed, bool Channel::WaitForStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline) { - ::grpc::CompletionQueue cq; + CompletionQueue cq; bool ok = false; void* tag = nullptr; NotifyOnStateChangeImpl(last_observed, deadline, &cq, nullptr); @@ -218,7 +214,7 @@ class ShutdownCallback : public grpc_experimental_completion_queue_functor { ShutdownCallback() { functor_run = &ShutdownCallback::Run; } // TakeCQ takes ownership of the cq into the shutdown callback // so that the shutdown callback will be responsible for destroying it - void TakeCQ(::grpc::CompletionQueue* cq) { cq_ = cq; } + void TakeCQ(CompletionQueue* cq) { cq_ = cq; } // The Run function will get invoked by the completion queue library // when the shutdown is actually complete @@ -229,17 +225,17 @@ class ShutdownCallback : public grpc_experimental_completion_queue_functor { } private: - ::grpc::CompletionQueue* cq_ = nullptr; + CompletionQueue* cq_ = nullptr; }; } // namespace -::grpc::CompletionQueue* Channel::CallbackCQ() { +CompletionQueue* Channel::CallbackCQ() { // TODO(vjpai): Consider using a single global CQ for the default CQ // if there is no explicit per-channel CQ registered grpc::internal::MutexLock l(&mu_); if (callback_cq_ == nullptr) { auto* shutdown_callback = new ShutdownCallback; - callback_cq_ = new ::grpc::CompletionQueue(grpc_completion_queue_attributes{ + callback_cq_ = new CompletionQueue(grpc_completion_queue_attributes{ GRPC_CQ_CURRENT_VERSION, GRPC_CQ_CALLBACK, GRPC_CQ_DEFAULT_POLLING, shutdown_callback}); @@ -249,4 +245,4 @@ class ShutdownCallback : public grpc_experimental_completion_queue_functor { return callback_cq_; } -} // namespace grpc_impl +} // namespace grpc diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc index 0ae1ecbf4ba..b4fce79b99a 100644 --- a/src/cpp/client/client_context.cc +++ b/src/cpp/client/client_context.cc @@ -31,11 +31,6 @@ #include #include -namespace grpc_impl { - -class Channel; -} - namespace grpc { class DefaultGlobalClientCallbacks final @@ -88,8 +83,8 @@ void ClientContext::AddMetadata(const grpc::string& meta_key, send_initial_metadata_.insert(std::make_pair(meta_key, meta_value)); } -void ClientContext::set_call( - grpc_call* call, const std::shared_ptr<::grpc_impl::Channel>& channel) { +void ClientContext::set_call(grpc_call* call, + const std::shared_ptr& channel) { grpc::internal::MutexLock lock(&mu_); GPR_ASSERT(call_ == nullptr); call_ = call; diff --git a/src/cpp/client/create_channel.cc b/src/cpp/client/create_channel.cc index fea3695cabc..e1dca5f1a12 100644 --- a/src/cpp/client/create_channel.cc +++ b/src/cpp/client/create_channel.cc @@ -43,7 +43,7 @@ std::shared_ptr CreateCustomChannel( grpc::GrpcLibraryCodegen init_lib; // We need to call init in case of a bad creds. return creds ? creds->CreateChannel(target, args) - : ::grpc_impl::CreateChannelInternal( + : grpc::CreateChannelInternal( "", grpc_lame_client_channel_create( nullptr, GRPC_STATUS_INVALID_ARGUMENT, @@ -74,7 +74,7 @@ std::shared_ptr CreateCustomChannelWithInterceptors( interceptor_creators) { return creds ? creds->CreateChannelWithInterceptors( target, args, std::move(interceptor_creators)) - : ::grpc_impl::CreateChannelInternal( + : grpc::CreateChannelInternal( "", grpc_lame_client_channel_create( nullptr, GRPC_STATUS_INVALID_ARGUMENT, diff --git a/src/cpp/client/create_channel_internal.cc b/src/cpp/client/create_channel_internal.cc index 77fd00fb3fe..a0efb97f7ef 100644 --- a/src/cpp/client/create_channel_internal.cc +++ b/src/cpp/client/create_channel_internal.cc @@ -22,15 +22,14 @@ struct grpc_channel; -namespace grpc_impl { +namespace grpc { std::shared_ptr CreateChannelInternal( const grpc::string& host, grpc_channel* c_channel, - std::vector> + std::vector< + std::unique_ptr> interceptor_creators) { return std::shared_ptr( new Channel(host, c_channel, std::move(interceptor_creators))); } - -} // namespace grpc_impl +} // namespace grpc diff --git a/src/cpp/client/create_channel_internal.h b/src/cpp/client/create_channel_internal.h index 7dab6473a9c..a90c92c518d 100644 --- a/src/cpp/client/create_channel_internal.h +++ b/src/cpp/client/create_channel_internal.h @@ -26,16 +26,15 @@ struct grpc_channel; -namespace grpc_impl { - +namespace grpc { class Channel; std::shared_ptr CreateChannelInternal( const grpc::string& host, grpc_channel* c_channel, - std::vector> + std::vector< + std::unique_ptr> interceptor_creators); -} // namespace grpc_impl +} // namespace grpc #endif // GRPC_INTERNAL_CPP_CLIENT_CREATE_CHANNEL_INTERNAL_H diff --git a/src/cpp/client/create_channel_posix.cc b/src/cpp/client/create_channel_posix.cc index fef8f9c0625..6de373577eb 100644 --- a/src/cpp/client/create_channel_posix.cc +++ b/src/cpp/client/create_channel_posix.cc @@ -32,7 +32,7 @@ std::shared_ptr CreateInsecureChannelFromFd( const grpc::string& target, int fd) { grpc::internal::GrpcLibrary init_lib; init_lib.init(); - return ::grpc_impl::CreateChannelInternal( + return grpc::CreateChannelInternal( "", grpc_insecure_channel_create_from_fd(target.c_str(), fd, nullptr), std::vector>()); @@ -44,7 +44,7 @@ std::shared_ptr CreateCustomInsecureChannelFromFd( init_lib.init(); grpc_channel_args channel_args; args.SetChannelArgs(&channel_args); - return ::grpc_impl::CreateChannelInternal( + return grpc::CreateChannelInternal( "", grpc_insecure_channel_create_from_fd(target.c_str(), fd, &channel_args), std::vector CreateChannel( + std::shared_ptr CreateChannel( const string& target, const grpc::ChannelArguments& args) override; SecureChannelCredentials* AsSecureCredentials() override { return this; } private: - std::shared_ptr<::grpc_impl::Channel> CreateChannelWithInterceptors( + std::shared_ptr CreateChannelWithInterceptors( const string& target, const grpc::ChannelArguments& args, std::vector< std::unique_ptr> diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 3969c845439..4f0fdefceda 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -1028,7 +1028,7 @@ grpc_server* Server::c_server() { return server_; } std::shared_ptr Server::InProcessChannel( const grpc::ChannelArguments& args) { grpc_channel_args channel_args = args.c_channel_args(); - return ::grpc_impl::CreateChannelInternal( + return grpc::CreateChannelInternal( "inproc", grpc_inproc_channel_create(server_, &channel_args, nullptr), std::vector>()); @@ -1041,7 +1041,7 @@ Server::experimental_type::InProcessChannelWithInterceptors( std::unique_ptr> interceptor_creators) { grpc_channel_args channel_args = args.c_channel_args(); - return ::grpc_impl::CreateChannelInternal( + return grpc::CreateChannelInternal( "inproc", grpc_inproc_channel_create(server_->server_, &channel_args, nullptr), std::move(interceptor_creators)); diff --git a/test/cpp/codegen/compiler_test_golden b/test/cpp/codegen/compiler_test_golden index 9202585535b..7f9fd29026e 100644 --- a/test/cpp/codegen/compiler_test_golden +++ b/test/cpp/codegen/compiler_test_golden @@ -40,12 +40,9 @@ #include #include -namespace grpc_impl { -class Channel; -} // namespace grpc_impl - namespace grpc { class CompletionQueue; +class Channel; class ServerCompletionQueue; class ServerContext; } // namespace grpc diff --git a/test/cpp/codegen/golden_file_test.cc b/test/cpp/codegen/golden_file_test.cc index 19f267dd4b5..bfd36494941 100644 --- a/test/cpp/codegen/golden_file_test.cc +++ b/test/cpp/codegen/golden_file_test.cc @@ -31,7 +31,7 @@ using namespace gflags; DEFINE_string( generated_file_path, "", - "path to the directory containing generated files compiler_test.grpc.pb.h " + "path to the directory containing generated files compiler_test.grpc.pb.h" "and compiler_test_mock.grpc.pb.h"); const char kGoldenFilePath[] = "test/cpp/codegen/compiler_test_golden"; diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc index a11b55eb90c..e84999b213f 100644 --- a/test/cpp/microbenchmarks/bm_call_create.cc +++ b/test/cpp/microbenchmarks/bm_call_create.cc @@ -131,7 +131,7 @@ static void* tag(int i) { static void BM_LameChannelCallCreateCpp(benchmark::State& state) { TrackCounters track_counters; auto stub = - grpc::testing::EchoTestService::NewStub(grpc_impl::CreateChannelInternal( + grpc::testing::EchoTestService::NewStub(grpc::CreateChannelInternal( "", grpc_lame_client_channel_create("localhost:1234", GRPC_STATUS_UNAUTHENTICATED, "blah"), diff --git a/test/cpp/microbenchmarks/fullstack_fixtures.h b/test/cpp/microbenchmarks/fullstack_fixtures.h index 2d488d8b227..6bbf553bbd8 100644 --- a/test/cpp/microbenchmarks/fullstack_fixtures.h +++ b/test/cpp/microbenchmarks/fullstack_fixtures.h @@ -218,7 +218,7 @@ class EndpointPairFixture : public BaseFixture { "target", &c_args, GRPC_CLIENT_DIRECT_CHANNEL, client_transport_); grpc_chttp2_transport_start_reading(client_transport_, nullptr, nullptr); - channel_ = ::grpc_impl::CreateChannelInternal( + channel_ = CreateChannelInternal( "", channel, std::vector>()); diff --git a/test/cpp/performance/writes_per_rpc_test.cc b/test/cpp/performance/writes_per_rpc_test.cc index b531e08138a..7b22f23cf00 100644 --- a/test/cpp/performance/writes_per_rpc_test.cc +++ b/test/cpp/performance/writes_per_rpc_test.cc @@ -118,7 +118,7 @@ class EndpointPairFixture { "target", &c_args, GRPC_CLIENT_DIRECT_CHANNEL, transport); grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); - channel_ = ::grpc_impl::CreateChannelInternal( + channel_ = CreateChannelInternal( "", channel, std::vector>()); diff --git a/test/cpp/util/create_test_channel.h b/test/cpp/util/create_test_channel.h index f644bd3e879..b50131b385c 100644 --- a/test/cpp/util/create_test_channel.h +++ b/test/cpp/util/create_test_channel.h @@ -24,12 +24,8 @@ #include #include -namespace grpc_impl { - -class Channel; -} - namespace grpc { +class Channel; namespace testing { @@ -37,35 +33,35 @@ typedef enum { INSECURE = 0, TLS, ALTS } transport_security; } // namespace testing -std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( +std::shared_ptr CreateTestChannel( const grpc::string& server, testing::transport_security security_type); -std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( +std::shared_ptr CreateTestChannel( const grpc::string& server, const grpc::string& override_hostname, testing::transport_security security_type, bool use_prod_roots); -std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( +std::shared_ptr CreateTestChannel( const grpc::string& server, const grpc::string& override_hostname, testing::transport_security security_type, bool use_prod_roots, const std::shared_ptr& creds); -std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( +std::shared_ptr CreateTestChannel( const grpc::string& server, const grpc::string& override_hostname, testing::transport_security security_type, bool use_prod_roots, const std::shared_ptr& creds, const ChannelArguments& args); -std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( +std::shared_ptr CreateTestChannel( const grpc::string& server, const grpc::string& cred_type, const grpc::string& override_hostname, bool use_prod_roots, const std::shared_ptr& creds, const ChannelArguments& args); -std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( +std::shared_ptr CreateTestChannel( const grpc::string& server, const grpc::string& credential_type, const std::shared_ptr& creds); -std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( +std::shared_ptr CreateTestChannel( const grpc::string& server, const grpc::string& override_hostname, testing::transport_security security_type, bool use_prod_roots, const std::shared_ptr& creds, @@ -73,7 +69,7 @@ std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( std::unique_ptr> interceptor_creators); -std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( +std::shared_ptr CreateTestChannel( const grpc::string& server, const grpc::string& override_hostname, testing::transport_security security_type, bool use_prod_roots, const std::shared_ptr& creds, const ChannelArguments& args, @@ -81,7 +77,7 @@ std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( std::unique_ptr> interceptor_creators); -std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( +std::shared_ptr CreateTestChannel( const grpc::string& server, const grpc::string& cred_type, const grpc::string& override_hostname, bool use_prod_roots, const std::shared_ptr& creds, const ChannelArguments& args, @@ -89,7 +85,7 @@ std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( std::unique_ptr> interceptor_creators); -std::shared_ptr<::grpc_impl::Channel> CreateTestChannel( +std::shared_ptr CreateTestChannel( const grpc::string& server, const grpc::string& credential_type, const std::shared_ptr& creds, std::vector< diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 8659a7d7381..67bbb4efa6b 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -927,7 +927,6 @@ include/grpc/support/workaround_list.h \ include/grpcpp/alarm.h \ include/grpcpp/alarm_impl.h \ include/grpcpp/channel.h \ -include/grpcpp/channel_impl.h \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 65369aa0e43..438cb98dbae 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -928,7 +928,6 @@ include/grpc/support/workaround_list.h \ include/grpcpp/alarm.h \ include/grpcpp/alarm_impl.h \ include/grpcpp/channel.h \ -include/grpcpp/channel_impl.h \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 27b2909a690..8534e71e2ce 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -10112,7 +10112,6 @@ "include/grpcpp/alarm.h", "include/grpcpp/alarm_impl.h", "include/grpcpp/channel.h", - "include/grpcpp/channel_impl.h", "include/grpcpp/client_context.h", "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", @@ -10234,7 +10233,6 @@ "include/grpcpp/alarm.h", "include/grpcpp/alarm_impl.h", "include/grpcpp/channel.h", - "include/grpcpp/channel_impl.h", "include/grpcpp/client_context.h", "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", From f03b309787c34216bc662238a866f4f3619784e5 Mon Sep 17 00:00:00 2001 From: Karthik Ravi Shankar Date: Wed, 10 Apr 2019 13:48:38 -0700 Subject: [PATCH 236/242] Revert "Merge pull request #18458 from grpc/grpc_namespace_server" This reverts commit dc1089a6d1e5874d4560fe1744c51cc55bdf7d4a, reversing changes made to 31843787ccdb8446e3be3b62d6688dc1de22c7b4. This change also includes - Revert "Merge pull request #17932 from soheilhy/gprpp-mutex" This reverts commit df4b6a763d49a9b590a8088dadc8eee569339b1d, reversing changes made to dc1089a6d1e5874d4560fe1744c51cc55bdf7d4a. --- BUILD | 15 +- BUILD.gn | 6 +- CMakeLists.txt | 8 - Makefile | 8 - build.yaml | 9 +- gRPC-C++.podspec | 8 +- gRPC-Core.podspec | 4 +- grpc.gemspec | 2 +- include/grpcpp/channel.h | 3 +- .../impl/codegen/async_generic_service.h | 10 +- include/grpcpp/impl/codegen/async_stream.h | 2 +- include/grpcpp/impl/codegen/client_context.h | 3 +- .../grpcpp/impl/codegen/completion_queue.h | 10 +- include/grpcpp/impl/codegen/server_context.h | 7 +- include/grpcpp/impl/codegen/service_type.h | 7 +- include/grpcpp/impl/codegen/sync.h | 138 -- include/grpcpp/impl/server_initializer_impl.h | 2 +- include/grpcpp/security/server_credentials.h | 4 - .../grpcpp/security/server_credentials_impl.h | 4 +- include/grpcpp/server.h | 328 ++- include/grpcpp/server_builder.h | 1 - include/grpcpp/server_builder_impl.h | 2 +- include/grpcpp/server_impl.h | 8 +- package.xml | 2 +- .../filters/client_channel/client_channel.cc | 2 +- .../health/health_check_client.cc | 4 +- .../health/health_check_client.h | 3 +- .../client_channel/http_connect_handshaker.cc | 2 +- .../client_channel/lb_policy/grpclb/grpclb.cc | 1 + .../lb_policy/grpclb/grpclb_client_stats.cc | 2 +- .../lb_policy/grpclb/grpclb_client_stats.h | 6 +- .../lb_policy/pick_first/pick_first.cc | 6 +- .../lb_policy/round_robin/round_robin.cc | 6 +- .../client_channel/lb_policy/xds/xds.cc | 19 +- .../client_channel/resolving_lb_policy.cc | 2 +- .../ext/filters/client_channel/subchannel.cc | 70 +- .../ext/filters/client_channel/subchannel.h | 3 +- src/core/lib/channel/channelz_registry.cc | 2 +- src/core/lib/channel/handshaker.h | 2 +- src/core/lib/gprpp/mutex_lock.h | 42 + src/core/lib/gprpp/sync.h | 126 - src/core/lib/iomgr/ev_epollex_linux.cc | 2 +- src/core/lib/surface/init.cc | 2 +- .../ssl/session_cache/ssl_session_cache.cc | 2 +- src/cpp/client/channel_cc.cc | 2 +- src/cpp/client/client_context.cc | 5 +- src/cpp/server/dynamic_thread_pool.cc | 23 +- src/cpp/server/dynamic_thread_pool.h | 7 +- .../health/default_health_check_service.cc | 28 +- .../health/default_health_check_service.h | 7 +- src/cpp/server/load_reporter/load_reporter.cc | 18 +- src/cpp/server/load_reporter/load_reporter.h | 5 +- .../load_reporter_async_service_impl.cc | 24 +- .../load_reporter_async_service_impl.h | 3 +- src/cpp/server/server_cc.cc | 2128 ++++++++--------- src/cpp/server/server_context.cc | 14 +- src/cpp/thread_manager/thread_manager.cc | 34 +- src/cpp/thread_manager/thread_manager.h | 7 +- test/cpp/client/client_channel_stress_test.cc | 17 +- test/cpp/end2end/client_lb_end2end_test.cc | 37 +- test/cpp/end2end/grpclb_end2end_test.cc | 67 +- test/cpp/end2end/thread_stress_test.cc | 21 +- test/cpp/end2end/xds_end2end_test.cc | 66 +- test/cpp/util/metrics_server.h | 2 - tools/doxygen/Doxyfile.c++ | 2 - tools/doxygen/Doxyfile.c++.internal | 4 +- tools/doxygen/Doxyfile.core.internal | 2 +- .../generated/sources_and_headers.json | 22 +- 68 files changed, 1722 insertions(+), 1718 deletions(-) delete mode 100644 include/grpcpp/impl/codegen/sync.h create mode 100644 src/core/lib/gprpp/mutex_lock.h delete mode 100644 src/core/lib/gprpp/sync.h diff --git a/BUILD b/BUILD index 19e370014e3..8837ed8075f 100644 --- a/BUILD +++ b/BUILD @@ -255,7 +255,6 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/security/server_credentials.h", "include/grpcpp/security/server_credentials_impl.h", "include/grpcpp/server.h", - "include/grpcpp/server_impl.h", "include/grpcpp/server_builder.h", "include/grpcpp/server_builder_impl.h", "include/grpcpp/server_context.h", @@ -526,17 +525,6 @@ grpc_cc_library( ], ) -grpc_cc_library( - name = "grpc++_internal_hdrs_only", - hdrs = [ - "include/grpcpp/impl/codegen/sync.h", - ], - language = "c++", - deps = [ - "gpr_codegen", - ], -) - grpc_cc_library( name = "gpr_base", srcs = [ @@ -602,8 +590,8 @@ grpc_cc_library( "src/core/lib/gprpp/manual_constructor.h", "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", + "src/core/lib/gprpp/mutex_lock.h", "src/core/lib/gprpp/pair.h", - "src/core/lib/gprpp/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/profiling/timers.h", ], @@ -2157,7 +2145,6 @@ grpc_cc_library( "include/grpcpp/impl/codegen/time.h", ], deps = [ - "grpc++_internal_hdrs_only", "grpc_codegen", ], ) diff --git a/BUILD.gn b/BUILD.gn index 57e15800e20..1417f1db5ea 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -186,8 +186,8 @@ config("grpc_config") { "src/core/lib/gprpp/manual_constructor.h", "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", + "src/core/lib/gprpp/mutex_lock.h", "src/core/lib/gprpp/pair.h", - "src/core/lib/gprpp/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/gprpp/thd_posix.cc", "src/core/lib/gprpp/thd_windows.cc", @@ -1064,7 +1064,6 @@ config("grpc_config") { "include/grpcpp/impl/codegen/status_code_enum.h", "include/grpcpp/impl/codegen/string_ref.h", "include/grpcpp/impl/codegen/stub_options.h", - "include/grpcpp/impl/codegen/sync.h", "include/grpcpp/impl/codegen/sync_stream.h", "include/grpcpp/impl/codegen/time.h", "include/grpcpp/impl/grpc_library.h", @@ -1090,7 +1089,6 @@ config("grpc_config") { "include/grpcpp/server_builder.h", "include/grpcpp/server_builder_impl.h", "include/grpcpp/server_context.h", - "include/grpcpp/server_impl.h", "include/grpcpp/server_posix.h", "include/grpcpp/server_posix_impl.h", "include/grpcpp/support/async_stream.h", @@ -1160,12 +1158,12 @@ config("grpc_config") { "src/core/lib/gprpp/manual_constructor.h", "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", + "src/core/lib/gprpp/mutex_lock.h", "src/core/lib/gprpp/optional.h", "src/core/lib/gprpp/orphanable.h", "src/core/lib/gprpp/pair.h", "src/core/lib/gprpp/ref_counted.h", "src/core/lib/gprpp/ref_counted_ptr.h", - "src/core/lib/gprpp/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 86dcbb320d5..5b99a57633a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3038,7 +3038,6 @@ foreach(_hdr include/grpcpp/server_builder.h include/grpcpp/server_builder_impl.h include/grpcpp/server_context.h - include/grpcpp/server_impl.h include/grpcpp/server_posix.h include/grpcpp/server_posix_impl.h include/grpcpp/support/async_stream.h @@ -3182,7 +3181,6 @@ foreach(_hdr include/grpcpp/impl/codegen/stub_options.h include/grpcpp/impl/codegen/sync_stream.h include/grpcpp/impl/codegen/time.h - include/grpcpp/impl/codegen/sync.h include/grpc++/impl/codegen/proto_utils.h include/grpcpp/impl/codegen/proto_buffer_reader.h include/grpcpp/impl/codegen/proto_buffer_writer.h @@ -3642,7 +3640,6 @@ foreach(_hdr include/grpcpp/server_builder.h include/grpcpp/server_builder_impl.h include/grpcpp/server_context.h - include/grpcpp/server_impl.h include/grpcpp/server_posix.h include/grpcpp/server_posix_impl.h include/grpcpp/support/async_stream.h @@ -3786,7 +3783,6 @@ foreach(_hdr include/grpcpp/impl/codegen/stub_options.h include/grpcpp/impl/codegen/sync_stream.h include/grpcpp/impl/codegen/time.h - include/grpcpp/impl/codegen/sync.h include/grpc/census.h ) string(REPLACE "include/" "" _path ${_hdr}) @@ -4241,7 +4237,6 @@ foreach(_hdr include/grpc/impl/codegen/sync_generic.h include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h - include/grpcpp/impl/codegen/sync.h include/grpc++/impl/codegen/proto_utils.h include/grpcpp/impl/codegen/proto_buffer_reader.h include/grpcpp/impl/codegen/proto_buffer_writer.h @@ -4438,7 +4433,6 @@ foreach(_hdr include/grpc/impl/codegen/sync_generic.h include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h - include/grpcpp/impl/codegen/sync.h include/grpc++/impl/codegen/proto_utils.h include/grpcpp/impl/codegen/proto_buffer_reader.h include/grpcpp/impl/codegen/proto_buffer_writer.h @@ -4622,7 +4616,6 @@ foreach(_hdr include/grpcpp/server_builder.h include/grpcpp/server_builder_impl.h include/grpcpp/server_context.h - include/grpcpp/server_impl.h include/grpcpp/server_posix.h include/grpcpp/server_posix_impl.h include/grpcpp/support/async_stream.h @@ -4766,7 +4759,6 @@ foreach(_hdr include/grpcpp/impl/codegen/stub_options.h include/grpcpp/impl/codegen/sync_stream.h include/grpcpp/impl/codegen/time.h - include/grpcpp/impl/codegen/sync.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) diff --git a/Makefile b/Makefile index 66f96985bdb..2e6e6070c43 100644 --- a/Makefile +++ b/Makefile @@ -5373,7 +5373,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/server_builder.h \ include/grpcpp/server_builder_impl.h \ include/grpcpp/server_context.h \ - include/grpcpp/server_impl.h \ include/grpcpp/server_posix.h \ include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ @@ -5517,7 +5516,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/stub_options.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ - include/grpcpp/impl/codegen/sync.h \ include/grpc++/impl/codegen/proto_utils.h \ include/grpcpp/impl/codegen/proto_buffer_reader.h \ include/grpcpp/impl/codegen/proto_buffer_writer.h \ @@ -5985,7 +5983,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/server_builder.h \ include/grpcpp/server_builder_impl.h \ include/grpcpp/server_context.h \ - include/grpcpp/server_impl.h \ include/grpcpp/server_posix.h \ include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ @@ -6129,7 +6126,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/stub_options.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ - include/grpcpp/impl/codegen/sync.h \ include/grpc/census.h \ LIBGRPC++_CRONET_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_CRONET_SRC)))) @@ -6556,7 +6552,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ - include/grpcpp/impl/codegen/sync.h \ include/grpc++/impl/codegen/proto_utils.h \ include/grpcpp/impl/codegen/proto_buffer_reader.h \ include/grpcpp/impl/codegen/proto_buffer_writer.h \ @@ -6724,7 +6719,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ - include/grpcpp/impl/codegen/sync.h \ include/grpc++/impl/codegen/proto_utils.h \ include/grpcpp/impl/codegen/proto_buffer_reader.h \ include/grpcpp/impl/codegen/proto_buffer_writer.h \ @@ -6914,7 +6908,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/server_builder.h \ include/grpcpp/server_builder_impl.h \ include/grpcpp/server_context.h \ - include/grpcpp/server_impl.h \ include/grpcpp/server_posix.h \ include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ @@ -7058,7 +7051,6 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/stub_options.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ - include/grpcpp/impl/codegen/sync.h \ LIBGRPC++_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_UNSECURE_SRC)))) diff --git a/build.yaml b/build.yaml index a786546c231..5e8c803e56f 100644 --- a/build.yaml +++ b/build.yaml @@ -196,8 +196,8 @@ filegroups: - src/core/lib/gprpp/manual_constructor.h - src/core/lib/gprpp/map.h - src/core/lib/gprpp/memory.h + - src/core/lib/gprpp/mutex_lock.h - src/core/lib/gprpp/pair.h - - src/core/lib/gprpp/sync.h - src/core/lib/gprpp/thd.h - src/core/lib/profiling/timers.h uses: @@ -1276,7 +1276,6 @@ filegroups: - include/grpcpp/impl/codegen/time.h uses: - grpc_codegen - - grpc++_internal_hdrs_only - name: grpc++_codegen_base_src language: c++ src: @@ -1384,7 +1383,6 @@ filegroups: - include/grpcpp/server_builder.h - include/grpcpp/server_builder_impl.h - include/grpcpp/server_context.h - - include/grpcpp/server_impl.h - include/grpcpp/server_posix.h - include/grpcpp/server_posix_impl.h - include/grpcpp/support/async_stream.h @@ -1452,7 +1450,6 @@ filegroups: - grpc_base_headers - grpc_transport_inproc_headers - grpc++_codegen_base - - grpc++_internal_hdrs_only - nanopb_headers - health_proto - name: grpc++_config_proto @@ -1460,10 +1457,6 @@ filegroups: public_headers: - include/grpc++/impl/codegen/config_protobuf.h - include/grpcpp/impl/codegen/config_protobuf.h -- name: grpc++_internal_hdrs_only - language: c++ - public_headers: - - include/grpcpp/impl/codegen/sync.h - name: grpc++_reflection_proto language: c++ src: diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 7f1ae557537..b8f3f56a83f 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -122,7 +122,6 @@ Pod::Spec.new do |s| 'include/grpcpp/server_builder.h', 'include/grpcpp/server_builder_impl.h', 'include/grpcpp/server_context.h', - 'include/grpcpp/server_impl.h', 'include/grpcpp/server_posix.h', 'include/grpcpp/server_posix_impl.h', 'include/grpcpp/support/async_stream.h', @@ -184,8 +183,7 @@ Pod::Spec.new do |s| 'include/grpcpp/impl/codegen/string_ref.h', 'include/grpcpp/impl/codegen/stub_options.h', 'include/grpcpp/impl/codegen/sync_stream.h', - 'include/grpcpp/impl/codegen/time.h', - 'include/grpcpp/impl/codegen/sync.h' + 'include/grpcpp/impl/codegen/time.h' end s.subspec 'Implementation' do |ss| @@ -268,8 +266,8 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/manual_constructor.h', 'src/core/lib/gprpp/map.h', 'src/core/lib/gprpp/memory.h', + 'src/core/lib/gprpp/mutex_lock.h', 'src/core/lib/gprpp/pair.h', - 'src/core/lib/gprpp/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/ext/transport/chttp2/transport/bin_decoder.h', @@ -585,8 +583,8 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/manual_constructor.h', 'src/core/lib/gprpp/map.h', 'src/core/lib/gprpp/memory.h', + 'src/core/lib/gprpp/mutex_lock.h', 'src/core/lib/gprpp/pair.h', - 'src/core/lib/gprpp/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/lib/avl/avl.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index c58152cf7f8..bab7ce4378e 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -210,8 +210,8 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/manual_constructor.h', 'src/core/lib/gprpp/map.h', 'src/core/lib/gprpp/memory.h', + 'src/core/lib/gprpp/mutex_lock.h', 'src/core/lib/gprpp/pair.h', - 'src/core/lib/gprpp/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/lib/gpr/alloc.cc', @@ -889,8 +889,8 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/manual_constructor.h', 'src/core/lib/gprpp/map.h', 'src/core/lib/gprpp/memory.h', + 'src/core/lib/gprpp/mutex_lock.h', 'src/core/lib/gprpp/pair.h', - 'src/core/lib/gprpp/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/ext/transport/chttp2/transport/bin_decoder.h', diff --git a/grpc.gemspec b/grpc.gemspec index c41db6f6293..b9d2107ee48 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -104,8 +104,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/gprpp/manual_constructor.h ) s.files += %w( src/core/lib/gprpp/map.h ) s.files += %w( src/core/lib/gprpp/memory.h ) + s.files += %w( src/core/lib/gprpp/mutex_lock.h ) s.files += %w( src/core/lib/gprpp/pair.h ) - s.files += %w( src/core/lib/gprpp/sync.h ) s.files += %w( src/core/lib/gprpp/thd.h ) s.files += %w( src/core/lib/profiling/timers.h ) s.files += %w( src/core/lib/gpr/alloc.cc ) diff --git a/include/grpcpp/channel.h b/include/grpcpp/channel.h index c4d5ab1177b..ee833960698 100644 --- a/include/grpcpp/channel.h +++ b/include/grpcpp/channel.h @@ -28,7 +28,6 @@ #include #include #include -#include struct grpc_channel; @@ -98,7 +97,7 @@ class Channel final : public ChannelInterface, grpc_channel* const c_channel_; // owned // mu_ protects callback_cq_ (the per-channel callbackable completion queue) - grpc::internal::Mutex mu_; + std::mutex mu_; // callback_cq_ references the callbackable completion queue associated // with this channel (if any). It is set on the first call to CallbackCQ(). diff --git a/include/grpcpp/impl/codegen/async_generic_service.h b/include/grpcpp/impl/codegen/async_generic_service.h index 46d09121a7b..759f6683bf4 100644 --- a/include/grpcpp/impl/codegen/async_generic_service.h +++ b/include/grpcpp/impl/codegen/async_generic_service.h @@ -39,7 +39,7 @@ class GenericServerContext final : public ServerContext { const grpc::string& host() const { return host_; } private: - friend class grpc_impl::Server; + friend class Server; friend class ServerInterface; void Clear() { @@ -79,8 +79,8 @@ class AsyncGenericService final { ServerCompletionQueue* notification_cq, void* tag); private: - friend class grpc_impl::Server; - grpc_impl::Server* server_; + friend class Server; + Server* server_; }; namespace experimental { @@ -135,14 +135,14 @@ class CallbackGenericService { } private: - friend class ::grpc_impl::Server; + friend class ::grpc::Server; internal::CallbackBidiHandler* Handler() { return new internal::CallbackBidiHandler( [this] { return CreateReactor(); }); } - grpc_impl::Server* server_{nullptr}; + Server* server_{nullptr}; }; } // namespace experimental } // namespace grpc diff --git a/include/grpcpp/impl/codegen/async_stream.h b/include/grpcpp/impl/codegen/async_stream.h index e12923ea02c..bfb2df4f232 100644 --- a/include/grpcpp/impl/codegen/async_stream.h +++ b/include/grpcpp/impl/codegen/async_stream.h @@ -1099,7 +1099,7 @@ class ServerAsyncReaderWriter final } private: - friend class ::grpc_impl::Server; + friend class ::grpc::Server; void BindCall(::grpc::internal::Call* call) override { call_ = *call; } diff --git a/include/grpcpp/impl/codegen/client_context.h b/include/grpcpp/impl/codegen/client_context.h index 85bbf36f06d..5946488566e 100644 --- a/include/grpcpp/impl/codegen/client_context.h +++ b/include/grpcpp/impl/codegen/client_context.h @@ -51,7 +51,6 @@ #include #include #include -#include #include struct census_context; @@ -458,7 +457,7 @@ class ClientContext { bool idempotent_; bool cacheable_; std::shared_ptr channel_; - grpc::internal::Mutex mu_; + std::mutex mu_; grpc_call* call_; bool call_canceled_; gpr_timespec deadline_; diff --git a/include/grpcpp/impl/codegen/completion_queue.h b/include/grpcpp/impl/codegen/completion_queue.h index 85eee6f34bf..73556ce9899 100644 --- a/include/grpcpp/impl/codegen/completion_queue.h +++ b/include/grpcpp/impl/codegen/completion_queue.h @@ -43,9 +43,8 @@ struct grpc_completion_queue; namespace grpc_impl { -class Server; class ServerBuilder; -} // namespace grpc_impl +} namespace grpc { template @@ -67,6 +66,7 @@ class Channel; class ChannelInterface; class ClientContext; class CompletionQueue; +class Server; class ServerContext; class ServerInterface; @@ -274,7 +274,7 @@ class CompletionQueue : private GrpcLibraryCodegen { friend class ::grpc::internal::TemplatedBidiStreamingHandler; template friend class ::grpc::internal::ErrorMethodHandler; - friend class ::grpc_impl::Server; + friend class ::grpc::Server; friend class ::grpc::ServerContext; friend class ::grpc::ServerInterface; template @@ -408,8 +408,8 @@ class ServerCompletionQueue : public CompletionQueue { polling_type_(polling_type) {} grpc_cq_polling_type polling_type_; - friend class grpc_impl::ServerBuilder; - friend class grpc_impl::Server; + friend class ::grpc_impl::ServerBuilder; + friend class Server; }; } // namespace grpc diff --git a/include/grpcpp/impl/codegen/server_context.h b/include/grpcpp/impl/codegen/server_context.h index f65598db41f..591a9ff9549 100644 --- a/include/grpcpp/impl/codegen/server_context.h +++ b/include/grpcpp/impl/codegen/server_context.h @@ -41,14 +41,11 @@ struct grpc_metadata; struct grpc_call; struct census_context; -namespace grpc_impl { - -class Server; -} // namespace grpc_impl namespace grpc { class ClientContext; class GenericServerContext; class CompletionQueue; +class Server; class ServerInterface; template class ServerAsyncReader; @@ -272,7 +269,7 @@ class ServerContext { friend class ::grpc::testing::InteropServerContextInspector; friend class ::grpc::testing::ServerContextTestSpouse; friend class ::grpc::ServerInterface; - friend class ::grpc_impl::Server; + friend class ::grpc::Server; template friend class ::grpc::ServerAsyncReader; template diff --git a/include/grpcpp/impl/codegen/service_type.h b/include/grpcpp/impl/codegen/service_type.h index 1d94abe12dd..332a04c294f 100644 --- a/include/grpcpp/impl/codegen/service_type.h +++ b/include/grpcpp/impl/codegen/service_type.h @@ -26,13 +26,10 @@ #include #include -namespace grpc_impl { - -class Server; -} // namespace grpc_impl namespace grpc { class CompletionQueue; +class Server; class ServerInterface; class ServerCompletionQueue; class ServerContext; @@ -231,7 +228,7 @@ class Service { } private: - friend class grpc_impl::Server; + friend class Server; friend class ServerInterface; ServerInterface* server_; std::vector> methods_; diff --git a/include/grpcpp/impl/codegen/sync.h b/include/grpcpp/impl/codegen/sync.h deleted file mode 100644 index 2ed71eeb9f2..00000000000 --- a/include/grpcpp/impl/codegen/sync.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * - * Copyright 2019 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef GRPCPP_IMPL_CODEGEN_SYNC_H -#define GRPCPP_IMPL_CODEGEN_SYNC_H - -#include -#include -#include - -#include - -// The core library is not accessible in C++ codegen headers, and vice versa. -// Thus, we need to have duplicate headers with similar functionality. -// Make sure any change to this file is also reflected in -// src/core/lib/gprpp/sync.h too. -// -// Whenever possible, prefer "src/core/lib/gprpp/sync.h" over this file, -// since in core we do not rely on g_core_codegen_interface and hence do not -// pay the costs of virtual function calls. - -namespace grpc { -namespace internal { - -class Mutex { - public: - Mutex() { g_core_codegen_interface->gpr_mu_init(&mu_); } - ~Mutex() { g_core_codegen_interface->gpr_mu_destroy(&mu_); } - - Mutex(const Mutex&) = delete; - Mutex& operator=(const Mutex&) = delete; - - gpr_mu* get() { return &mu_; } - const gpr_mu* get() const { return &mu_; } - - private: - gpr_mu mu_; -}; - -// MutexLock is a std:: -class MutexLock { - public: - explicit MutexLock(Mutex* mu) : mu_(mu->get()) { - g_core_codegen_interface->gpr_mu_lock(mu_); - } - explicit MutexLock(gpr_mu* mu) : mu_(mu) { - g_core_codegen_interface->gpr_mu_lock(mu_); - } - ~MutexLock() { g_core_codegen_interface->gpr_mu_unlock(mu_); } - - MutexLock(const MutexLock&) = delete; - MutexLock& operator=(const MutexLock&) = delete; - - private: - gpr_mu* const mu_; -}; - -class ReleasableMutexLock { - public: - explicit ReleasableMutexLock(Mutex* mu) : mu_(mu->get()) { - g_core_codegen_interface->gpr_mu_lock(mu_); - } - explicit ReleasableMutexLock(gpr_mu* mu) : mu_(mu) { - g_core_codegen_interface->gpr_mu_lock(mu_); - } - ~ReleasableMutexLock() { - if (!released_) g_core_codegen_interface->gpr_mu_unlock(mu_); - } - - ReleasableMutexLock(const ReleasableMutexLock&) = delete; - ReleasableMutexLock& operator=(const ReleasableMutexLock&) = delete; - - void Lock() { - GPR_DEBUG_ASSERT(released_); - g_core_codegen_interface->gpr_mu_lock(mu_); - released_ = false; - } - - void Unlock() { - GPR_DEBUG_ASSERT(!released_); - released_ = true; - g_core_codegen_interface->gpr_mu_unlock(mu_); - } - - private: - gpr_mu* const mu_; - bool released_ = false; -}; - -class CondVar { - public: - CondVar() { g_core_codegen_interface->gpr_cv_init(&cv_); } - ~CondVar() { g_core_codegen_interface->gpr_cv_destroy(&cv_); } - - CondVar(const CondVar&) = delete; - CondVar& operator=(const CondVar&) = delete; - - void Signal() { g_core_codegen_interface->gpr_cv_signal(&cv_); } - void Broadcast() { g_core_codegen_interface->gpr_cv_broadcast(&cv_); } - - int Wait(Mutex* mu) { - return Wait(mu, - g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME)); - } - int Wait(Mutex* mu, const gpr_timespec& deadline) { - return g_core_codegen_interface->gpr_cv_wait(&cv_, mu->get(), deadline); - } - - template - void WaitUntil(Mutex* mu, Predicate pred) { - while (!pred()) { - Wait(mu, g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME)); - } - } - - private: - gpr_cv cv_; -}; - -} // namespace internal -} // namespace grpc - -#endif // GRPCPP_IMPL_CODEGEN_SYNC_H diff --git a/include/grpcpp/impl/server_initializer_impl.h b/include/grpcpp/impl/server_initializer_impl.h index 0e2c65f4af4..ff610efa2ac 100644 --- a/include/grpcpp/impl/server_initializer_impl.h +++ b/include/grpcpp/impl/server_initializer_impl.h @@ -26,10 +26,10 @@ namespace grpc { +class Server; class Service; } // namespace grpc namespace grpc_impl { -class Server; class ServerInitializer { public: diff --git a/include/grpcpp/security/server_credentials.h b/include/grpcpp/security/server_credentials.h index 57f733886f4..7e643ae7400 100644 --- a/include/grpcpp/security/server_credentials.h +++ b/include/grpcpp/security/server_credentials.h @@ -21,10 +21,6 @@ #include -namespace grpc_impl { - -class Server; -} // namespace grpc_impl namespace grpc { typedef ::grpc_impl::ServerCredentials ServerCredentials; diff --git a/include/grpcpp/security/server_credentials_impl.h b/include/grpcpp/security/server_credentials_impl.h index f08849097ad..afe8d22650b 100644 --- a/include/grpcpp/security/server_credentials_impl.h +++ b/include/grpcpp/security/server_credentials_impl.h @@ -30,10 +30,10 @@ struct grpc_server; namespace grpc { +class Server; struct SslServerCredentialsOptions; } // namespace grpc namespace grpc_impl { -class Server; /// Wrapper around \a grpc_server_credentials, a way to authenticate a server. class ServerCredentials { @@ -46,7 +46,7 @@ class ServerCredentials { const std::shared_ptr& processor) = 0; private: - friend class ::grpc_impl::Server; + friend class ::grpc::Server; /// Tries to bind \a server to the given \a addr (eg, localhost:1234, /// 192.168.1.1:31416, [::1]:27182, etc.) diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index 3de2aba0b59..2ae9d712012 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -1,6 +1,6 @@ /* * - * Copyright 2019 gRPC authors. + * Copyright 2015 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,11 +19,333 @@ #ifndef GRPCPP_SERVER_H #define GRPCPP_SERVER_H -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct grpc_server; + +namespace grpc_impl { + +class ServerInitializer; +} namespace grpc { -typedef ::grpc_impl::Server Server; +class AsyncGenericService; +class ServerContext; + +/// Represents a gRPC server. +/// +/// Use a \a grpc::ServerBuilder to create, configure, and start +/// \a Server instances. +class Server : public ServerInterface, private GrpcLibraryCodegen { + public: + ~Server(); + + /// Block until the server shuts down. + /// + /// \warning The server must be either shutting down or some other thread must + /// call \a Shutdown for this function to ever return. + void Wait() override; + + /// Global callbacks are a set of hooks that are called when server + /// events occur. \a SetGlobalCallbacks method is used to register + /// the hooks with gRPC. Note that + /// the \a GlobalCallbacks instance will be shared among all + /// \a Server instances in an application and can be set exactly + /// once per application. + class GlobalCallbacks { + public: + virtual ~GlobalCallbacks() {} + /// Called before server is created. + virtual void UpdateArguments(ChannelArguments* args) {} + /// Called before application callback for each synchronous server request + virtual void PreSynchronousRequest(ServerContext* context) = 0; + /// Called after application callback for each synchronous server request + virtual void PostSynchronousRequest(ServerContext* context) = 0; + /// Called before server is started. + virtual void PreServerStart(Server* server) {} + /// Called after a server port is added. + virtual void AddPort(Server* server, const grpc::string& addr, + ServerCredentials* creds, int port) {} + }; + /// Set the global callback object. Can only be called once per application. + /// Does not take ownership of callbacks, and expects the pointed to object + /// to be alive until all server objects in the process have been destroyed. + /// The same \a GlobalCallbacks object will be used throughout the + /// application and is shared among all \a Server objects. + static void SetGlobalCallbacks(GlobalCallbacks* callbacks); + + /// Returns a \em raw pointer to the underlying \a grpc_server instance. + /// EXPERIMENTAL: for internal/test use only + grpc_server* c_server(); + + /// Returns the health check service. + HealthCheckServiceInterface* GetHealthCheckService() const { + return health_check_service_.get(); + } + + /// Establish a channel for in-process communication + std::shared_ptr InProcessChannel(const ChannelArguments& args); + + /// NOTE: class experimental_type is not part of the public API of this class. + /// TODO(yashykt): Integrate into public API when this is no longer + /// experimental. + class experimental_type { + public: + explicit experimental_type(Server* server) : server_(server) {} + + /// Establish a channel for in-process communication with client + /// interceptors + std::shared_ptr InProcessChannelWithInterceptors( + const ChannelArguments& args, + std::vector< + std::unique_ptr> + interceptor_creators); + + private: + Server* server_; + }; + + /// NOTE: The function experimental() is not stable public API. It is a view + /// to the experimental components of this class. It may be changed or removed + /// at any time. + experimental_type experimental() { return experimental_type(this); } + + protected: + /// Register a service. This call does not take ownership of the service. + /// The service must exist for the lifetime of the Server instance. + bool RegisterService(const grpc::string* host, Service* service) override; + + /// Try binding the server to the given \a addr endpoint + /// (port, and optionally including IP address to bind to). + /// + /// It can be invoked multiple times. Should be used before + /// starting the server. + /// + /// \param addr The address to try to bind to the server (eg, localhost:1234, + /// 192.168.1.1:31416, [::1]:27182, etc.). + /// \param creds The credentials associated with the server. + /// + /// \return bound port number on success, 0 on failure. + /// + /// \warning It is an error to call this method on an already started server. + int AddListeningPort(const grpc::string& addr, + ServerCredentials* creds) override; + + /// NOTE: This is *NOT* a public API. The server constructors are supposed to + /// be used by \a ServerBuilder class only. The constructor will be made + /// 'private' very soon. + /// + /// Server constructors. To be used by \a ServerBuilder only. + /// + /// \param max_message_size Maximum message length that the channel can + /// receive. + /// + /// \param args The channel args + /// + /// \param sync_server_cqs The completion queues to use if the server is a + /// synchronous server (or a hybrid server). The server polls for new RPCs on + /// these queues + /// + /// \param min_pollers The minimum number of polling threads per server + /// completion queue (in param sync_server_cqs) to use for listening to + /// incoming requests (used only in case of sync server) + /// + /// \param max_pollers The maximum number of polling threads per server + /// completion queue (in param sync_server_cqs) to use for listening to + /// incoming requests (used only in case of sync server) + /// + /// \param sync_cq_timeout_msec The timeout to use when calling AsyncNext() on + /// server completion queues passed via sync_server_cqs param. + Server(int max_message_size, ChannelArguments* args, + std::shared_ptr>> + sync_server_cqs, + int min_pollers, int max_pollers, int sync_cq_timeout_msec, + grpc_resource_quota* server_rq = nullptr, + std::vector< + std::unique_ptr> + interceptor_creators = std::vector>()); + + /// Start the server. + /// + /// \param cqs Completion queues for handling asynchronous services. The + /// caller is required to keep all completion queues live until the server is + /// destroyed. + /// \param num_cqs How many completion queues does \a cqs hold. + void Start(ServerCompletionQueue** cqs, size_t num_cqs) override; + + grpc_server* server() override { return server_; } + + private: + std::vector>* + interceptor_creators() override { + return &interceptor_creators_; + } + + friend class AsyncGenericService; + friend class grpc_impl::ServerBuilder; + friend class grpc_impl::ServerInitializer; + + class SyncRequest; + class CallbackRequestBase; + template + class CallbackRequest; + class UnimplementedAsyncRequest; + class UnimplementedAsyncResponse; + + /// SyncRequestThreadManager is an implementation of ThreadManager. This class + /// is responsible for polling for incoming RPCs and calling the RPC handlers. + /// This is only used in case of a Sync server (i.e a server exposing a sync + /// interface) + class SyncRequestThreadManager; + + /// Register a generic service. This call does not take ownership of the + /// service. The service must exist for the lifetime of the Server instance. + void RegisterAsyncGenericService(AsyncGenericService* service) override; + + /// NOTE: class experimental_registration_type is not part of the public API + /// of this class + /// TODO(vjpai): Move these contents to the public API of Server when + /// they are no longer experimental + class experimental_registration_type final + : public experimental_registration_interface { + public: + explicit experimental_registration_type(Server* server) : server_(server) {} + void RegisterCallbackGenericService( + experimental::CallbackGenericService* service) override { + server_->RegisterCallbackGenericService(service); + } + + private: + Server* server_; + }; + + /// TODO(vjpai): Mark this override when experimental type above is deleted + void RegisterCallbackGenericService( + experimental::CallbackGenericService* service); + + /// NOTE: The function experimental_registration() is not stable public API. + /// It is a view to the experimental components of this class. It may be + /// changed or removed at any time. + experimental_registration_interface* experimental_registration() override { + return &experimental_registration_; + } + + void PerformOpsOnCall(internal::CallOpSetInterface* ops, + internal::Call* call) override; + + void ShutdownInternal(gpr_timespec deadline) override; + + int max_receive_message_size() const override { + return max_receive_message_size_; + } + + CompletionQueue* CallbackCQ() override; + + grpc_impl::ServerInitializer* initializer(); + + // A vector of interceptor factory objects. + // This should be destroyed after health_check_service_ and this requirement + // is satisfied by declaring interceptor_creators_ before + // health_check_service_. (C++ mandates that member objects be destroyed in + // the reverse order of initialization.) + std::vector> + interceptor_creators_; + + const int max_receive_message_size_; + + /// The following completion queues are ONLY used in case of Sync API + /// i.e. if the server has any services with sync methods. The server uses + /// these completion queues to poll for new RPCs + std::shared_ptr>> + sync_server_cqs_; + + /// List of \a ThreadManager instances (one for each cq in + /// the \a sync_server_cqs) + std::vector> sync_req_mgrs_; + + // Outstanding unmatched callback requests, indexed by method. + // NOTE: Using a gpr_atm rather than atomic_int because atomic_int isn't + // copyable or movable and thus will cause compilation errors. We + // actually only want to extend the vector before the threaded use + // starts, but this is still a limitation. + std::vector callback_unmatched_reqs_count_; + + // List of callback requests to start when server actually starts. + std::list callback_reqs_to_start_; + + // For registering experimental callback generic service; remove when that + // method longer experimental + experimental_registration_type experimental_registration_{this}; + + // Server status + std::mutex mu_; + bool started_; + bool shutdown_; + bool shutdown_notified_; // Was notify called on the shutdown_cv_ + + std::condition_variable shutdown_cv_; + + // It is ok (but not required) to nest callback_reqs_mu_ under mu_ . + // Incrementing callback_reqs_outstanding_ is ok without a lock but it must be + // decremented under the lock in case it is the last request and enables the + // server shutdown. The increment is performance-critical since it happens + // during periods of increasing load; the decrement happens only when memory + // is maxed out, during server shutdown, or (possibly in a future version) + // during decreasing load, so it is less performance-critical. + std::mutex callback_reqs_mu_; + std::condition_variable callback_reqs_done_cv_; + std::atomic_int callback_reqs_outstanding_{0}; + + std::shared_ptr global_callbacks_; + + std::vector services_; + bool has_async_generic_service_{false}; + bool has_callback_generic_service_{false}; + + // Pointer to the wrapped grpc_server. + grpc_server* server_; + + std::unique_ptr server_initializer_; + + std::unique_ptr health_check_service_; + bool health_check_service_disabled_; + + // When appropriate, use a default callback generic service to handle + // unimplemented methods + std::unique_ptr unimplemented_service_; + + // A special handler for resource exhausted in sync case + std::unique_ptr resource_exhausted_handler_; + + // Handler for callback generic service, if any + std::unique_ptr generic_handler_; + + // callback_cq_ references the callbackable completion queue associated + // with this server (if any). It is set on the first call to CallbackCQ(). + // It is _not owned_ by the server; ownership belongs with its internal + // shutdown callback tag (invoked when the CQ is fully shutdown). + // It is protected by mu_ + CompletionQueue* callback_cq_ = nullptr; +}; } // namespace grpc diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h index 89c4eba1d95..33689561825 100644 --- a/include/grpcpp/server_builder.h +++ b/include/grpcpp/server_builder.h @@ -23,7 +23,6 @@ namespace grpc_impl { -class Server; class ServerCredentials; class ResourceQuota; } // namespace grpc_impl diff --git a/include/grpcpp/server_builder_impl.h b/include/grpcpp/server_builder_impl.h index f7624deba5f..25b8091a7df 100644 --- a/include/grpcpp/server_builder_impl.h +++ b/include/grpcpp/server_builder_impl.h @@ -31,7 +31,6 @@ #include #include #include -#include #include struct grpc_resource_quota; @@ -45,6 +44,7 @@ namespace grpc { class AsyncGenericService; class CompletionQueue; +class Server; class ServerCompletionQueue; class Service; diff --git a/include/grpcpp/server_impl.h b/include/grpcpp/server_impl.h index 14b16a06f4e..771a3a10be9 100644 --- a/include/grpcpp/server_impl.h +++ b/include/grpcpp/server_impl.h @@ -304,12 +304,12 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen { experimental_registration_type experimental_registration_{this}; // Server status - grpc::internal::Mutex mu_; + std::mutex mu_; bool started_; bool shutdown_; bool shutdown_notified_; // Was notify called on the shutdown_cv_ - grpc::internal::CondVar shutdown_cv_; + std::condition_variable shutdown_cv_; // It is ok (but not required) to nest callback_reqs_mu_ under mu_ . // Incrementing callback_reqs_outstanding_ is ok without a lock but it must be @@ -318,8 +318,8 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen { // during periods of increasing load; the decrement happens only when memory // is maxed out, during server shutdown, or (possibly in a future version) // during decreasing load, so it is less performance-critical. - grpc::internal::Mutex callback_reqs_mu_; - grpc::internal::CondVar callback_reqs_done_cv_; + std::mutex callback_reqs_mu_; + std::condition_variable callback_reqs_done_cv_; std::atomic_int callback_reqs_outstanding_{0}; std::shared_ptr global_callbacks_; diff --git a/package.xml b/package.xml index 5be3d24365d..f3bbb449ac5 100644 --- a/package.xml +++ b/package.xml @@ -109,8 +109,8 @@ + - diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index cd552739732..86938a51d9b 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -51,7 +51,7 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/manual_constructor.h" -#include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/polling_entity.h" diff --git a/src/core/ext/filters/client_channel/health/health_check_client.cc b/src/core/ext/filters/client_channel/health/health_check_client.cc index a99f1e54062..a22d6450cbd 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.cc +++ b/src/core/ext/filters/client_channel/health/health_check_client.cc @@ -27,7 +27,7 @@ #include "pb_encode.h" #include "src/core/ext/filters/client_channel/health/health.pb.h" #include "src/core/lib/debug/trace.h" -#include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/transport/error_utils.h" #include "src/core/lib/transport/status_metadata.h" @@ -69,6 +69,7 @@ HealthCheckClient::HealthCheckClient( } GRPC_CLOSURE_INIT(&retry_timer_callback_, OnRetryTimer, this, grpc_schedule_on_exec_ctx); + gpr_mu_init(&mu_); StartCall(); } @@ -77,6 +78,7 @@ HealthCheckClient::~HealthCheckClient() { gpr_log(GPR_INFO, "destroying HealthCheckClient %p", this); } GRPC_ERROR_UNREF(error_); + gpr_mu_destroy(&mu_); } void HealthCheckClient::NotifyOnHealthChange(grpc_connectivity_state* state, diff --git a/src/core/ext/filters/client_channel/health/health_check_client.h b/src/core/ext/filters/client_channel/health/health_check_client.h index 6e0123e4925..1fa4487c403 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.h +++ b/src/core/ext/filters/client_channel/health/health_check_client.h @@ -31,7 +31,6 @@ #include "src/core/lib/gprpp/atomic.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" -#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/call_combiner.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/polling_entity.h" @@ -158,7 +157,7 @@ class HealthCheckClient : public InternallyRefCounted { grpc_pollset_set* interested_parties_; // Do not own. RefCountedPtr channelz_node_; - Mutex mu_; + gpr_mu mu_; grpc_connectivity_state state_ = GRPC_CHANNEL_CONNECTING; grpc_error* error_ = GRPC_ERROR_NONE; grpc_connectivity_state* notify_state_ = nullptr; diff --git a/src/core/ext/filters/client_channel/http_connect_handshaker.cc b/src/core/ext/filters/client_channel/http_connect_handshaker.cc index 90a79843458..2b1eb92bbd4 100644 --- a/src/core/ext/filters/client_channel/http_connect_handshaker.cc +++ b/src/core/ext/filters/client_channel/http_connect_handshaker.cc @@ -33,7 +33,7 @@ #include "src/core/lib/channel/handshaker_registry.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" -#include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/http/format_request.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/slice/slice_internal.h" diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index ead15308f49..aebd2fd3faa 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -88,6 +88,7 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/combiner.h" diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc index 35123633feb..84b9c41a734 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc @@ -25,7 +25,7 @@ #include #include -#include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/gprpp/mutex_lock.h" namespace grpc_core { diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h index bcc6598c105..fdebdf55c17 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h @@ -26,7 +26,6 @@ #include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/ref_counted.h" -#include "src/core/lib/gprpp/sync.h" namespace grpc_core { @@ -42,6 +41,9 @@ class GrpcLbClientStats : public RefCounted { typedef InlinedVector DroppedCallCounts; + GrpcLbClientStats() { gpr_mu_init(&drop_count_mu_); } + ~GrpcLbClientStats() { gpr_mu_destroy(&drop_count_mu_); } + void AddCallStarted(); void AddCallFinished(bool finished_with_client_failed_to_send, bool finished_known_received); @@ -64,7 +66,7 @@ class GrpcLbClientStats : public RefCounted { gpr_atm num_calls_finished_ = 0; gpr_atm num_calls_finished_with_client_failed_to_send_ = 0; gpr_atm num_calls_finished_known_received_ = 0; - Mutex drop_count_mu_; // Guards drop_token_counts_. + gpr_mu drop_count_mu_; // Guards drop_token_counts_. UniquePtr drop_token_counts_; }; diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index 892472e1c9b..332f66808e0 100644 --- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -27,7 +27,7 @@ #include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" @@ -154,12 +154,13 @@ class PickFirst : public LoadBalancingPolicy { /// Lock and data used to capture snapshots of this channels child /// channels and subchannels. This data is consumed by channelz. - Mutex child_refs_mu_; + gpr_mu child_refs_mu_; channelz::ChildRefsList child_subchannels_; channelz::ChildRefsList child_channels_; }; PickFirst::PickFirst(Args args) : LoadBalancingPolicy(std::move(args)) { + gpr_mu_init(&child_refs_mu_); if (grpc_lb_pick_first_trace.enabled()) { gpr_log(GPR_INFO, "Pick First %p created.", this); } @@ -169,6 +170,7 @@ PickFirst::~PickFirst() { if (grpc_lb_pick_first_trace.enabled()) { gpr_log(GPR_INFO, "Destroying Pick First %p", this); } + gpr_mu_destroy(&child_refs_mu_); GPR_ASSERT(subchannel_list_ == nullptr); GPR_ASSERT(latest_pending_subchannel_list_ == nullptr); } diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc index 29cfe972f78..d3faaaddc98 100644 --- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc @@ -36,8 +36,8 @@ #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/debug/trace.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" -#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" @@ -193,7 +193,7 @@ class RoundRobin : public LoadBalancingPolicy { bool shutdown_ = false; /// Lock and data used to capture snapshots of this channel's child /// channels and subchannels. This data is consumed by channelz. - Mutex child_refs_mu_; + gpr_mu child_refs_mu_; channelz::ChildRefsList child_subchannels_; channelz::ChildRefsList child_channels_; }; @@ -245,6 +245,7 @@ RoundRobin::PickResult RoundRobin::Picker::Pick(PickArgs* pick, // RoundRobin::RoundRobin(Args args) : LoadBalancingPolicy(std::move(args)) { + gpr_mu_init(&child_refs_mu_); if (grpc_lb_round_robin_trace.enabled()) { gpr_log(GPR_INFO, "[RR %p] Created", this); } @@ -254,6 +255,7 @@ RoundRobin::~RoundRobin() { if (grpc_lb_round_robin_trace.enabled()) { gpr_log(GPR_INFO, "[RR %p] Destroying Round Robin policy", this); } + gpr_mu_destroy(&child_refs_mu_); GPR_ASSERT(subchannel_list_ == nullptr); GPR_ASSERT(latest_pending_subchannel_list_ == nullptr); } diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc b/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc index 443deb01274..fe49e9aca03 100644 --- a/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +++ b/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc @@ -89,9 +89,9 @@ #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/gprpp/map.h" #include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" -#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" @@ -278,8 +278,10 @@ class XdsLb : public LoadBalancingPolicy { class LocalityEntry : public InternallyRefCounted { public: explicit LocalityEntry(RefCountedPtr parent) - : parent_(std::move(parent)) {} - ~LocalityEntry() = default; + : parent_(std::move(parent)) { + gpr_mu_init(&child_policy_mu_); + } + ~LocalityEntry() { gpr_mu_destroy(&child_policy_mu_); } void UpdateLocked(xds_grpclb_serverlist* serverlist, LoadBalancingPolicy::Config* child_policy_config, @@ -321,10 +323,13 @@ class XdsLb : public LoadBalancingPolicy { OrphanablePtr pending_child_policy_; // Lock held when modifying the value of child_policy_ or // pending_child_policy_. - Mutex child_policy_mu_; + gpr_mu child_policy_mu_; RefCountedPtr parent_; }; + LocalityMap() { gpr_mu_init(&child_refs_mu_); } + ~LocalityMap() { gpr_mu_destroy(&child_refs_mu_); } + void UpdateLocked(const LocalityList& locality_list, LoadBalancingPolicy::Config* child_policy_config, const grpc_channel_args* args, XdsLb* parent); @@ -338,7 +343,7 @@ class XdsLb : public LoadBalancingPolicy { Map, OrphanablePtr, StringLess> map_; // Lock held while filling child refs for all localities // inside the map - Mutex child_refs_mu_; + gpr_mu child_refs_mu_; }; struct LocalityServerlistEntry { @@ -392,7 +397,7 @@ class XdsLb : public LoadBalancingPolicy { // Mutex to protect the channel to the LB server. This is used when // processing a channelz request. // TODO(juanlishen): Replace this with atomic. - Mutex lb_chand_mu_; + gpr_mu lb_chand_mu_; // Timeout in milliseconds for the LB call. 0 means no deadline. int lb_call_timeout_ms_ = 0; @@ -1085,6 +1090,7 @@ XdsLb::XdsLb(Args args) : LoadBalancingPolicy(std::move(args)), locality_map_(), locality_serverlist_() { + gpr_mu_init(&lb_chand_mu_); // Record server name. const grpc_arg* arg = grpc_channel_args_find(args.args, GRPC_ARG_SERVER_URI); const char* server_uri = grpc_channel_arg_get_string(arg); @@ -1108,6 +1114,7 @@ XdsLb::XdsLb(Args args) } XdsLb::~XdsLb() { + gpr_mu_destroy(&lb_chand_mu_); gpr_free((void*)server_name_); grpc_channel_args_destroy(args_); locality_serverlist_.clear(); diff --git a/src/core/ext/filters/client_channel/resolving_lb_policy.cc b/src/core/ext/filters/client_channel/resolving_lb_policy.cc index a2367e09d9b..d15af908b3f 100644 --- a/src/core/ext/filters/client_channel/resolving_lb_policy.cc +++ b/src/core/ext/filters/client_channel/resolving_lb_policy.cc @@ -48,7 +48,7 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/manual_constructor.h" -#include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/polling_entity.h" diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index b38bd4b701e..20a6023f71c 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -42,8 +42,8 @@ #include "src/core/lib/gpr/alloc.h" #include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/gprpp/manual_constructor.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" -#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" @@ -457,14 +457,13 @@ struct Subchannel::ExternalStateWatcher { grpc_pollset_set_del_pollset_set(w->subchannel->pollset_set_, w->pollset_set); } - { - MutexLock lock(&w->subchannel->mu_); - if (w->subchannel->external_state_watcher_list_ == w) { - w->subchannel->external_state_watcher_list_ = w->next; - } - if (w->next != nullptr) w->next->prev = w->prev; - if (w->prev != nullptr) w->prev->next = w->next; + gpr_mu_lock(&w->subchannel->mu_); + if (w->subchannel->external_state_watcher_list_ == w) { + w->subchannel->external_state_watcher_list_ = w->next; } + if (w->next != nullptr) w->next->prev = w->prev; + if (w->prev != nullptr) w->prev->next = w->next; + gpr_mu_unlock(&w->subchannel->mu_); GRPC_SUBCHANNEL_WEAK_UNREF(w->subchannel, "external_state_watcher+done"); Delete(w); GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error)); @@ -586,6 +585,7 @@ Subchannel::Subchannel(SubchannelKey* key, grpc_connector* connector, "subchannel"); grpc_connectivity_state_init(&state_and_health_tracker_, GRPC_CHANNEL_IDLE, "subchannel"); + gpr_mu_init(&mu_); // Check whether we should enable health checking. const char* service_config_json = grpc_channel_arg_get_string( grpc_channel_args_find(args_, GRPC_ARG_SERVICE_CONFIG)); @@ -632,6 +632,7 @@ Subchannel::~Subchannel() { grpc_connector_unref(connector_); grpc_pollset_set_destroy(pollset_set_); Delete(key_); + gpr_mu_destroy(&mu_); } Subchannel* Subchannel::Create(grpc_connector* connector, @@ -907,9 +908,7 @@ void Subchannel::MaybeStartConnectingLocked() { void Subchannel::OnRetryAlarm(void* arg, grpc_error* error) { Subchannel* c = static_cast(arg); - // TODO(soheilhy): Once subchannel refcounting is simplified, we can get use - // MutexLock instead of ReleasableMutexLock, here. - ReleasableMutexLock lock(&c->mu_); + gpr_mu_lock(&c->mu_); c->have_retry_alarm_ = false; if (c->disconnected_) { error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected", @@ -923,9 +922,9 @@ void Subchannel::OnRetryAlarm(void* arg, grpc_error* error) { if (error == GRPC_ERROR_NONE) { gpr_log(GPR_INFO, "Failed to connect to channel, retrying"); c->ContinueConnectingLocked(); - lock.Unlock(); + gpr_mu_unlock(&c->mu_); } else { - lock.Unlock(); + gpr_mu_unlock(&c->mu_); GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); } GRPC_ERROR_UNREF(error); @@ -952,30 +951,29 @@ void Subchannel::OnConnectingFinished(void* arg, grpc_error* error) { auto* c = static_cast(arg); grpc_channel_args* delete_channel_args = c->connecting_result_.channel_args; GRPC_SUBCHANNEL_WEAK_REF(c, "on_connecting_finished"); - { - MutexLock lock(&c->mu_); - c->connecting_ = false; - if (c->connecting_result_.transport != nullptr && - c->PublishTransportLocked()) { - // Do nothing, transport was published. - } else if (c->disconnected_) { - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); - } else { - const char* errmsg = grpc_error_string(error); - gpr_log(GPR_INFO, "Connect failed: %s", errmsg); - error = grpc_error_set_int( - GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Connect Failed", - &error, 1), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); - c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, - GRPC_ERROR_REF(error), "connect_failed"); - grpc_connectivity_state_set(&c->state_and_health_tracker_, - GRPC_CHANNEL_TRANSIENT_FAILURE, error, - "connect_failed"); - c->MaybeStartConnectingLocked(); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); - } + gpr_mu_lock(&c->mu_); + c->connecting_ = false; + if (c->connecting_result_.transport != nullptr && + c->PublishTransportLocked()) { + // Do nothing, transport was published. + } else if (c->disconnected_) { + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + } else { + const char* errmsg = grpc_error_string(error); + gpr_log(GPR_INFO, "Connect failed: %s", errmsg); + error = + grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Connect Failed", &error, 1), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); + c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, + GRPC_ERROR_REF(error), "connect_failed"); + grpc_connectivity_state_set(&c->state_and_health_tracker_, + GRPC_CHANNEL_TRANSIENT_FAILURE, error, + "connect_failed"); + c->MaybeStartConnectingLocked(); + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); } + gpr_mu_unlock(&c->mu_); GRPC_SUBCHANNEL_WEAK_UNREF(c, "on_connecting_finished"); grpc_channel_args_destroy(delete_channel_args); } diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 83b57dd7ff3..968fc74e22a 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -29,7 +29,6 @@ #include "src/core/lib/gpr/arena.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" -#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/transport/connectivity_state.h" @@ -265,7 +264,7 @@ class Subchannel { // pollset_set tracking who's interested in a connection being setup. grpc_pollset_set* pollset_set_; // Protects the other members. - Mutex mu_; + gpr_mu mu_; // Refcount // - lower INTERNAL_REF_BITS bits are for internal references: // these do not keep the subchannel open. diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index b6a660b18fd..9f0169aeaab 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -23,7 +23,7 @@ #include "src/core/lib/channel/channelz_registry.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/memory.h" -#include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include #include diff --git a/src/core/lib/channel/handshaker.h b/src/core/lib/channel/handshaker.h index b68799b6e0e..912d524c8db 100644 --- a/src/core/lib/channel/handshaker.h +++ b/src/core/lib/channel/handshaker.h @@ -27,8 +27,8 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/ref_counted.h" -#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/exec_ctx.h" diff --git a/src/core/lib/gprpp/mutex_lock.h b/src/core/lib/gprpp/mutex_lock.h new file mode 100644 index 00000000000..54751d5fe46 --- /dev/null +++ b/src/core/lib/gprpp/mutex_lock.h @@ -0,0 +1,42 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_GPRPP_MUTEX_LOCK_H +#define GRPC_CORE_LIB_GPRPP_MUTEX_LOCK_H + +#include + +#include + +namespace grpc_core { + +class MutexLock { + public: + explicit MutexLock(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu); } + ~MutexLock() { gpr_mu_unlock(mu_); } + + MutexLock(const MutexLock&) = delete; + MutexLock& operator=(const MutexLock&) = delete; + + private: + gpr_mu* const mu_; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_GPRPP_MUTEX_LOCK_H */ diff --git a/src/core/lib/gprpp/sync.h b/src/core/lib/gprpp/sync.h deleted file mode 100644 index 895ca60fec0..00000000000 --- a/src/core/lib/gprpp/sync.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * - * Copyright 2019 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef GRPC_CORE_LIB_GPRPP_SYNC_H -#define GRPC_CORE_LIB_GPRPP_SYNC_H - -#include - -#include -#include -#include -#include - -// The core library is not accessible in C++ codegen headers, and vice versa. -// Thus, we need to have duplicate headers with similar functionality. -// Make sure any change to this file is also reflected in -// include/grpcpp/impl/codegen/sync.h. -// -// Whenever possible, prefer using this file over -// since this file doesn't rely on g_core_codegen_interface and hence does not -// pay the costs of virtual function calls. - -namespace grpc_core { - -class Mutex { - public: - Mutex() { gpr_mu_init(&mu_); } - ~Mutex() { gpr_mu_destroy(&mu_); } - - Mutex(const Mutex&) = delete; - Mutex& operator=(const Mutex&) = delete; - - gpr_mu* get() { return &mu_; } - const gpr_mu* get() const { return &mu_; } - - private: - gpr_mu mu_; -}; - -// MutexLock is a std:: -class MutexLock { - public: - explicit MutexLock(Mutex* mu) : mu_(mu->get()) { gpr_mu_lock(mu_); } - explicit MutexLock(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu_); } - ~MutexLock() { gpr_mu_unlock(mu_); } - - MutexLock(const MutexLock&) = delete; - MutexLock& operator=(const MutexLock&) = delete; - - private: - gpr_mu* const mu_; -}; - -class ReleasableMutexLock { - public: - explicit ReleasableMutexLock(Mutex* mu) : mu_(mu->get()) { gpr_mu_lock(mu_); } - explicit ReleasableMutexLock(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu_); } - ~ReleasableMutexLock() { - if (!released_) gpr_mu_unlock(mu_); - } - - ReleasableMutexLock(const ReleasableMutexLock&) = delete; - ReleasableMutexLock& operator=(const ReleasableMutexLock&) = delete; - - void Lock() { - GPR_DEBUG_ASSERT(released_); - gpr_mu_lock(mu_); - released_ = false; - } - - void Unlock() { - GPR_DEBUG_ASSERT(!released_); - released_ = true; - gpr_mu_unlock(mu_); - } - - private: - gpr_mu* const mu_; - bool released_ = false; -}; - -class CondVar { - public: - CondVar() { gpr_cv_init(&cv_); } - ~CondVar() { gpr_cv_destroy(&cv_); } - - CondVar(const CondVar&) = delete; - CondVar& operator=(const CondVar&) = delete; - - void Signal() { gpr_cv_signal(&cv_); } - void Broadcast() { gpr_cv_broadcast(&cv_); } - - int Wait(Mutex* mu) { return Wait(mu, gpr_inf_future(GPR_CLOCK_REALTIME)); } - int Wait(Mutex* mu, const gpr_timespec& deadline) { - return gpr_cv_wait(&cv_, mu->get(), deadline); - } - - template - void WaitUntil(Mutex* mu, Predicate pred) { - while (!pred()) { - Wait(mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - } - - private: - gpr_cv cv_; -}; - -} // namespace grpc_core - -#endif /* GRPC_CORE_LIB_GPRPP_SYNC_H */ diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc index c387f8359a0..01be46c9f68 100644 --- a/src/core/lib/iomgr/ev_epollex_linux.cc +++ b/src/core/lib/iomgr/ev_epollex_linux.cc @@ -47,7 +47,7 @@ #include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/manual_constructor.h" -#include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/iomgr/block_annotate.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/is_epollexclusive_available.h" diff --git a/src/core/lib/surface/init.cc b/src/core/lib/surface/init.cc index 57d975564b1..b67d4f12252 100644 --- a/src/core/lib/surface/init.cc +++ b/src/core/lib/surface/init.cc @@ -33,7 +33,7 @@ #include "src/core/lib/debug/stats.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/gprpp/fork.h" -#include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/call_combiner.h" #include "src/core/lib/iomgr/combiner.h" diff --git a/src/core/tsi/ssl/session_cache/ssl_session_cache.cc b/src/core/tsi/ssl/session_cache/ssl_session_cache.cc index ba0745a2359..f9184bcc34f 100644 --- a/src/core/tsi/ssl/session_cache/ssl_session_cache.cc +++ b/src/core/tsi/ssl/session_cache/ssl_session_cache.cc @@ -18,7 +18,7 @@ #include -#include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/tsi/ssl/session_cache/ssl_session.h" #include "src/core/tsi/ssl/session_cache/ssl_session_cache.h" diff --git a/src/cpp/client/channel_cc.cc b/src/cpp/client/channel_cc.cc index 2d5e74163a9..db59d4d8416 100644 --- a/src/cpp/client/channel_cc.cc +++ b/src/cpp/client/channel_cc.cc @@ -232,7 +232,7 @@ class ShutdownCallback : public grpc_experimental_completion_queue_functor { CompletionQueue* Channel::CallbackCQ() { // TODO(vjpai): Consider using a single global CQ for the default CQ // if there is no explicit per-channel CQ registered - grpc::internal::MutexLock l(&mu_); + std::lock_guard l(mu_); if (callback_cq_ == nullptr) { auto* shutdown_callback = new ShutdownCallback; callback_cq_ = new CompletionQueue(grpc_completion_queue_attributes{ diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc index b4fce79b99a..efb59c71a8c 100644 --- a/src/cpp/client/client_context.cc +++ b/src/cpp/client/client_context.cc @@ -25,7 +25,6 @@ #include #include -#include #include #include #include @@ -85,7 +84,7 @@ void ClientContext::AddMetadata(const grpc::string& meta_key, void ClientContext::set_call(grpc_call* call, const std::shared_ptr& channel) { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); GPR_ASSERT(call_ == nullptr); call_ = call; channel_ = channel; @@ -115,7 +114,7 @@ void ClientContext::set_compression_algorithm( } void ClientContext::TryCancel() { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); if (call_) { SendCancelToInterceptors(); grpc_call_cancel(call_, nullptr); diff --git a/src/cpp/server/dynamic_thread_pool.cc b/src/cpp/server/dynamic_thread_pool.cc index c8bdbdea7e6..ef99d6459f7 100644 --- a/src/cpp/server/dynamic_thread_pool.cc +++ b/src/cpp/server/dynamic_thread_pool.cc @@ -21,7 +21,6 @@ #include #include -#include #include "src/core/lib/gprpp/thd.h" @@ -41,27 +40,27 @@ DynamicThreadPool::DynamicThread::~DynamicThread() { thd_.Join(); } void DynamicThreadPool::DynamicThread::ThreadFunc() { pool_->ThreadFunc(); // Now that we have killed ourselves, we should reduce the thread count - grpc_core::MutexLock lock(&pool_->mu_); + std::unique_lock lock(pool_->mu_); pool_->nthreads_--; // Move ourselves to dead list pool_->dead_threads_.push_back(this); if ((pool_->shutdown_) && (pool_->nthreads_ == 0)) { - pool_->shutdown_cv_.Signal(); + pool_->shutdown_cv_.notify_one(); } } void DynamicThreadPool::ThreadFunc() { for (;;) { // Wait until work is available or we are shutting down. - grpc_core::ReleasableMutexLock lock(&mu_); + std::unique_lock lock(mu_); if (!shutdown_ && callbacks_.empty()) { // If there are too many threads waiting, then quit this thread if (threads_waiting_ >= reserve_threads_) { break; } threads_waiting_++; - cv_.Wait(&mu_); + cv_.wait(lock); threads_waiting_--; } // Drain callbacks before considering shutdown to ensure all work @@ -69,7 +68,7 @@ void DynamicThreadPool::ThreadFunc() { if (!callbacks_.empty()) { auto cb = callbacks_.front(); callbacks_.pop(); - lock.Unlock(); + lock.unlock(); cb(); } else if (shutdown_) { break; @@ -83,7 +82,7 @@ DynamicThreadPool::DynamicThreadPool(int reserve_threads) nthreads_(0), threads_waiting_(0) { for (int i = 0; i < reserve_threads_; i++) { - grpc_core::MutexLock lock(&mu_); + std::lock_guard lock(mu_); nthreads_++; new DynamicThread(this); } @@ -96,17 +95,17 @@ void DynamicThreadPool::ReapThreads(std::list* tlist) { } DynamicThreadPool::~DynamicThreadPool() { - grpc_core::MutexLock lock(&mu_); + std::unique_lock lock(mu_); shutdown_ = true; - cv_.Broadcast(); + cv_.notify_all(); while (nthreads_ != 0) { - shutdown_cv_.Wait(&mu_); + shutdown_cv_.wait(lock); } ReapThreads(&dead_threads_); } void DynamicThreadPool::Add(const std::function& callback) { - grpc_core::MutexLock lock(&mu_); + std::lock_guard lock(mu_); // Add works to the callbacks list callbacks_.push(callback); // Increase pool size or notify as needed @@ -115,7 +114,7 @@ void DynamicThreadPool::Add(const std::function& callback) { nthreads_++; new DynamicThread(this); } else { - cv_.Signal(); + cv_.notify_one(); } // Also use this chance to harvest dead threads if (!dead_threads_.empty()) { diff --git a/src/cpp/server/dynamic_thread_pool.h b/src/cpp/server/dynamic_thread_pool.h index 4ae0257d40b..5df8cf2b043 100644 --- a/src/cpp/server/dynamic_thread_pool.h +++ b/src/cpp/server/dynamic_thread_pool.h @@ -27,7 +27,6 @@ #include -#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/thd.h" #include "src/cpp/server/thread_pool_interface.h" @@ -51,9 +50,9 @@ class DynamicThreadPool final : public ThreadPoolInterface { grpc_core::Thread thd_; void ThreadFunc(); }; - grpc_core::Mutex mu_; - grpc_core::CondVar cv_; - grpc_core::CondVar shutdown_cv_; + std::mutex mu_; + std::condition_variable cv_; + std::condition_variable shutdown_cv_; bool shutdown_; std::queue> callbacks_; int reserve_threads_; diff --git a/src/cpp/server/health/default_health_check_service.cc b/src/cpp/server/health/default_health_check_service.cc index 01bc51aa213..44aebd2f9d9 100644 --- a/src/cpp/server/health/default_health_check_service.cc +++ b/src/cpp/server/health/default_health_check_service.cc @@ -41,7 +41,7 @@ DefaultHealthCheckService::DefaultHealthCheckService() { void DefaultHealthCheckService::SetServingStatus( const grpc::string& service_name, bool serving) { - grpc_core::MutexLock lock(&mu_); + std::unique_lock lock(mu_); if (shutdown_) { // Set to NOT_SERVING in case service_name is not in the map. serving = false; @@ -51,7 +51,7 @@ void DefaultHealthCheckService::SetServingStatus( void DefaultHealthCheckService::SetServingStatus(bool serving) { const ServingStatus status = serving ? SERVING : NOT_SERVING; - grpc_core::MutexLock lock(&mu_); + std::unique_lock lock(mu_); if (shutdown_) { return; } @@ -62,7 +62,7 @@ void DefaultHealthCheckService::SetServingStatus(bool serving) { } void DefaultHealthCheckService::Shutdown() { - grpc_core::MutexLock lock(&mu_); + std::unique_lock lock(mu_); if (shutdown_) { return; } @@ -76,7 +76,7 @@ void DefaultHealthCheckService::Shutdown() { DefaultHealthCheckService::ServingStatus DefaultHealthCheckService::GetServingStatus( const grpc::string& service_name) const { - grpc_core::MutexLock lock(&mu_); + std::lock_guard lock(mu_); auto it = services_map_.find(service_name); if (it == services_map_.end()) { return NOT_FOUND; @@ -88,7 +88,7 @@ DefaultHealthCheckService::GetServingStatus( void DefaultHealthCheckService::RegisterCallHandler( const grpc::string& service_name, std::shared_ptr handler) { - grpc_core::MutexLock lock(&mu_); + std::unique_lock lock(mu_); ServiceData& service_data = services_map_[service_name]; service_data.AddCallHandler(handler /* copies ref */); HealthCheckServiceImpl::CallHandler* h = handler.get(); @@ -98,7 +98,7 @@ void DefaultHealthCheckService::RegisterCallHandler( void DefaultHealthCheckService::UnregisterCallHandler( const grpc::string& service_name, const std::shared_ptr& handler) { - grpc_core::MutexLock lock(&mu_); + std::unique_lock lock(mu_); auto it = services_map_.find(service_name); if (it == services_map_.end()) return; ServiceData& service_data = it->second; @@ -166,7 +166,7 @@ DefaultHealthCheckService::HealthCheckServiceImpl::~HealthCheckServiceImpl() { // We will reach here after the server starts shutting down. shutdown_ = true; { - grpc_core::MutexLock lock(&cq_shutdown_mu_); + std::unique_lock lock(cq_shutdown_mu_); cq_->Shutdown(); } thread_->Join(); @@ -266,7 +266,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::CheckCallHandler:: std::make_shared(cq, database, service); CheckCallHandler* handler = static_cast(self.get()); { - grpc_core::MutexLock lock(&service->cq_shutdown_mu_); + std::unique_lock lock(service->cq_shutdown_mu_); if (service->shutdown_) return; // Request a Check() call. handler->next_ = @@ -311,7 +311,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::CheckCallHandler:: } // Send response. { - grpc_core::MutexLock lock(&service_->cq_shutdown_mu_); + std::unique_lock lock(service_->cq_shutdown_mu_); if (!service_->shutdown_) { next_ = CallableTag(std::bind(&CheckCallHandler::OnFinishDone, this, @@ -347,7 +347,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: std::make_shared(cq, database, service); WatchCallHandler* handler = static_cast(self.get()); { - grpc_core::MutexLock lock(&service->cq_shutdown_mu_); + std::unique_lock lock(service->cq_shutdown_mu_); if (service->shutdown_) return; // Request AsyncNotifyWhenDone(). handler->on_done_notified_ = @@ -402,7 +402,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: SendHealth(std::shared_ptr self, ServingStatus status) { - grpc_core::MutexLock lock(&send_mu_); + std::unique_lock lock(send_mu_); // If there's already a send in flight, cache the new status, and // we'll start a new send for it when the one in flight completes. if (send_in_flight_) { @@ -420,7 +420,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: ByteBuffer response; bool success = service_->EncodeResponse(status, &response); // Grab shutdown lock and send response. - grpc_core::MutexLock cq_lock(&service_->cq_shutdown_mu_); + std::unique_lock cq_lock(service_->cq_shutdown_mu_); if (service_->shutdown_) { SendFinishLocked(std::move(self), Status::CANCELLED); return; @@ -442,7 +442,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: SendFinish(std::move(self), Status::CANCELLED); return; } - grpc_core::MutexLock lock(&send_mu_); + std::unique_lock lock(send_mu_); send_in_flight_ = false; // If we got a new status since we started the last send, start a // new send for it. @@ -456,7 +456,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: SendFinish(std::shared_ptr self, const Status& status) { if (finish_called_) return; - grpc_core::MutexLock cq_lock(&service_->cq_shutdown_mu_); + std::unique_lock cq_lock(service_->cq_shutdown_mu_); if (service_->shutdown_) return; SendFinishLocked(std::move(self), status); } diff --git a/src/cpp/server/health/default_health_check_service.h b/src/cpp/server/health/default_health_check_service.h index 4b926efdfe8..9551cd2e2cf 100644 --- a/src/cpp/server/health/default_health_check_service.h +++ b/src/cpp/server/health/default_health_check_service.h @@ -31,7 +31,6 @@ #include #include -#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/thd.h" namespace grpc { @@ -198,7 +197,7 @@ class DefaultHealthCheckService final : public HealthCheckServiceInterface { GenericServerAsyncWriter stream_; ServerContext ctx_; - grpc_core::Mutex send_mu_; + std::mutex send_mu_; bool send_in_flight_ = false; // Guarded by mu_. ServingStatus pending_status_ = NOT_FOUND; // Guarded by mu_. @@ -227,7 +226,7 @@ class DefaultHealthCheckService final : public HealthCheckServiceInterface { // To synchronize the operations related to shutdown state of cq_, so that // we don't enqueue new tags into cq_ after it is already shut down. - grpc_core::Mutex cq_shutdown_mu_; + std::mutex cq_shutdown_mu_; std::atomic_bool shutdown_{false}; std::unique_ptr<::grpc_core::Thread> thread_; }; @@ -274,7 +273,7 @@ class DefaultHealthCheckService final : public HealthCheckServiceInterface { const grpc::string& service_name, const std::shared_ptr& handler); - mutable grpc_core::Mutex mu_; + mutable std::mutex mu_; bool shutdown_ = false; // Guarded by mu_. std::map services_map_; // Guarded by mu_. std::unique_ptr impl_; diff --git a/src/cpp/server/load_reporter/load_reporter.cc b/src/cpp/server/load_reporter/load_reporter.cc index 422ea62efd5..464063a13ff 100644 --- a/src/cpp/server/load_reporter/load_reporter.cc +++ b/src/cpp/server/load_reporter/load_reporter.cc @@ -239,7 +239,7 @@ grpc::string LoadReporter::GenerateLbId() { ::grpc::lb::v1::LoadBalancingFeedback LoadReporter::GenerateLoadBalancingFeedback() { - grpc_core::ReleasableMutexLock lock(&feedback_mu_); + std::unique_lock lock(feedback_mu_); auto now = std::chrono::system_clock::now(); // Discard records outside the window until there is only one record // outside the window, which is used as the base for difference. @@ -277,7 +277,7 @@ LoadReporter::GenerateLoadBalancingFeedback() { double cpu_limit = newest->cpu_limit - oldest->cpu_limit; std::chrono::duration duration_seconds = newest->end_time - oldest->end_time; - lock.Unlock(); + lock.unlock(); ::grpc::lb::v1::LoadBalancingFeedback feedback; feedback.set_server_utilization(static_cast(cpu_usage / cpu_limit)); feedback.set_calls_per_second( @@ -290,7 +290,7 @@ LoadReporter::GenerateLoadBalancingFeedback() { ::google::protobuf::RepeatedPtrField<::grpc::lb::v1::Load> LoadReporter::GenerateLoads(const grpc::string& hostname, const grpc::string& lb_id) { - grpc_core::MutexLock lock(&store_mu_); + std::lock_guard lock(store_mu_); auto assigned_stores = load_data_store_.GetAssignedStores(hostname, lb_id); GPR_ASSERT(assigned_stores != nullptr); GPR_ASSERT(!assigned_stores->empty()); @@ -371,7 +371,7 @@ void LoadReporter::AppendNewFeedbackRecord(uint64_t rpcs, uint64_t errors) { // This will make the load balancing feedback generation a no-op. cpu_stats = {0, 0}; } - grpc_core::MutexLock lock(&feedback_mu_); + std::unique_lock lock(feedback_mu_); feedback_records_.emplace_back(std::chrono::system_clock::now(), rpcs, errors, cpu_stats.first, cpu_stats.second); } @@ -379,7 +379,7 @@ void LoadReporter::AppendNewFeedbackRecord(uint64_t rpcs, uint64_t errors) { void LoadReporter::ReportStreamCreated(const grpc::string& hostname, const grpc::string& lb_id, const grpc::string& load_key) { - grpc_core::MutexLock lock(&store_mu_); + std::lock_guard lock(store_mu_); load_data_store_.ReportStreamCreated(hostname, lb_id, load_key); gpr_log(GPR_INFO, "[LR %p] Report stream created (host: %s, LB ID: %s, load key: %s).", @@ -388,7 +388,7 @@ void LoadReporter::ReportStreamCreated(const grpc::string& hostname, void LoadReporter::ReportStreamClosed(const grpc::string& hostname, const grpc::string& lb_id) { - grpc_core::MutexLock lock(&store_mu_); + std::lock_guard lock(store_mu_); load_data_store_.ReportStreamClosed(hostname, lb_id); gpr_log(GPR_INFO, "[LR %p] Report stream closed (host: %s, LB ID: %s).", this, hostname.c_str(), lb_id.c_str()); @@ -407,7 +407,7 @@ void LoadReporter::ProcessViewDataCallStart( LoadRecordKey key(client_ip_and_token, user_id); LoadRecordValue value = LoadRecordValue(start_count); { - grpc_core::MutexLock lock(&store_mu_); + std::unique_lock lock(store_mu_); load_data_store_.MergeRow(host, key, value); } } @@ -459,7 +459,7 @@ void LoadReporter::ProcessViewDataCallEnd( LoadRecordValue value = LoadRecordValue( 0, ok_count, error_count, bytes_sent, bytes_received, latency_ms); { - grpc_core::MutexLock lock(&store_mu_); + std::unique_lock lock(store_mu_); load_data_store_.MergeRow(host, key, value); } } @@ -486,7 +486,7 @@ void LoadReporter::ProcessViewDataOtherCallMetrics( LoadRecordValue value = LoadRecordValue( metric_name, static_cast(num_calls), total_metric_value); { - grpc_core::MutexLock lock(&store_mu_); + std::unique_lock lock(store_mu_); load_data_store_.MergeRow(host, key, value); } } diff --git a/src/cpp/server/load_reporter/load_reporter.h b/src/cpp/server/load_reporter/load_reporter.h index 766e02a407a..b2254d56016 100644 --- a/src/cpp/server/load_reporter/load_reporter.h +++ b/src/cpp/server/load_reporter/load_reporter.h @@ -29,7 +29,6 @@ #include #include -#include "src/core/lib/gprpp/sync.h" #include "src/cpp/server/load_reporter/load_data_store.h" #include "src/proto/grpc/lb/v1/load_reporter.grpc.pb.h" @@ -213,11 +212,11 @@ class LoadReporter { std::atomic next_lb_id_{0}; const std::chrono::seconds feedback_sample_window_seconds_; - grpc_core::Mutex feedback_mu_; + std::mutex feedback_mu_; std::deque feedback_records_; // TODO(juanlishen): Lock in finer grain. Locking the whole store may be // too expensive. - grpc_core::Mutex store_mu_; + std::mutex store_mu_; LoadDataStore load_data_store_; std::unique_ptr census_view_provider_; std::unique_ptr cpu_stats_provider_; diff --git a/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc b/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc index 9eaab5d6366..859ad9946c8 100644 --- a/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc +++ b/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc @@ -48,7 +48,7 @@ LoadReporterAsyncServiceImpl::~LoadReporterAsyncServiceImpl() { // We will reach here after the server starts shutting down. shutdown_ = true; { - grpc_core::MutexLock lock(&cq_shutdown_mu_); + std::unique_lock lock(cq_shutdown_mu_); cq_->Shutdown(); } if (next_fetch_and_sample_alarm_ != nullptr) @@ -62,7 +62,7 @@ void LoadReporterAsyncServiceImpl::ScheduleNextFetchAndSample() { gpr_time_from_millis(kFetchAndSampleIntervalSeconds * 1000, GPR_TIMESPAN)); { - grpc_core::MutexLock lock(&cq_shutdown_mu_); + std::unique_lock lock(cq_shutdown_mu_); if (shutdown_) return; // TODO(juanlishen): Improve the Alarm implementation to reuse a single // instance for multiple events. @@ -119,7 +119,7 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::CreateAndStart( std::make_shared(cq, service, load_reporter); ReportLoadHandler* p = handler.get(); { - grpc_core::MutexLock lock(&service->cq_shutdown_mu_); + std::unique_lock lock(service->cq_shutdown_mu_); if (service->shutdown_) return; p->on_done_notified_ = CallableTag(std::bind(&ReportLoadHandler::OnDoneNotified, p, @@ -164,9 +164,9 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::OnRequestDelivered( // instance will deallocate itself when it's done. CreateAndStart(cq_, service_, load_reporter_); { - grpc_core::ReleasableMutexLock lock(&service_->cq_shutdown_mu_); + std::unique_lock lock(service_->cq_shutdown_mu_); if (service_->shutdown_) { - lock.Unlock(); + lock.release()->unlock(); Shutdown(std::move(self), "OnRequestDelivered"); return; } @@ -222,9 +222,9 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::OnReadDone( SendReport(self, true /* ok */); // Expect this read to fail. { - grpc_core::ReleasableMutexLock lock(&service_->cq_shutdown_mu_); + std::unique_lock lock(service_->cq_shutdown_mu_); if (service_->shutdown_) { - lock.Unlock(); + lock.release()->unlock(); Shutdown(std::move(self), "OnReadDone"); return; } @@ -254,9 +254,9 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::ScheduleNextReport( gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_millis(load_report_interval_ms_, GPR_TIMESPAN)); { - grpc_core::ReleasableMutexLock lock(&service_->cq_shutdown_mu_); + std::unique_lock lock(service_->cq_shutdown_mu_); if (service_->shutdown_) { - lock.Unlock(); + lock.release()->unlock(); Shutdown(std::move(self), "ScheduleNextReport"); return; } @@ -294,9 +294,9 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::SendReport( call_status_ = INITIAL_RESPONSE_SENT; } { - grpc_core::ReleasableMutexLock lock(&service_->cq_shutdown_mu_); + std::unique_lock lock(service_->cq_shutdown_mu_); if (service_->shutdown_) { - lock.Unlock(); + lock.release()->unlock(); Shutdown(std::move(self), "SendReport"); return; } @@ -342,7 +342,7 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::Shutdown( // OnRequestDelivered() may be called after OnDoneNotified(), so we need to // try to Finish() every time we are in Shutdown(). if (call_status_ >= DELIVERED && call_status_ < FINISH_CALLED) { - grpc_core::MutexLock lock(&service_->cq_shutdown_mu_); + std::unique_lock lock(service_->cq_shutdown_mu_); if (!service_->shutdown_) { on_finish_done_ = CallableTag(std::bind(&ReportLoadHandler::OnFinishDone, this, diff --git a/src/cpp/server/load_reporter/load_reporter_async_service_impl.h b/src/cpp/server/load_reporter/load_reporter_async_service_impl.h index 3087cbfc04d..6fc577ff493 100644 --- a/src/cpp/server/load_reporter/load_reporter_async_service_impl.h +++ b/src/cpp/server/load_reporter/load_reporter_async_service_impl.h @@ -25,7 +25,6 @@ #include #include -#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/thd.h" #include "src/cpp/server/load_reporter/load_reporter.h" @@ -182,7 +181,7 @@ class LoadReporterAsyncServiceImpl std::unique_ptr cq_; // To synchronize the operations related to shutdown state of cq_, so that we // don't enqueue new tags into cq_ after it is already shut down. - grpc_core::Mutex cq_shutdown_mu_; + std::mutex cq_shutdown_mu_; std::atomic_bool shutdown_{false}; std::unique_ptr<::grpc_core::Thread> thread_; std::unique_ptr load_reporter_; diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 4f0fdefceda..aa9fdac9bea 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -106,6 +106,1029 @@ class UnimplementedAsyncRequestContext { } // namespace +/// Use private inheritance rather than composition only to establish order +/// of construction, since the public base class should be constructed after the +/// elements belonging to the private base class are constructed. This is not +/// possible using true composition. +class Server::UnimplementedAsyncRequest final + : private UnimplementedAsyncRequestContext, + public GenericAsyncRequest { + public: + UnimplementedAsyncRequest(Server* server, ServerCompletionQueue* cq) + : GenericAsyncRequest(server, &server_context_, &generic_stream_, cq, cq, + nullptr, false), + server_(server), + cq_(cq) {} + + bool FinalizeResult(void** tag, bool* status) override; + + ServerContext* context() { return &server_context_; } + GenericServerAsyncReaderWriter* stream() { return &generic_stream_; } + + private: + Server* const server_; + ServerCompletionQueue* const cq_; +}; + +/// UnimplementedAsyncResponse should not post user-visible completions to the +/// C++ completion queue, but is generated as a CQ event by the core +class Server::UnimplementedAsyncResponse final + : public internal::CallOpSet { + public: + UnimplementedAsyncResponse(UnimplementedAsyncRequest* request); + ~UnimplementedAsyncResponse() { delete request_; } + + bool FinalizeResult(void** tag, bool* status) override { + if (internal::CallOpSet< + internal::CallOpSendInitialMetadata, + internal::CallOpServerSendStatus>::FinalizeResult(tag, status)) { + delete this; + } else { + // The tag was swallowed due to interception. We will see it again. + } + return false; + } + + private: + UnimplementedAsyncRequest* const request_; +}; + +class Server::SyncRequest final : public internal::CompletionQueueTag { + public: + SyncRequest(internal::RpcServiceMethod* method, void* method_tag) + : method_(method), + method_tag_(method_tag), + in_flight_(false), + has_request_payload_( + method->method_type() == internal::RpcMethod::NORMAL_RPC || + method->method_type() == internal::RpcMethod::SERVER_STREAMING), + call_details_(nullptr), + cq_(nullptr) { + grpc_metadata_array_init(&request_metadata_); + } + + ~SyncRequest() { + if (call_details_) { + delete call_details_; + } + grpc_metadata_array_destroy(&request_metadata_); + } + + void SetupRequest() { cq_ = grpc_completion_queue_create_for_pluck(nullptr); } + + void TeardownRequest() { + grpc_completion_queue_destroy(cq_); + cq_ = nullptr; + } + + void Request(grpc_server* server, grpc_completion_queue* notify_cq) { + GPR_ASSERT(cq_ && !in_flight_); + in_flight_ = true; + if (method_tag_) { + if (grpc_server_request_registered_call( + server, method_tag_, &call_, &deadline_, &request_metadata_, + has_request_payload_ ? &request_payload_ : nullptr, cq_, + notify_cq, this) != GRPC_CALL_OK) { + TeardownRequest(); + return; + } + } else { + if (!call_details_) { + call_details_ = new grpc_call_details; + grpc_call_details_init(call_details_); + } + if (grpc_server_request_call(server, &call_, call_details_, + &request_metadata_, cq_, notify_cq, + this) != GRPC_CALL_OK) { + TeardownRequest(); + return; + } + } + } + + void PostShutdownCleanup() { + if (call_) { + grpc_call_unref(call_); + call_ = nullptr; + } + if (cq_) { + grpc_completion_queue_destroy(cq_); + cq_ = nullptr; + } + } + + bool FinalizeResult(void** tag, bool* status) override { + if (!*status) { + grpc_completion_queue_destroy(cq_); + cq_ = nullptr; + } + if (call_details_) { + deadline_ = call_details_->deadline; + grpc_call_details_destroy(call_details_); + grpc_call_details_init(call_details_); + } + return true; + } + + // The CallData class represents a call that is "active" as opposed + // to just being requested. It wraps and takes ownership of the cq from + // the call request + class CallData final { + public: + explicit CallData(Server* server, SyncRequest* mrd) + : cq_(mrd->cq_), + ctx_(mrd->deadline_, &mrd->request_metadata_), + has_request_payload_(mrd->has_request_payload_), + request_payload_(has_request_payload_ ? mrd->request_payload_ + : nullptr), + request_(nullptr), + method_(mrd->method_), + call_( + mrd->call_, server, &cq_, server->max_receive_message_size(), + ctx_.set_server_rpc_info(method_->name(), method_->method_type(), + server->interceptor_creators_)), + server_(server), + global_callbacks_(nullptr), + resources_(false) { + ctx_.set_call(mrd->call_); + ctx_.cq_ = &cq_; + GPR_ASSERT(mrd->in_flight_); + mrd->in_flight_ = false; + mrd->request_metadata_.count = 0; + } + + ~CallData() { + if (has_request_payload_ && request_payload_) { + grpc_byte_buffer_destroy(request_payload_); + } + } + + void Run(const std::shared_ptr& global_callbacks, + bool resources) { + global_callbacks_ = global_callbacks; + resources_ = resources; + + interceptor_methods_.SetCall(&call_); + interceptor_methods_.SetReverse(); + // Set interception point for RECV INITIAL METADATA + interceptor_methods_.AddInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA); + interceptor_methods_.SetRecvInitialMetadata(&ctx_.client_metadata_); + + if (has_request_payload_) { + // Set interception point for RECV MESSAGE + auto* handler = resources_ ? method_->handler() + : server_->resource_exhausted_handler_.get(); + request_ = handler->Deserialize(call_.call(), request_payload_, + &request_status_); + + request_payload_ = nullptr; + interceptor_methods_.AddInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_MESSAGE); + interceptor_methods_.SetRecvMessage(request_, nullptr); + } + + if (interceptor_methods_.RunInterceptors( + [this]() { ContinueRunAfterInterception(); })) { + ContinueRunAfterInterception(); + } else { + // There were interceptors to be run, so ContinueRunAfterInterception + // will be run when interceptors are done. + } + } + + void ContinueRunAfterInterception() { + { + ctx_.BeginCompletionOp(&call_, nullptr, nullptr); + global_callbacks_->PreSynchronousRequest(&ctx_); + auto* handler = resources_ ? method_->handler() + : server_->resource_exhausted_handler_.get(); + handler->RunHandler(internal::MethodHandler::HandlerParameter( + &call_, &ctx_, request_, request_status_, nullptr)); + request_ = nullptr; + global_callbacks_->PostSynchronousRequest(&ctx_); + + cq_.Shutdown(); + + internal::CompletionQueueTag* op_tag = ctx_.GetCompletionOpTag(); + cq_.TryPluck(op_tag, gpr_inf_future(GPR_CLOCK_REALTIME)); + + /* Ensure the cq_ is shutdown */ + DummyTag ignored_tag; + GPR_ASSERT(cq_.Pluck(&ignored_tag) == false); + } + delete this; + } + + private: + CompletionQueue cq_; + ServerContext ctx_; + const bool has_request_payload_; + grpc_byte_buffer* request_payload_; + void* request_; + Status request_status_; + internal::RpcServiceMethod* const method_; + internal::Call call_; + Server* server_; + std::shared_ptr global_callbacks_; + bool resources_; + internal::InterceptorBatchMethodsImpl interceptor_methods_; + }; + + private: + internal::RpcServiceMethod* const method_; + void* const method_tag_; + bool in_flight_; + const bool has_request_payload_; + grpc_call* call_; + grpc_call_details* call_details_; + gpr_timespec deadline_; + grpc_metadata_array request_metadata_; + grpc_byte_buffer* request_payload_; + grpc_completion_queue* cq_; +}; + +class Server::CallbackRequestBase : public internal::CompletionQueueTag { + public: + virtual ~CallbackRequestBase() {} + virtual bool Request() = 0; +}; + +template +class Server::CallbackRequest final : public Server::CallbackRequestBase { + public: + static_assert(std::is_base_of::value, + "ServerContextType must be derived from ServerContext"); + + // The constructor needs to know the server for this callback request and its + // index in the server's request count array to allow for proper dynamic + // requesting of incoming RPCs. For codegen services, the values of method and + // method_tag represent the defined characteristics of the method being + // requested. For generic services, method and method_tag are nullptr since + // these services don't have pre-defined methods or method registration tags. + CallbackRequest(Server* server, size_t method_idx, + internal::RpcServiceMethod* method, void* method_tag) + : server_(server), + method_index_(method_idx), + method_(method), + method_tag_(method_tag), + has_request_payload_( + method_ != nullptr && + (method->method_type() == internal::RpcMethod::NORMAL_RPC || + method->method_type() == internal::RpcMethod::SERVER_STREAMING)), + cq_(server->CallbackCQ()), + tag_(this) { + server_->callback_reqs_outstanding_++; + Setup(); + } + + ~CallbackRequest() { + Clear(); + + // The counter of outstanding requests must be decremented + // under a lock in case it causes the server shutdown. + std::lock_guard l(server_->callback_reqs_mu_); + if (--server_->callback_reqs_outstanding_ == 0) { + server_->callback_reqs_done_cv_.notify_one(); + } + } + + bool Request() override { + if (method_tag_) { + if (GRPC_CALL_OK != + grpc_server_request_registered_call( + server_->c_server(), method_tag_, &call_, &deadline_, + &request_metadata_, + has_request_payload_ ? &request_payload_ : nullptr, cq_->cq(), + cq_->cq(), static_cast(&tag_))) { + return false; + } + } else { + if (!call_details_) { + call_details_ = new grpc_call_details; + grpc_call_details_init(call_details_); + } + if (grpc_server_request_call(server_->c_server(), &call_, call_details_, + &request_metadata_, cq_->cq(), cq_->cq(), + static_cast(&tag_)) != GRPC_CALL_OK) { + return false; + } + } + return true; + } + + // Needs specialization to account for different processing of metadata + // in generic API + bool FinalizeResult(void** tag, bool* status) override; + + private: + // method_name needs to be specialized between named method and generic + const char* method_name() const; + + class CallbackCallTag : public grpc_experimental_completion_queue_functor { + public: + CallbackCallTag(Server::CallbackRequest* req) + : req_(req) { + functor_run = &CallbackCallTag::StaticRun; + } + + // force_run can not be performed on a tag if operations using this tag + // have been sent to PerformOpsOnCall. It is intended for error conditions + // that are detected before the operations are internally processed. + void force_run(bool ok) { Run(ok); } + + private: + Server::CallbackRequest* req_; + internal::Call* call_; + + static void StaticRun(grpc_experimental_completion_queue_functor* cb, + int ok) { + static_cast(cb)->Run(static_cast(ok)); + } + void Run(bool ok) { + void* ignored = req_; + bool new_ok = ok; + GPR_ASSERT(!req_->FinalizeResult(&ignored, &new_ok)); + GPR_ASSERT(ignored == req_); + + int count = + static_cast(gpr_atm_no_barrier_fetch_add( + &req_->server_ + ->callback_unmatched_reqs_count_[req_->method_index_], + -1)) - + 1; + if (!ok) { + // The call has been shutdown. + // Delete its contents to free up the request. + delete req_; + return; + } + + // If this was the last request in the list or it is below the soft + // minimum and there are spare requests available, set up a new one. + if (count == 0 || (count < SOFT_MINIMUM_SPARE_CALLBACK_REQS_PER_METHOD && + req_->server_->callback_reqs_outstanding_ < + SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING)) { + auto* new_req = new CallbackRequest( + req_->server_, req_->method_index_, req_->method_, + req_->method_tag_); + if (!new_req->Request()) { + // The server must have just decided to shutdown. + gpr_atm_no_barrier_fetch_add( + &new_req->server_ + ->callback_unmatched_reqs_count_[new_req->method_index_], + -1); + delete new_req; + } + } + + // Bind the call, deadline, and metadata from what we got + req_->ctx_.set_call(req_->call_); + req_->ctx_.cq_ = req_->cq_; + req_->ctx_.BindDeadlineAndMetadata(req_->deadline_, + &req_->request_metadata_); + req_->request_metadata_.count = 0; + + // Create a C++ Call to control the underlying core call + call_ = new (grpc_call_arena_alloc(req_->call_, sizeof(internal::Call))) + internal::Call(req_->call_, req_->server_, req_->cq_, + req_->server_->max_receive_message_size(), + req_->ctx_.set_server_rpc_info( + req_->method_name(), + (req_->method_ != nullptr) + ? req_->method_->method_type() + : internal::RpcMethod::BIDI_STREAMING, + req_->server_->interceptor_creators_)); + + req_->interceptor_methods_.SetCall(call_); + req_->interceptor_methods_.SetReverse(); + // Set interception point for RECV INITIAL METADATA + req_->interceptor_methods_.AddInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA); + req_->interceptor_methods_.SetRecvInitialMetadata( + &req_->ctx_.client_metadata_); + + if (req_->has_request_payload_) { + // Set interception point for RECV MESSAGE + req_->request_ = req_->method_->handler()->Deserialize( + req_->call_, req_->request_payload_, &req_->request_status_); + req_->request_payload_ = nullptr; + req_->interceptor_methods_.AddInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_MESSAGE); + req_->interceptor_methods_.SetRecvMessage(req_->request_, nullptr); + } + + if (req_->interceptor_methods_.RunInterceptors( + [this] { ContinueRunAfterInterception(); })) { + ContinueRunAfterInterception(); + } else { + // There were interceptors to be run, so ContinueRunAfterInterception + // will be run when interceptors are done. + } + } + void ContinueRunAfterInterception() { + auto* handler = (req_->method_ != nullptr) + ? req_->method_->handler() + : req_->server_->generic_handler_.get(); + handler->RunHandler(internal::MethodHandler::HandlerParameter( + call_, &req_->ctx_, req_->request_, req_->request_status_, [this] { + // Recycle this request if there aren't too many outstanding. + // Note that we don't have to worry about a case where there + // are no requests waiting to match for this method since that + // is already taken care of when binding a request to a call. + // TODO(vjpai): Also don't recycle this request if the dynamic + // load no longer justifies it. Consider measuring + // dynamic load and setting a target accordingly. + if (req_->server_->callback_reqs_outstanding_ < + SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING) { + req_->Clear(); + req_->Setup(); + } else { + // We can free up this request because there are too many + delete req_; + return; + } + if (!req_->Request()) { + // The server must have just decided to shutdown. + delete req_; + } + })); + } + }; + + void Clear() { + if (call_details_) { + delete call_details_; + call_details_ = nullptr; + } + grpc_metadata_array_destroy(&request_metadata_); + if (has_request_payload_ && request_payload_) { + grpc_byte_buffer_destroy(request_payload_); + } + ctx_.Clear(); + interceptor_methods_.ClearState(); + } + + void Setup() { + gpr_atm_no_barrier_fetch_add( + &server_->callback_unmatched_reqs_count_[method_index_], 1); + grpc_metadata_array_init(&request_metadata_); + ctx_.Setup(gpr_inf_future(GPR_CLOCK_REALTIME)); + request_payload_ = nullptr; + request_ = nullptr; + request_status_ = Status(); + } + + Server* const server_; + const size_t method_index_; + internal::RpcServiceMethod* const method_; + void* const method_tag_; + const bool has_request_payload_; + grpc_byte_buffer* request_payload_; + void* request_; + Status request_status_; + grpc_call_details* call_details_ = nullptr; + grpc_call* call_; + gpr_timespec deadline_; + grpc_metadata_array request_metadata_; + CompletionQueue* cq_; + CallbackCallTag tag_; + ServerContextType ctx_; + internal::InterceptorBatchMethodsImpl interceptor_methods_; +}; + +template <> +bool Server::CallbackRequest::FinalizeResult(void** tag, + bool* status) { + return false; +} + +template <> +bool Server::CallbackRequest::FinalizeResult( + void** tag, bool* status) { + if (*status) { + // TODO(yangg) remove the copy here + ctx_.method_ = StringFromCopiedSlice(call_details_->method); + ctx_.host_ = StringFromCopiedSlice(call_details_->host); + } + grpc_slice_unref(call_details_->method); + grpc_slice_unref(call_details_->host); + return false; +} + +template <> +const char* Server::CallbackRequest::method_name() const { + return method_->name(); +} + +template <> +const char* Server::CallbackRequest::method_name() const { + return ctx_.method().c_str(); +} + +// Implementation of ThreadManager. Each instance of SyncRequestThreadManager +// manages a pool of threads that poll for incoming Sync RPCs and call the +// appropriate RPC handlers +class Server::SyncRequestThreadManager : public ThreadManager { + public: + SyncRequestThreadManager(Server* server, CompletionQueue* server_cq, + std::shared_ptr global_callbacks, + grpc_resource_quota* rq, int min_pollers, + int max_pollers, int cq_timeout_msec) + : ThreadManager("SyncServer", rq, min_pollers, max_pollers), + server_(server), + server_cq_(server_cq), + cq_timeout_msec_(cq_timeout_msec), + global_callbacks_(std::move(global_callbacks)) {} + + WorkStatus PollForWork(void** tag, bool* ok) override { + *tag = nullptr; + // TODO(ctiller): workaround for GPR_TIMESPAN based deadlines not working + // right now + gpr_timespec deadline = + gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_millis(cq_timeout_msec_, GPR_TIMESPAN)); + + switch (server_cq_->AsyncNext(tag, ok, deadline)) { + case CompletionQueue::TIMEOUT: + return TIMEOUT; + case CompletionQueue::SHUTDOWN: + return SHUTDOWN; + case CompletionQueue::GOT_EVENT: + return WORK_FOUND; + } + + GPR_UNREACHABLE_CODE(return TIMEOUT); + } + + void DoWork(void* tag, bool ok, bool resources) override { + SyncRequest* sync_req = static_cast(tag); + + if (!sync_req) { + // No tag. Nothing to work on. This is an unlikley scenario and possibly a + // bug in RPC Manager implementation. + gpr_log(GPR_ERROR, "Sync server. DoWork() was called with NULL tag"); + return; + } + + if (ok) { + // Calldata takes ownership of the completion queue and interceptors + // inside sync_req + auto* cd = new SyncRequest::CallData(server_, sync_req); + // Prepare for the next request + if (!IsShutdown()) { + sync_req->SetupRequest(); // Create new completion queue for sync_req + sync_req->Request(server_->c_server(), server_cq_->cq()); + } + + GPR_TIMER_SCOPE("cd.Run()", 0); + cd->Run(global_callbacks_, resources); + } + // TODO (sreek) If ok is false here (which it isn't in case of + // grpc_request_registered_call), we should still re-queue the request + // object + } + + void AddSyncMethod(internal::RpcServiceMethod* method, void* tag) { + sync_requests_.emplace_back(new SyncRequest(method, tag)); + } + + void AddUnknownSyncMethod() { + if (!sync_requests_.empty()) { + unknown_method_.reset(new internal::RpcServiceMethod( + "unknown", internal::RpcMethod::BIDI_STREAMING, + new internal::UnknownMethodHandler)); + sync_requests_.emplace_back( + new SyncRequest(unknown_method_.get(), nullptr)); + } + } + + void Shutdown() override { + ThreadManager::Shutdown(); + server_cq_->Shutdown(); + } + + void Wait() override { + ThreadManager::Wait(); + // Drain any pending items from the queue + void* tag; + bool ok; + while (server_cq_->Next(&tag, &ok)) { + if (ok) { + // If a request was pulled off the queue, it means that the thread + // handling the request added it to the completion queue after shutdown + // was called - because the thread had already started and checked the + // shutdown flag before shutdown was called. In this case, we simply + // clean it up here, *after* calling wait on all the worker threads, at + // which point we are certain no in-flight requests will add more to the + // queue. This fixes an intermittent memory leak on shutdown. + SyncRequest* sync_req = static_cast(tag); + sync_req->PostShutdownCleanup(); + } + } + } + + void Start() { + if (!sync_requests_.empty()) { + for (auto m = sync_requests_.begin(); m != sync_requests_.end(); m++) { + (*m)->SetupRequest(); + (*m)->Request(server_->c_server(), server_cq_->cq()); + } + + Initialize(); // ThreadManager's Initialize() + } + } + + private: + Server* server_; + CompletionQueue* server_cq_; + int cq_timeout_msec_; + std::vector> sync_requests_; + std::unique_ptr unknown_method_; + std::shared_ptr global_callbacks_; +}; + +static internal::GrpcLibraryInitializer g_gli_initializer; +Server::Server( + int max_receive_message_size, ChannelArguments* args, + std::shared_ptr>> + sync_server_cqs, + int min_pollers, int max_pollers, int sync_cq_timeout_msec, + grpc_resource_quota* server_rq, + std::vector< + std::unique_ptr> + interceptor_creators) + : interceptor_creators_(std::move(interceptor_creators)), + max_receive_message_size_(max_receive_message_size), + sync_server_cqs_(std::move(sync_server_cqs)), + started_(false), + shutdown_(false), + shutdown_notified_(false), + server_(nullptr), + server_initializer_(new grpc_impl::ServerInitializer(this)), + health_check_service_disabled_(false) { + g_gli_initializer.summon(); + gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks); + global_callbacks_ = g_callbacks; + global_callbacks_->UpdateArguments(args); + + if (sync_server_cqs_ != nullptr) { + bool default_rq_created = false; + if (server_rq == nullptr) { + server_rq = grpc_resource_quota_create("SyncServer-default-rq"); + grpc_resource_quota_set_max_threads(server_rq, + DEFAULT_MAX_SYNC_SERVER_THREADS); + default_rq_created = true; + } + + for (const auto& it : *sync_server_cqs_) { + sync_req_mgrs_.emplace_back(new SyncRequestThreadManager( + this, it.get(), global_callbacks_, server_rq, min_pollers, + max_pollers, sync_cq_timeout_msec)); + } + + if (default_rq_created) { + grpc_resource_quota_unref(server_rq); + } + } + + grpc_channel_args channel_args; + args->SetChannelArgs(&channel_args); + + for (size_t i = 0; i < channel_args.num_args; i++) { + if (0 == + strcmp(channel_args.args[i].key, kHealthCheckServiceInterfaceArg)) { + if (channel_args.args[i].value.pointer.p == nullptr) { + health_check_service_disabled_ = true; + } else { + health_check_service_.reset(static_cast( + channel_args.args[i].value.pointer.p)); + } + break; + } + } + + server_ = grpc_server_create(&channel_args, nullptr); +} + +Server::~Server() { + { + std::unique_lock lock(mu_); + if (callback_cq_ != nullptr) { + callback_cq_->Shutdown(); + } + if (started_ && !shutdown_) { + lock.unlock(); + Shutdown(); + } else if (!started_) { + // Shutdown the completion queues + for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { + (*it)->Shutdown(); + } + } + } + + grpc_server_destroy(server_); + for (auto& per_method_count : callback_unmatched_reqs_count_) { + // There should be no more unmatched callbacks for any method + // as each request is failed by Shutdown. Check that this actually + // happened + GPR_ASSERT(static_cast(gpr_atm_no_barrier_load(&per_method_count)) == + 0); + } +} + +void Server::SetGlobalCallbacks(GlobalCallbacks* callbacks) { + GPR_ASSERT(!g_callbacks); + GPR_ASSERT(callbacks); + g_callbacks.reset(callbacks); +} + +grpc_server* Server::c_server() { return server_; } + +std::shared_ptr Server::InProcessChannel( + const ChannelArguments& args) { + grpc_channel_args channel_args = args.c_channel_args(); + return CreateChannelInternal( + "inproc", grpc_inproc_channel_create(server_, &channel_args, nullptr), + std::vector< + std::unique_ptr>()); +} + +std::shared_ptr +Server::experimental_type::InProcessChannelWithInterceptors( + const ChannelArguments& args, + std::vector< + std::unique_ptr> + interceptor_creators) { + grpc_channel_args channel_args = args.c_channel_args(); + return CreateChannelInternal( + "inproc", + grpc_inproc_channel_create(server_->server_, &channel_args, nullptr), + std::move(interceptor_creators)); +} + +static grpc_server_register_method_payload_handling PayloadHandlingForMethod( + internal::RpcServiceMethod* method) { + switch (method->method_type()) { + case internal::RpcMethod::NORMAL_RPC: + case internal::RpcMethod::SERVER_STREAMING: + return GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER; + case internal::RpcMethod::CLIENT_STREAMING: + case internal::RpcMethod::BIDI_STREAMING: + return GRPC_SRM_PAYLOAD_NONE; + } + GPR_UNREACHABLE_CODE(return GRPC_SRM_PAYLOAD_NONE;); +} + +bool Server::RegisterService(const grpc::string* host, Service* service) { + bool has_async_methods = service->has_async_methods(); + if (has_async_methods) { + GPR_ASSERT(service->server_ == nullptr && + "Can only register an asynchronous service against one server."); + service->server_ = this; + } + + const char* method_name = nullptr; + + for (auto it = service->methods_.begin(); it != service->methods_.end(); + ++it) { + if (it->get() == nullptr) { // Handled by generic service if any. + continue; + } + + internal::RpcServiceMethod* method = it->get(); + void* method_registration_tag = grpc_server_register_method( + server_, method->name(), host ? host->c_str() : nullptr, + PayloadHandlingForMethod(method), 0); + if (method_registration_tag == nullptr) { + gpr_log(GPR_DEBUG, "Attempt to register %s multiple times", + method->name()); + return false; + } + + if (method->handler() == nullptr) { // Async method without handler + method->set_server_tag(method_registration_tag); + } else if (method->api_type() == + internal::RpcServiceMethod::ApiType::SYNC) { + for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { + (*it)->AddSyncMethod(method, method_registration_tag); + } + } else { + // a callback method. Register at least some callback requests + callback_unmatched_reqs_count_.push_back(0); + auto method_index = callback_unmatched_reqs_count_.size() - 1; + // TODO(vjpai): Register these dynamically based on need + for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) { + callback_reqs_to_start_.push_back(new CallbackRequest( + this, method_index, method, method_registration_tag)); + } + // Enqueue it so that it will be Request'ed later after all request + // matchers are created at core server startup + } + + method_name = method->name(); + } + + // Parse service name. + if (method_name != nullptr) { + std::stringstream ss(method_name); + grpc::string service_name; + if (std::getline(ss, service_name, '/') && + std::getline(ss, service_name, '/')) { + services_.push_back(service_name); + } + } + return true; +} + +void Server::RegisterAsyncGenericService(AsyncGenericService* service) { + GPR_ASSERT(service->server_ == nullptr && + "Can only register an async generic service against one server."); + service->server_ = this; + has_async_generic_service_ = true; +} + +void Server::RegisterCallbackGenericService( + experimental::CallbackGenericService* service) { + GPR_ASSERT( + service->server_ == nullptr && + "Can only register a callback generic service against one server."); + service->server_ = this; + has_callback_generic_service_ = true; + generic_handler_.reset(service->Handler()); + + callback_unmatched_reqs_count_.push_back(0); + auto method_index = callback_unmatched_reqs_count_.size() - 1; + // TODO(vjpai): Register these dynamically based on need + for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) { + callback_reqs_to_start_.push_back(new CallbackRequest( + this, method_index, nullptr, nullptr)); + } +} + +int Server::AddListeningPort(const grpc::string& addr, + ServerCredentials* creds) { + GPR_ASSERT(!started_); + int port = creds->AddPortToServer(addr, server_); + global_callbacks_->AddPort(this, addr, creds, port); + return port; +} + +void Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) { + GPR_ASSERT(!started_); + global_callbacks_->PreServerStart(this); + started_ = true; + + // Only create default health check service when user did not provide an + // explicit one. + ServerCompletionQueue* health_check_cq = nullptr; + DefaultHealthCheckService::HealthCheckServiceImpl* + default_health_check_service_impl = nullptr; + if (health_check_service_ == nullptr && !health_check_service_disabled_ && + DefaultHealthCheckServiceEnabled()) { + auto* default_hc_service = new DefaultHealthCheckService; + health_check_service_.reset(default_hc_service); + // We create a non-polling CQ to avoid impacting application + // performance. This ensures that we don't introduce thread hops + // for application requests that wind up on this CQ, which is polled + // in its own thread. + health_check_cq = + new ServerCompletionQueue(GRPC_CQ_NEXT, GRPC_CQ_NON_POLLING, nullptr); + grpc_server_register_completion_queue(server_, health_check_cq->cq(), + nullptr); + default_health_check_service_impl = + default_hc_service->GetHealthCheckService( + std::unique_ptr(health_check_cq)); + RegisterService(nullptr, default_health_check_service_impl); + } + + // If this server uses callback methods, then create a callback generic + // service to handle any unimplemented methods using the default reactor + // creator + if (!callback_reqs_to_start_.empty() && !has_callback_generic_service_) { + unimplemented_service_.reset(new experimental::CallbackGenericService); + RegisterCallbackGenericService(unimplemented_service_.get()); + } + + grpc_server_start(server_); + + if (!has_async_generic_service_ && !has_callback_generic_service_) { + for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { + (*it)->AddUnknownSyncMethod(); + } + + for (size_t i = 0; i < num_cqs; i++) { + if (cqs[i]->IsFrequentlyPolled()) { + new UnimplementedAsyncRequest(this, cqs[i]); + } + } + if (health_check_cq != nullptr) { + new UnimplementedAsyncRequest(this, health_check_cq); + } + } + + // If this server has any support for synchronous methods (has any sync + // server CQs), make sure that we have a ResourceExhausted handler + // to deal with the case of thread exhaustion + if (sync_server_cqs_ != nullptr && !sync_server_cqs_->empty()) { + resource_exhausted_handler_.reset(new internal::ResourceExhaustedHandler); + } + + for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { + (*it)->Start(); + } + + for (auto* cbreq : callback_reqs_to_start_) { + GPR_ASSERT(cbreq->Request()); + } + callback_reqs_to_start_.clear(); + + if (default_health_check_service_impl != nullptr) { + default_health_check_service_impl->StartServingThread(); + } +} + +void Server::ShutdownInternal(gpr_timespec deadline) { + std::unique_lock lock(mu_); + if (shutdown_) { + return; + } + + shutdown_ = true; + + /// The completion queue to use for server shutdown completion notification + CompletionQueue shutdown_cq; + ShutdownTag shutdown_tag; // Dummy shutdown tag + grpc_server_shutdown_and_notify(server_, shutdown_cq.cq(), &shutdown_tag); + + shutdown_cq.Shutdown(); + + void* tag; + bool ok; + CompletionQueue::NextStatus status = + shutdown_cq.AsyncNext(&tag, &ok, deadline); + + // If this timed out, it means we are done with the grace period for a clean + // shutdown. We should force a shutdown now by cancelling all inflight calls + if (status == CompletionQueue::NextStatus::TIMEOUT) { + grpc_server_cancel_all_calls(server_); + } + // Else in case of SHUTDOWN or GOT_EVENT, it means that the server has + // successfully shutdown + + // Shutdown all ThreadManagers. This will try to gracefully stop all the + // threads in the ThreadManagers (once they process any inflight requests) + for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { + (*it)->Shutdown(); // ThreadManager's Shutdown() + } + + // Wait for threads in all ThreadManagers to terminate + for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { + (*it)->Wait(); + } + + // Wait for all outstanding callback requests to complete + // (whether waiting for a match or already active). + // We know that no new requests will be created after this point + // because they are only created at server startup time or when + // we have a successful match on a request. During the shutdown phase, + // requests that have not yet matched will be failed rather than + // allowed to succeed, which will cause the server to delete the + // request and decrement the count. Possibly a request will match before + // the shutdown but then find that shutdown has already started by the + // time it tries to register a new request. In that case, the registration + // will report a failure, indicating a shutdown and again we won't end + // up incrementing the counter. + { + std::unique_lock cblock(callback_reqs_mu_); + callback_reqs_done_cv_.wait( + cblock, [this] { return callback_reqs_outstanding_ == 0; }); + } + + // Drain the shutdown queue (if the previous call to AsyncNext() timed out + // and we didn't remove the tag from the queue yet) + while (shutdown_cq.Next(&tag, &ok)) { + // Nothing to be done here. Just ignore ok and tag values + } + + shutdown_notified_ = true; + shutdown_cv_.notify_all(); +} + +void Server::Wait() { + std::unique_lock lock(mu_); + while (started_ && !shutdown_notified_) { + shutdown_cv_.wait(lock); + } +} + +void Server::PerformOpsOnCall(internal::CallOpSetInterface* ops, + internal::Call* call) { + ops->FillOps(call); +} + ServerInterface::BaseAsyncRequest::BaseAsyncRequest( ServerInterface* server, ServerContext* context, internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, @@ -249,6 +1272,32 @@ bool ServerInterface::GenericAsyncRequest::FinalizeResult(void** tag, return BaseAsyncRequest::FinalizeResult(tag, status); } +bool Server::UnimplementedAsyncRequest::FinalizeResult(void** tag, + bool* status) { + if (GenericAsyncRequest::FinalizeResult(tag, status)) { + // We either had no interceptors run or we are done intercepting + if (*status) { + new UnimplementedAsyncRequest(server_, cq_); + new UnimplementedAsyncResponse(this); + } else { + delete this; + } + } else { + // The tag was swallowed due to interception. We will see it again. + } + return false; +} + +Server::UnimplementedAsyncResponse::UnimplementedAsyncResponse( + UnimplementedAsyncRequest* request) + : request_(request) { + Status status(StatusCode::UNIMPLEMENTED, ""); + internal::UnknownMethodHandler::FillOps(request_->context(), this); + request_->stream()->call_.PerformOps(this); +} + +ServerInitializer* Server::initializer() { return server_initializer_.get(); } + namespace { class ShutdownCallback : public grpc_experimental_completion_queue_functor { public: @@ -270,1082 +1319,13 @@ class ShutdownCallback : public grpc_experimental_completion_queue_functor { }; } // namespace -} // namespace grpc - -namespace grpc_impl { - -/// Use private inheritance rather than composition only to establish order -/// of construction, since the public base class should be constructed after the -/// elements belonging to the private base class are constructed. This is not -/// possible using true composition. -class Server::UnimplementedAsyncRequest final - : private grpc::UnimplementedAsyncRequestContext, - public GenericAsyncRequest { - public: - UnimplementedAsyncRequest(Server* server, grpc::ServerCompletionQueue* cq) - : GenericAsyncRequest(server, &server_context_, &generic_stream_, cq, cq, - nullptr, false), - server_(server), - cq_(cq) {} - - bool FinalizeResult(void** tag, bool* status) override; - - grpc::ServerContext* context() { return &server_context_; } - grpc::GenericServerAsyncReaderWriter* stream() { return &generic_stream_; } - - private: - Server* const server_; - grpc::ServerCompletionQueue* const cq_; -}; - -/// UnimplementedAsyncResponse should not post user-visible completions to the -/// C++ completion queue, but is generated as a CQ event by the core -class Server::UnimplementedAsyncResponse final - : public grpc::internal::CallOpSet< - grpc::internal::CallOpSendInitialMetadata, - grpc::internal::CallOpServerSendStatus> { - public: - UnimplementedAsyncResponse(UnimplementedAsyncRequest* request); - ~UnimplementedAsyncResponse() { delete request_; } - - bool FinalizeResult(void** tag, bool* status) override { - if (grpc::internal::CallOpSet< - grpc::internal::CallOpSendInitialMetadata, - grpc::internal::CallOpServerSendStatus>::FinalizeResult(tag, - status)) { - delete this; - } else { - // The tag was swallowed due to interception. We will see it again. - } - return false; - } - - private: - UnimplementedAsyncRequest* const request_; -}; - -class Server::SyncRequest final : public grpc::internal::CompletionQueueTag { - public: - SyncRequest(grpc::internal::RpcServiceMethod* method, void* method_tag) - : method_(method), - method_tag_(method_tag), - in_flight_(false), - has_request_payload_(method->method_type() == - grpc::internal::RpcMethod::NORMAL_RPC || - method->method_type() == - grpc::internal::RpcMethod::SERVER_STREAMING), - call_details_(nullptr), - cq_(nullptr) { - grpc_metadata_array_init(&request_metadata_); - } - - ~SyncRequest() { - if (call_details_) { - delete call_details_; - } - grpc_metadata_array_destroy(&request_metadata_); - } - - void SetupRequest() { cq_ = grpc_completion_queue_create_for_pluck(nullptr); } - - void TeardownRequest() { - grpc_completion_queue_destroy(cq_); - cq_ = nullptr; - } - - void Request(grpc_server* server, grpc_completion_queue* notify_cq) { - GPR_ASSERT(cq_ && !in_flight_); - in_flight_ = true; - if (method_tag_) { - if (grpc_server_request_registered_call( - server, method_tag_, &call_, &deadline_, &request_metadata_, - has_request_payload_ ? &request_payload_ : nullptr, cq_, - notify_cq, this) != GRPC_CALL_OK) { - TeardownRequest(); - return; - } - } else { - if (!call_details_) { - call_details_ = new grpc_call_details; - grpc_call_details_init(call_details_); - } - if (grpc_server_request_call(server, &call_, call_details_, - &request_metadata_, cq_, notify_cq, - this) != GRPC_CALL_OK) { - TeardownRequest(); - return; - } - } - } - - void PostShutdownCleanup() { - if (call_) { - grpc_call_unref(call_); - call_ = nullptr; - } - if (cq_) { - grpc_completion_queue_destroy(cq_); - cq_ = nullptr; - } - } - - bool FinalizeResult(void** tag, bool* status) override { - if (!*status) { - grpc_completion_queue_destroy(cq_); - cq_ = nullptr; - } - if (call_details_) { - deadline_ = call_details_->deadline; - grpc_call_details_destroy(call_details_); - grpc_call_details_init(call_details_); - } - return true; - } - - // The CallData class represents a call that is "active" as opposed - // to just being requested. It wraps and takes ownership of the cq from - // the call request - class CallData final { - public: - explicit CallData(Server* server, SyncRequest* mrd) - : cq_(mrd->cq_), - ctx_(mrd->deadline_, &mrd->request_metadata_), - has_request_payload_(mrd->has_request_payload_), - request_payload_(has_request_payload_ ? mrd->request_payload_ - : nullptr), - request_(nullptr), - method_(mrd->method_), - call_( - mrd->call_, server, &cq_, server->max_receive_message_size(), - ctx_.set_server_rpc_info(method_->name(), method_->method_type(), - server->interceptor_creators_)), - server_(server), - global_callbacks_(nullptr), - resources_(false) { - ctx_.set_call(mrd->call_); - ctx_.cq_ = &cq_; - GPR_ASSERT(mrd->in_flight_); - mrd->in_flight_ = false; - mrd->request_metadata_.count = 0; - } - - ~CallData() { - if (has_request_payload_ && request_payload_) { - grpc_byte_buffer_destroy(request_payload_); - } - } - - void Run(const std::shared_ptr& global_callbacks, - bool resources) { - global_callbacks_ = global_callbacks; - resources_ = resources; - - interceptor_methods_.SetCall(&call_); - interceptor_methods_.SetReverse(); - // Set interception point for RECV INITIAL METADATA - interceptor_methods_.AddInterceptionHookPoint( - grpc::experimental::InterceptionHookPoints:: - POST_RECV_INITIAL_METADATA); - interceptor_methods_.SetRecvInitialMetadata(&ctx_.client_metadata_); - - if (has_request_payload_) { - // Set interception point for RECV MESSAGE - auto* handler = resources_ ? method_->handler() - : server_->resource_exhausted_handler_.get(); - request_ = handler->Deserialize(call_.call(), request_payload_, - &request_status_); - - request_payload_ = nullptr; - interceptor_methods_.AddInterceptionHookPoint( - grpc::experimental::InterceptionHookPoints::POST_RECV_MESSAGE); - interceptor_methods_.SetRecvMessage(request_, nullptr); - } - - if (interceptor_methods_.RunInterceptors( - [this]() { ContinueRunAfterInterception(); })) { - ContinueRunAfterInterception(); - } else { - // There were interceptors to be run, so ContinueRunAfterInterception - // will be run when interceptors are done. - } - } - - void ContinueRunAfterInterception() { - { - ctx_.BeginCompletionOp(&call_, nullptr, nullptr); - global_callbacks_->PreSynchronousRequest(&ctx_); - auto* handler = resources_ ? method_->handler() - : server_->resource_exhausted_handler_.get(); - handler->RunHandler(grpc::internal::MethodHandler::HandlerParameter( - &call_, &ctx_, request_, request_status_, nullptr)); - request_ = nullptr; - global_callbacks_->PostSynchronousRequest(&ctx_); - - cq_.Shutdown(); - - grpc::internal::CompletionQueueTag* op_tag = ctx_.GetCompletionOpTag(); - cq_.TryPluck(op_tag, gpr_inf_future(GPR_CLOCK_REALTIME)); - - /* Ensure the cq_ is shutdown */ - grpc::DummyTag ignored_tag; - GPR_ASSERT(cq_.Pluck(&ignored_tag) == false); - } - delete this; - } - - private: - grpc::CompletionQueue cq_; - grpc::ServerContext ctx_; - const bool has_request_payload_; - grpc_byte_buffer* request_payload_; - void* request_; - grpc::Status request_status_; - grpc::internal::RpcServiceMethod* const method_; - grpc::internal::Call call_; - Server* server_; - std::shared_ptr global_callbacks_; - bool resources_; - grpc::internal::InterceptorBatchMethodsImpl interceptor_methods_; - }; - - private: - grpc::internal::RpcServiceMethod* const method_; - void* const method_tag_; - bool in_flight_; - const bool has_request_payload_; - grpc_call* call_; - grpc_call_details* call_details_; - gpr_timespec deadline_; - grpc_metadata_array request_metadata_; - grpc_byte_buffer* request_payload_; - grpc_completion_queue* cq_; -}; - -class Server::CallbackRequestBase : public grpc::internal::CompletionQueueTag { - public: - virtual ~CallbackRequestBase() {} - virtual bool Request() = 0; -}; - -template -class Server::CallbackRequest final : public Server::CallbackRequestBase { - public: - static_assert(std::is_base_of::value, - "ServerContextType must be derived from ServerContext"); - - // The constructor needs to know the server for this callback request and its - // index in the server's request count array to allow for proper dynamic - // requesting of incoming RPCs. For codegen services, the values of method and - // method_tag represent the defined characteristics of the method being - // requested. For generic services, method and method_tag are nullptr since - // these services don't have pre-defined methods or method registration tags. - CallbackRequest(Server* server, size_t method_idx, - grpc::internal::RpcServiceMethod* method, void* method_tag) - : server_(server), - method_index_(method_idx), - method_(method), - method_tag_(method_tag), - has_request_payload_( - method_ != nullptr && - (method->method_type() == grpc::internal::RpcMethod::NORMAL_RPC || - method->method_type() == - grpc::internal::RpcMethod::SERVER_STREAMING)), - cq_(server->CallbackCQ()), - tag_(this) { - server_->callback_reqs_outstanding_++; - Setup(); - } - - ~CallbackRequest() { - Clear(); - - // The counter of outstanding requests must be decremented - // under a lock in case it causes the server shutdown. - grpc::internal::MutexLock l(&server_->callback_reqs_mu_); - if (--server_->callback_reqs_outstanding_ == 0) { - server_->callback_reqs_done_cv_.Signal(); - } - } - - bool Request() override { - if (method_tag_) { - if (GRPC_CALL_OK != - grpc_server_request_registered_call( - server_->c_server(), method_tag_, &call_, &deadline_, - &request_metadata_, - has_request_payload_ ? &request_payload_ : nullptr, cq_->cq(), - cq_->cq(), static_cast(&tag_))) { - return false; - } - } else { - if (!call_details_) { - call_details_ = new grpc_call_details; - grpc_call_details_init(call_details_); - } - if (grpc_server_request_call(server_->c_server(), &call_, call_details_, - &request_metadata_, cq_->cq(), cq_->cq(), - static_cast(&tag_)) != GRPC_CALL_OK) { - return false; - } - } - return true; - } - - // Needs specialization to account for different processing of metadata - // in generic API - bool FinalizeResult(void** tag, bool* status) override; - - private: - // method_name needs to be specialized between named method and generic - const char* method_name() const; - - class CallbackCallTag : public grpc_experimental_completion_queue_functor { - public: - CallbackCallTag(Server::CallbackRequest* req) - : req_(req) { - functor_run = &CallbackCallTag::StaticRun; - } - - // force_run can not be performed on a tag if operations using this tag - // have been sent to PerformOpsOnCall. It is intended for error conditions - // that are detected before the operations are internally processed. - void force_run(bool ok) { Run(ok); } - - private: - Server::CallbackRequest* req_; - grpc::internal::Call* call_; - - static void StaticRun(grpc_experimental_completion_queue_functor* cb, - int ok) { - static_cast(cb)->Run(static_cast(ok)); - } - void Run(bool ok) { - void* ignored = req_; - bool new_ok = ok; - GPR_ASSERT(!req_->FinalizeResult(&ignored, &new_ok)); - GPR_ASSERT(ignored == req_); - - int count = - static_cast(gpr_atm_no_barrier_fetch_add( - &req_->server_ - ->callback_unmatched_reqs_count_[req_->method_index_], - -1)) - - 1; - if (!ok) { - // The call has been shutdown. - // Delete its contents to free up the request. - delete req_; - return; - } - - // If this was the last request in the list or it is below the soft - // minimum and there are spare requests available, set up a new one. - if (count == 0 || (count < SOFT_MINIMUM_SPARE_CALLBACK_REQS_PER_METHOD && - req_->server_->callback_reqs_outstanding_ < - SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING)) { - auto* new_req = new CallbackRequest( - req_->server_, req_->method_index_, req_->method_, - req_->method_tag_); - if (!new_req->Request()) { - // The server must have just decided to shutdown. - gpr_atm_no_barrier_fetch_add( - &new_req->server_ - ->callback_unmatched_reqs_count_[new_req->method_index_], - -1); - delete new_req; - } - } - - // Bind the call, deadline, and metadata from what we got - req_->ctx_.set_call(req_->call_); - req_->ctx_.cq_ = req_->cq_; - req_->ctx_.BindDeadlineAndMetadata(req_->deadline_, - &req_->request_metadata_); - req_->request_metadata_.count = 0; - - // Create a C++ Call to control the underlying core call - call_ = - new (grpc_call_arena_alloc(req_->call_, sizeof(grpc::internal::Call))) - grpc::internal::Call( - req_->call_, req_->server_, req_->cq_, - req_->server_->max_receive_message_size(), - req_->ctx_.set_server_rpc_info( - req_->method_name(), - (req_->method_ != nullptr) - ? req_->method_->method_type() - : grpc::internal::RpcMethod::BIDI_STREAMING, - req_->server_->interceptor_creators_)); - - req_->interceptor_methods_.SetCall(call_); - req_->interceptor_methods_.SetReverse(); - // Set interception point for RECV INITIAL METADATA - req_->interceptor_methods_.AddInterceptionHookPoint( - grpc::experimental::InterceptionHookPoints:: - POST_RECV_INITIAL_METADATA); - req_->interceptor_methods_.SetRecvInitialMetadata( - &req_->ctx_.client_metadata_); - - if (req_->has_request_payload_) { - // Set interception point for RECV MESSAGE - req_->request_ = req_->method_->handler()->Deserialize( - req_->call_, req_->request_payload_, &req_->request_status_); - req_->request_payload_ = nullptr; - req_->interceptor_methods_.AddInterceptionHookPoint( - grpc::experimental::InterceptionHookPoints::POST_RECV_MESSAGE); - req_->interceptor_methods_.SetRecvMessage(req_->request_, nullptr); - } - - if (req_->interceptor_methods_.RunInterceptors( - [this] { ContinueRunAfterInterception(); })) { - ContinueRunAfterInterception(); - } else { - // There were interceptors to be run, so ContinueRunAfterInterception - // will be run when interceptors are done. - } - } - void ContinueRunAfterInterception() { - auto* handler = (req_->method_ != nullptr) - ? req_->method_->handler() - : req_->server_->generic_handler_.get(); - handler->RunHandler(grpc::internal::MethodHandler::HandlerParameter( - call_, &req_->ctx_, req_->request_, req_->request_status_, [this] { - // Recycle this request if there aren't too many outstanding. - // Note that we don't have to worry about a case where there - // are no requests waiting to match for this method since that - // is already taken care of when binding a request to a call. - // TODO(vjpai): Also don't recycle this request if the dynamic - // load no longer justifies it. Consider measuring - // dynamic load and setting a target accordingly. - if (req_->server_->callback_reqs_outstanding_ < - SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING) { - req_->Clear(); - req_->Setup(); - } else { - // We can free up this request because there are too many - delete req_; - return; - } - if (!req_->Request()) { - // The server must have just decided to shutdown. - delete req_; - } - })); - } - }; - - void Clear() { - if (call_details_) { - delete call_details_; - call_details_ = nullptr; - } - grpc_metadata_array_destroy(&request_metadata_); - if (has_request_payload_ && request_payload_) { - grpc_byte_buffer_destroy(request_payload_); - } - ctx_.Clear(); - interceptor_methods_.ClearState(); - } - - void Setup() { - gpr_atm_no_barrier_fetch_add( - &server_->callback_unmatched_reqs_count_[method_index_], 1); - grpc_metadata_array_init(&request_metadata_); - ctx_.Setup(gpr_inf_future(GPR_CLOCK_REALTIME)); - request_payload_ = nullptr; - request_ = nullptr; - request_status_ = grpc::Status(); - } - - Server* const server_; - const size_t method_index_; - grpc::internal::RpcServiceMethod* const method_; - void* const method_tag_; - const bool has_request_payload_; - grpc_byte_buffer* request_payload_; - void* request_; - grpc::Status request_status_; - grpc_call_details* call_details_ = nullptr; - grpc_call* call_; - gpr_timespec deadline_; - grpc_metadata_array request_metadata_; - grpc::CompletionQueue* cq_; - CallbackCallTag tag_; - ServerContextType ctx_; - grpc::internal::InterceptorBatchMethodsImpl interceptor_methods_; -}; - -template <> -bool Server::CallbackRequest::FinalizeResult( - void** tag, bool* status) { - return false; -} - -template <> -bool Server::CallbackRequest::FinalizeResult( - void** tag, bool* status) { - if (*status) { - // TODO(yangg) remove the copy here - ctx_.method_ = grpc::StringFromCopiedSlice(call_details_->method); - ctx_.host_ = grpc::StringFromCopiedSlice(call_details_->host); - } - grpc_slice_unref(call_details_->method); - grpc_slice_unref(call_details_->host); - return false; -} - -template <> -const char* Server::CallbackRequest::method_name() const { - return method_->name(); -} - -template <> -const char* Server::CallbackRequest::method_name() - const { - return ctx_.method().c_str(); -} - -// Implementation of ThreadManager. Each instance of SyncRequestThreadManager -// manages a pool of threads that poll for incoming Sync RPCs and call the -// appropriate RPC handlers -class Server::SyncRequestThreadManager : public grpc::ThreadManager { - public: - SyncRequestThreadManager(Server* server, grpc::CompletionQueue* server_cq, - std::shared_ptr global_callbacks, - grpc_resource_quota* rq, int min_pollers, - int max_pollers, int cq_timeout_msec) - : ThreadManager("SyncServer", rq, min_pollers, max_pollers), - server_(server), - server_cq_(server_cq), - cq_timeout_msec_(cq_timeout_msec), - global_callbacks_(std::move(global_callbacks)) {} - - WorkStatus PollForWork(void** tag, bool* ok) override { - *tag = nullptr; - // TODO(ctiller): workaround for GPR_TIMESPAN based deadlines not working - // right now - gpr_timespec deadline = - gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_millis(cq_timeout_msec_, GPR_TIMESPAN)); - - switch (server_cq_->AsyncNext(tag, ok, deadline)) { - case grpc::CompletionQueue::TIMEOUT: - return TIMEOUT; - case grpc::CompletionQueue::SHUTDOWN: - return SHUTDOWN; - case grpc::CompletionQueue::GOT_EVENT: - return WORK_FOUND; - } - - GPR_UNREACHABLE_CODE(return TIMEOUT); - } - - void DoWork(void* tag, bool ok, bool resources) override { - SyncRequest* sync_req = static_cast(tag); - - if (!sync_req) { - // No tag. Nothing to work on. This is an unlikley scenario and possibly a - // bug in RPC Manager implementation. - gpr_log(GPR_ERROR, "Sync server. DoWork() was called with NULL tag"); - return; - } - - if (ok) { - // Calldata takes ownership of the completion queue and interceptors - // inside sync_req - auto* cd = new SyncRequest::CallData(server_, sync_req); - // Prepare for the next request - if (!IsShutdown()) { - sync_req->SetupRequest(); // Create new completion queue for sync_req - sync_req->Request(server_->c_server(), server_cq_->cq()); - } - - GPR_TIMER_SCOPE("cd.Run()", 0); - cd->Run(global_callbacks_, resources); - } - // TODO (sreek) If ok is false here (which it isn't in case of - // grpc_request_registered_call), we should still re-queue the request - // object - } - - void AddSyncMethod(grpc::internal::RpcServiceMethod* method, void* tag) { - sync_requests_.emplace_back(new SyncRequest(method, tag)); - } - - void AddUnknownSyncMethod() { - if (!sync_requests_.empty()) { - unknown_method_.reset(new grpc::internal::RpcServiceMethod( - "unknown", grpc::internal::RpcMethod::BIDI_STREAMING, - new grpc::internal::UnknownMethodHandler)); - sync_requests_.emplace_back( - new SyncRequest(unknown_method_.get(), nullptr)); - } - } - - void Shutdown() override { - ThreadManager::Shutdown(); - server_cq_->Shutdown(); - } - - void Wait() override { - ThreadManager::Wait(); - // Drain any pending items from the queue - void* tag; - bool ok; - while (server_cq_->Next(&tag, &ok)) { - if (ok) { - // If a request was pulled off the queue, it means that the thread - // handling the request added it to the completion queue after shutdown - // was called - because the thread had already started and checked the - // shutdown flag before shutdown was called. In this case, we simply - // clean it up here, *after* calling wait on all the worker threads, at - // which point we are certain no in-flight requests will add more to the - // queue. This fixes an intermittent memory leak on shutdown. - SyncRequest* sync_req = static_cast(tag); - sync_req->PostShutdownCleanup(); - } - } - } - - void Start() { - if (!sync_requests_.empty()) { - for (auto m = sync_requests_.begin(); m != sync_requests_.end(); m++) { - (*m)->SetupRequest(); - (*m)->Request(server_->c_server(), server_cq_->cq()); - } - - Initialize(); // ThreadManager's Initialize() - } - } - - private: - Server* server_; - grpc::CompletionQueue* server_cq_; - int cq_timeout_msec_; - std::vector> sync_requests_; - std::unique_ptr unknown_method_; - std::shared_ptr global_callbacks_; -}; - -static grpc::internal::GrpcLibraryInitializer g_gli_initializer; -Server::Server( - int max_receive_message_size, grpc::ChannelArguments* args, - std::shared_ptr>> - sync_server_cqs, - int min_pollers, int max_pollers, int sync_cq_timeout_msec, - grpc_resource_quota* server_rq, - std::vector< - std::unique_ptr> - interceptor_creators) - : interceptor_creators_(std::move(interceptor_creators)), - max_receive_message_size_(max_receive_message_size), - sync_server_cqs_(std::move(sync_server_cqs)), - started_(false), - shutdown_(false), - shutdown_notified_(false), - server_(nullptr), - server_initializer_(new grpc_impl::ServerInitializer(this)), - health_check_service_disabled_(false) { - g_gli_initializer.summon(); - gpr_once_init(&grpc::g_once_init_callbacks, grpc::InitGlobalCallbacks); - global_callbacks_ = grpc::g_callbacks; - global_callbacks_->UpdateArguments(args); - - if (sync_server_cqs_ != nullptr) { - bool default_rq_created = false; - if (server_rq == nullptr) { - server_rq = grpc_resource_quota_create("SyncServer-default-rq"); - grpc_resource_quota_set_max_threads(server_rq, - DEFAULT_MAX_SYNC_SERVER_THREADS); - default_rq_created = true; - } - - for (const auto& it : *sync_server_cqs_) { - sync_req_mgrs_.emplace_back(new SyncRequestThreadManager( - this, it.get(), global_callbacks_, server_rq, min_pollers, - max_pollers, sync_cq_timeout_msec)); - } - - if (default_rq_created) { - grpc_resource_quota_unref(server_rq); - } - } - - grpc_channel_args channel_args; - args->SetChannelArgs(&channel_args); - - for (size_t i = 0; i < channel_args.num_args; i++) { - if (0 == strcmp(channel_args.args[i].key, - grpc::kHealthCheckServiceInterfaceArg)) { - if (channel_args.args[i].value.pointer.p == nullptr) { - health_check_service_disabled_ = true; - } else { - health_check_service_.reset( - static_cast( - channel_args.args[i].value.pointer.p)); - } - break; - } - } - - server_ = grpc_server_create(&channel_args, nullptr); -} - -Server::~Server() { - { - grpc::internal::ReleasableMutexLock lock(&mu_); - if (callback_cq_ != nullptr) { - callback_cq_->Shutdown(); - } - if (started_ && !shutdown_) { - lock.Unlock(); - Shutdown(); - } else if (!started_) { - // Shutdown the completion queues - for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { - (*it)->Shutdown(); - } - } - } - - grpc_server_destroy(server_); - for (auto& per_method_count : callback_unmatched_reqs_count_) { - // There should be no more unmatched callbacks for any method - // as each request is failed by Shutdown. Check that this actually - // happened - GPR_ASSERT(static_cast(gpr_atm_no_barrier_load(&per_method_count)) == - 0); - } -} - -void Server::SetGlobalCallbacks(GlobalCallbacks* callbacks) { - GPR_ASSERT(!grpc::g_callbacks); - GPR_ASSERT(callbacks); - grpc::g_callbacks.reset(callbacks); -} - -grpc_server* Server::c_server() { return server_; } - -std::shared_ptr Server::InProcessChannel( - const grpc::ChannelArguments& args) { - grpc_channel_args channel_args = args.c_channel_args(); - return grpc::CreateChannelInternal( - "inproc", grpc_inproc_channel_create(server_, &channel_args, nullptr), - std::vector>()); -} - -std::shared_ptr -Server::experimental_type::InProcessChannelWithInterceptors( - const grpc::ChannelArguments& args, - std::vector< - std::unique_ptr> - interceptor_creators) { - grpc_channel_args channel_args = args.c_channel_args(); - return grpc::CreateChannelInternal( - "inproc", - grpc_inproc_channel_create(server_->server_, &channel_args, nullptr), - std::move(interceptor_creators)); -} - -static grpc_server_register_method_payload_handling PayloadHandlingForMethod( - grpc::internal::RpcServiceMethod* method) { - switch (method->method_type()) { - case grpc::internal::RpcMethod::NORMAL_RPC: - case grpc::internal::RpcMethod::SERVER_STREAMING: - return GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER; - case grpc::internal::RpcMethod::CLIENT_STREAMING: - case grpc::internal::RpcMethod::BIDI_STREAMING: - return GRPC_SRM_PAYLOAD_NONE; - } - GPR_UNREACHABLE_CODE(return GRPC_SRM_PAYLOAD_NONE;); -} - -bool Server::RegisterService(const grpc::string* host, grpc::Service* service) { - bool has_async_methods = service->has_async_methods(); - if (has_async_methods) { - GPR_ASSERT(service->server_ == nullptr && - "Can only register an asynchronous service against one server."); - service->server_ = this; - } - - const char* method_name = nullptr; - - for (auto it = service->methods_.begin(); it != service->methods_.end(); - ++it) { - if (it->get() == nullptr) { // Handled by generic service if any. - continue; - } - - grpc::internal::RpcServiceMethod* method = it->get(); - void* method_registration_tag = grpc_server_register_method( - server_, method->name(), host ? host->c_str() : nullptr, - PayloadHandlingForMethod(method), 0); - if (method_registration_tag == nullptr) { - gpr_log(GPR_DEBUG, "Attempt to register %s multiple times", - method->name()); - return false; - } - - if (method->handler() == nullptr) { // Async method without handler - method->set_server_tag(method_registration_tag); - } else if (method->api_type() == - grpc::internal::RpcServiceMethod::ApiType::SYNC) { - for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { - (*it)->AddSyncMethod(method, method_registration_tag); - } - } else { - // a callback method. Register at least some callback requests - callback_unmatched_reqs_count_.push_back(0); - auto method_index = callback_unmatched_reqs_count_.size() - 1; - // TODO(vjpai): Register these dynamically based on need - for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) { - callback_reqs_to_start_.push_back( - new CallbackRequest(this, method_index, method, - method_registration_tag)); - } - // Enqueue it so that it will be Request'ed later after all request - // matchers are created at core server startup - } - - method_name = method->name(); - } - - // Parse service name. - if (method_name != nullptr) { - std::stringstream ss(method_name); - grpc::string service_name; - if (std::getline(ss, service_name, '/') && - std::getline(ss, service_name, '/')) { - services_.push_back(service_name); - } - } - return true; -} - -void Server::RegisterAsyncGenericService(grpc::AsyncGenericService* service) { - GPR_ASSERT(service->server_ == nullptr && - "Can only register an async generic service against one server."); - service->server_ = this; - has_async_generic_service_ = true; -} - -void Server::RegisterCallbackGenericService( - grpc::experimental::CallbackGenericService* service) { - GPR_ASSERT( - service->server_ == nullptr && - "Can only register a callback generic service against one server."); - service->server_ = this; - has_callback_generic_service_ = true; - generic_handler_.reset(service->Handler()); - - callback_unmatched_reqs_count_.push_back(0); - auto method_index = callback_unmatched_reqs_count_.size() - 1; - // TODO(vjpai): Register these dynamically based on need - for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) { - callback_reqs_to_start_.push_back( - new CallbackRequest(this, method_index, - nullptr, nullptr)); - } -} - -int Server::AddListeningPort(const grpc::string& addr, - grpc::ServerCredentials* creds) { - GPR_ASSERT(!started_); - int port = creds->AddPortToServer(addr, server_); - global_callbacks_->AddPort(this, addr, creds, port); - return port; -} - -void Server::Start(grpc::ServerCompletionQueue** cqs, size_t num_cqs) { - GPR_ASSERT(!started_); - global_callbacks_->PreServerStart(this); - started_ = true; - - // Only create default health check service when user did not provide an - // explicit one. - grpc::ServerCompletionQueue* health_check_cq = nullptr; - grpc::DefaultHealthCheckService::HealthCheckServiceImpl* - default_health_check_service_impl = nullptr; - if (health_check_service_ == nullptr && !health_check_service_disabled_ && - grpc::DefaultHealthCheckServiceEnabled()) { - auto* default_hc_service = new grpc::DefaultHealthCheckService; - health_check_service_.reset(default_hc_service); - // We create a non-polling CQ to avoid impacting application - // performance. This ensures that we don't introduce thread hops - // for application requests that wind up on this CQ, which is polled - // in its own thread. - health_check_cq = new grpc::ServerCompletionQueue( - GRPC_CQ_NEXT, GRPC_CQ_NON_POLLING, nullptr); - grpc_server_register_completion_queue(server_, health_check_cq->cq(), - nullptr); - default_health_check_service_impl = - default_hc_service->GetHealthCheckService( - std::unique_ptr(health_check_cq)); - RegisterService(nullptr, default_health_check_service_impl); - } - - // If this server uses callback methods, then create a callback generic - // service to handle any unimplemented methods using the default reactor - // creator - if (!callback_reqs_to_start_.empty() && !has_callback_generic_service_) { - unimplemented_service_.reset( - new grpc::experimental::CallbackGenericService); - RegisterCallbackGenericService(unimplemented_service_.get()); - } - - grpc_server_start(server_); - - if (!has_async_generic_service_ && !has_callback_generic_service_) { - for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { - (*it)->AddUnknownSyncMethod(); - } - - for (size_t i = 0; i < num_cqs; i++) { - if (cqs[i]->IsFrequentlyPolled()) { - new UnimplementedAsyncRequest(this, cqs[i]); - } - } - if (health_check_cq != nullptr) { - new UnimplementedAsyncRequest(this, health_check_cq); - } - } - - // If this server has any support for synchronous methods (has any sync - // server CQs), make sure that we have a ResourceExhausted handler - // to deal with the case of thread exhaustion - if (sync_server_cqs_ != nullptr && !sync_server_cqs_->empty()) { - resource_exhausted_handler_.reset( - new grpc::internal::ResourceExhaustedHandler); - } - - for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { - (*it)->Start(); - } - - for (auto* cbreq : callback_reqs_to_start_) { - GPR_ASSERT(cbreq->Request()); - } - callback_reqs_to_start_.clear(); - - if (default_health_check_service_impl != nullptr) { - default_health_check_service_impl->StartServingThread(); - } -} - -void Server::ShutdownInternal(gpr_timespec deadline) { - grpc::internal::MutexLock lock(&mu_); - if (shutdown_) { - return; - } - - shutdown_ = true; - - /// The completion queue to use for server shutdown completion notification - grpc::CompletionQueue shutdown_cq; - grpc::ShutdownTag shutdown_tag; // Dummy shutdown tag - grpc_server_shutdown_and_notify(server_, shutdown_cq.cq(), &shutdown_tag); - - shutdown_cq.Shutdown(); - - void* tag; - bool ok; - grpc::CompletionQueue::NextStatus status = - shutdown_cq.AsyncNext(&tag, &ok, deadline); - - // If this timed out, it means we are done with the grace period for a clean - // shutdown. We should force a shutdown now by cancelling all inflight calls - if (status == grpc::CompletionQueue::NextStatus::TIMEOUT) { - grpc_server_cancel_all_calls(server_); - } - // Else in case of SHUTDOWN or GOT_EVENT, it means that the server has - // successfully shutdown - - // Shutdown all ThreadManagers. This will try to gracefully stop all the - // threads in the ThreadManagers (once they process any inflight requests) - for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { - (*it)->Shutdown(); // ThreadManager's Shutdown() - } - - // Wait for threads in all ThreadManagers to terminate - for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { - (*it)->Wait(); - } - - // Wait for all outstanding callback requests to complete - // (whether waiting for a match or already active). - // We know that no new requests will be created after this point - // because they are only created at server startup time or when - // we have a successful match on a request. During the shutdown phase, - // requests that have not yet matched will be failed rather than - // allowed to succeed, which will cause the server to delete the - // request and decrement the count. Possibly a request will match before - // the shutdown but then find that shutdown has already started by the - // time it tries to register a new request. In that case, the registration - // will report a failure, indicating a shutdown and again we won't end - // up incrementing the counter. - { - grpc::internal::MutexLock cblock(&callback_reqs_mu_); - callback_reqs_done_cv_.WaitUntil( - &callback_reqs_mu_, [this] { return callback_reqs_outstanding_ == 0; }); - } - - // Drain the shutdown queue (if the previous call to AsyncNext() timed out - // and we didn't remove the tag from the queue yet) - while (shutdown_cq.Next(&tag, &ok)) { - // Nothing to be done here. Just ignore ok and tag values - } - - shutdown_notified_ = true; - shutdown_cv_.Broadcast(); -} - -void Server::Wait() { - grpc::internal::MutexLock lock(&mu_); - while (started_ && !shutdown_notified_) { - shutdown_cv_.Wait(&mu_); - } -} - -void Server::PerformOpsOnCall(grpc::internal::CallOpSetInterface* ops, - grpc::internal::Call* call) { - ops->FillOps(call); -} - -bool Server::UnimplementedAsyncRequest::FinalizeResult(void** tag, - bool* status) { - if (GenericAsyncRequest::FinalizeResult(tag, status)) { - // We either had no interceptors run or we are done intercepting - if (*status) { - new UnimplementedAsyncRequest(server_, cq_); - new UnimplementedAsyncResponse(this); - } else { - delete this; - } - } else { - // The tag was swallowed due to interception. We will see it again. - } - return false; -} - -Server::UnimplementedAsyncResponse::UnimplementedAsyncResponse( - UnimplementedAsyncRequest* request) - : request_(request) { - grpc::Status status(grpc::StatusCode::UNIMPLEMENTED, ""); - grpc::internal::UnknownMethodHandler::FillOps(request_->context(), this); - request_->stream()->call_.PerformOps(this); -} - -grpc::ServerInitializer* Server::initializer() { - return server_initializer_.get(); -} - -grpc::CompletionQueue* Server::CallbackCQ() { +CompletionQueue* Server::CallbackCQ() { // TODO(vjpai): Consider using a single global CQ for the default CQ // if there is no explicit per-server CQ registered - grpc::internal::MutexLock l(&mu_); + std::lock_guard l(mu_); if (callback_cq_ == nullptr) { - auto* shutdown_callback = new grpc::ShutdownCallback; - callback_cq_ = new grpc::CompletionQueue(grpc_completion_queue_attributes{ + auto* shutdown_callback = new ShutdownCallback; + callback_cq_ = new CompletionQueue(grpc_completion_queue_attributes{ GRPC_CQ_CURRENT_VERSION, GRPC_CQ_CALLBACK, GRPC_CQ_DEFAULT_POLLING, shutdown_callback}); @@ -1355,4 +1335,4 @@ grpc::CompletionQueue* Server::CallbackCQ() { return callback_cq_; } -} // namespace grpc_impl +} // namespace grpc diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc index 70c5cd8861e..73fd6a62c48 100644 --- a/src/cpp/server/server_context.cc +++ b/src/cpp/server/server_context.cc @@ -33,7 +33,6 @@ #include #include "src/core/lib/gprpp/ref_counted.h" -#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/surface/call.h" namespace grpc { @@ -97,7 +96,7 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { } void SetCancelCallback(std::function callback) { - grpc_core::MutexLock lock(&mu_); + std::lock_guard lock(mu_); if (finalized_ && (cancelled_ != 0)) { callback(); @@ -108,7 +107,7 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { } void ClearCancelCallback() { - grpc_core::MutexLock g(&mu_); + std::lock_guard g(mu_); cancel_callback_ = nullptr; } @@ -145,7 +144,7 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { private: bool CheckCancelledNoPluck() { - grpc_core::MutexLock lock(&mu_); + std::lock_guard g(mu_); return finalized_ ? (cancelled_ != 0) : false; } @@ -155,7 +154,7 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { void* tag_; void* core_cq_tag_; grpc_core::RefCount refs_; - grpc_core::Mutex mu_; + std::mutex mu_; bool finalized_; int cancelled_; // This is an int (not bool) because it is passed to core std::function cancel_callback_; @@ -187,7 +186,7 @@ void ServerContext::CompletionOp::FillOps(internal::Call* call) { bool ServerContext::CompletionOp::FinalizeResult(void** tag, bool* status) { bool ret = false; - grpc_core::ReleasableMutexLock lock(&mu_); + std::unique_lock lock(mu_); if (done_intercepting_) { /* We are done intercepting. */ if (has_tag_) { @@ -217,11 +216,12 @@ bool ServerContext::CompletionOp::FinalizeResult(void** tag, bool* status) { // Release the lock since we are going to be calling a callback and // interceptors now - lock.Unlock(); + lock.unlock(); if (call_cancel && reactor_ != nullptr) { reactor_->OnCancel(); } + /* Add interception point and run through interceptors */ interceptor_methods_.AddInterceptionHookPoint( experimental::InterceptionHookPoints::POST_RECV_CLOSE); diff --git a/src/cpp/thread_manager/thread_manager.cc b/src/cpp/thread_manager/thread_manager.cc index 2b65352f797..3e8606a76fd 100644 --- a/src/cpp/thread_manager/thread_manager.cc +++ b/src/cpp/thread_manager/thread_manager.cc @@ -62,7 +62,7 @@ ThreadManager::ThreadManager(const char* name, ThreadManager::~ThreadManager() { { - grpc_core::MutexLock lock(&mu_); + std::lock_guard lock(mu_); GPR_ASSERT(num_threads_ == 0); } @@ -72,38 +72,38 @@ ThreadManager::~ThreadManager() { } void ThreadManager::Wait() { - grpc_core::MutexLock lock(&mu_); + std::unique_lock lock(mu_); while (num_threads_ != 0) { - shutdown_cv_.Wait(&mu_); + shutdown_cv_.wait(lock); } } void ThreadManager::Shutdown() { - grpc_core::MutexLock lock(&mu_); + std::lock_guard lock(mu_); shutdown_ = true; } bool ThreadManager::IsShutdown() { - grpc_core::MutexLock lock(&mu_); + std::lock_guard lock(mu_); return shutdown_; } int ThreadManager::GetMaxActiveThreadsSoFar() { - grpc_core::MutexLock list_lock(&list_mu_); + std::lock_guard list_lock(list_mu_); return max_active_threads_sofar_; } void ThreadManager::MarkAsCompleted(WorkerThread* thd) { { - grpc_core::MutexLock list_lock(&list_mu_); + std::lock_guard list_lock(list_mu_); completed_threads_.push_back(thd); } { - grpc_core::MutexLock lock(&mu_); + std::lock_guard lock(mu_); num_threads_--; if (num_threads_ == 0) { - shutdown_cv_.Signal(); + shutdown_cv_.notify_one(); } } @@ -116,7 +116,7 @@ void ThreadManager::CleanupCompletedThreads() { { // swap out the completed threads list: allows other threads to clean up // more quickly - grpc_core::MutexLock lock(&list_mu_); + std::unique_lock lock(list_mu_); completed_threads.swap(completed_threads_); } for (auto thd : completed_threads) delete thd; @@ -132,7 +132,7 @@ void ThreadManager::Initialize() { } { - grpc_core::MutexLock lock(&mu_); + std::unique_lock lock(mu_); num_pollers_ = min_pollers_; num_threads_ = min_pollers_; max_active_threads_sofar_ = min_pollers_; @@ -149,7 +149,7 @@ void ThreadManager::MainWorkLoop() { bool ok; WorkStatus work_status = PollForWork(&tag, &ok); - grpc_core::ReleasableMutexLock lock(&mu_); + std::unique_lock lock(mu_); // Reduce the number of pollers by 1 and check what happened with the poll num_pollers_--; bool done = false; @@ -176,30 +176,30 @@ void ThreadManager::MainWorkLoop() { max_active_threads_sofar_ = num_threads_; } // Drop lock before spawning thread to avoid contention - lock.Unlock(); + lock.unlock(); new WorkerThread(this); } else if (num_pollers_ > 0) { // There is still at least some thread polling, so we can go on // even though we are below the number of pollers that we would // like to have (min_pollers_) - lock.Unlock(); + lock.unlock(); } else { // There are no pollers to spare and we couldn't allocate // a new thread, so resources are exhausted! - lock.Unlock(); + lock.unlock(); resource_exhausted = true; } } else { // There are a sufficient number of pollers available so we can do // the work and continue polling with our existing poller threads - lock.Unlock(); + lock.unlock(); } // Lock is always released at this point - do the application work // or return resource exhausted if there is new work but we couldn't // get a thread in which to do it. DoWork(tag, ok, !resource_exhausted); // Take the lock again to check post conditions - lock.Lock(); + lock.lock(); // If we're shutdown, we should finish at this point. if (shutdown_) done = true; break; diff --git a/src/cpp/thread_manager/thread_manager.h b/src/cpp/thread_manager/thread_manager.h index 2fbf309d421..6f0bd17c5fe 100644 --- a/src/cpp/thread_manager/thread_manager.h +++ b/src/cpp/thread_manager/thread_manager.h @@ -26,7 +26,6 @@ #include -#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/thd.h" #include "src/core/lib/iomgr/resource_quota.h" @@ -141,10 +140,10 @@ class ThreadManager { // Protects shutdown_, num_pollers_, num_threads_ and // max_active_threads_sofar_ - grpc_core::Mutex mu_; + std::mutex mu_; bool shutdown_; - grpc_core::CondVar shutdown_cv_; + std::condition_variable shutdown_cv_; // The resource user object to use when requesting quota to create threads // @@ -170,7 +169,7 @@ class ThreadManager { // ever set so far int max_active_threads_sofar_; - grpc_core::Mutex list_mu_; + std::mutex list_mu_; std::list completed_threads_; }; diff --git a/test/cpp/client/client_channel_stress_test.cc b/test/cpp/client/client_channel_stress_test.cc index d326b2ed37e..91419cb257b 100644 --- a/test/cpp/client/client_channel_stress_test.cc +++ b/test/cpp/client/client_channel_stress_test.cc @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -169,24 +168,24 @@ class ClientChannelStressTest { explicit ServerThread(const grpc::string& type, const grpc::string& server_host, T* service) : type_(type), service_(service) { - grpc::internal::Mutex mu; + std::mutex mu; // We need to acquire the lock here in order to prevent the notify_one // by ServerThread::Start from firing before the wait below is hit. - grpc::internal::MutexLock lock(&mu); + std::unique_lock lock(mu); port_ = grpc_pick_unused_port_or_die(); gpr_log(GPR_INFO, "starting %s server on port %d", type_.c_str(), port_); - grpc::internal::CondVar cond; + std::condition_variable cond; thread_.reset(new std::thread( std::bind(&ServerThread::Start, this, server_host, &mu, &cond))); - cond.Wait(&mu); + cond.wait(lock); gpr_log(GPR_INFO, "%s server startup complete", type_.c_str()); } - void Start(const grpc::string& server_host, grpc::internal::Mutex* mu, - grpc::internal::CondVar* cond) { + void Start(const grpc::string& server_host, std::mutex* mu, + std::condition_variable* cond) { // We need to acquire the lock here in order to prevent the notify_one // below from firing before its corresponding wait is executed. - grpc::internal::MutexLock lock(mu); + std::lock_guard lock(*mu); std::ostringstream server_address; server_address << server_host << ":" << port_; ServerBuilder builder; @@ -194,7 +193,7 @@ class ClientChannelStressTest { InsecureServerCredentials()); builder.RegisterService(service_); server_ = builder.BuildAndStart(); - cond->Signal(); + cond->notify_one(); } void Shutdown() { diff --git a/test/cpp/end2end/client_lb_end2end_test.cc b/test/cpp/end2end/client_lb_end2end_test.cc index 6623a2ff55f..77f9db94acc 100644 --- a/test/cpp/end2end/client_lb_end2end_test.cc +++ b/test/cpp/end2end/client_lb_end2end_test.cc @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -99,7 +98,7 @@ class MyTestServiceImpl : public TestServiceImpl { Status Echo(ServerContext* context, const EchoRequest* request, EchoResponse* response) override { { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); ++request_count_; } AddClient(context->peer()); @@ -107,29 +106,29 @@ class MyTestServiceImpl : public TestServiceImpl { } int request_count() { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); return request_count_; } void ResetCounters() { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); request_count_ = 0; } std::set clients() { - grpc::internal::MutexLock lock(&clients_mu_); + std::unique_lock lock(clients_mu_); return clients_; } private: void AddClient(const grpc::string& client) { - grpc::internal::MutexLock lock(&clients_mu_); + std::unique_lock lock(clients_mu_); clients_.insert(client); } - grpc::internal::Mutex mu_; + std::mutex mu_; int request_count_; - grpc::internal::Mutex clients_mu_; + std::mutex clients_mu_; std::set clients_; }; @@ -294,18 +293,18 @@ class ClientLbEnd2endTest : public ::testing::Test { void Start(const grpc::string& server_host) { gpr_log(GPR_INFO, "starting server on port %d", port_); started_ = true; - grpc::internal::Mutex mu; - grpc::internal::MutexLock lock(&mu); - grpc::internal::CondVar cond; + std::mutex mu; + std::unique_lock lock(mu); + std::condition_variable cond; thread_.reset(new std::thread( std::bind(&ServerData::Serve, this, server_host, &mu, &cond))); - cond.WaitUntil(&mu, [this] { return server_ready_; }); + cond.wait(lock, [this] { return server_ready_; }); server_ready_ = false; gpr_log(GPR_INFO, "server startup complete"); } - void Serve(const grpc::string& server_host, grpc::internal::Mutex* mu, - grpc::internal::CondVar* cond) { + void Serve(const grpc::string& server_host, std::mutex* mu, + std::condition_variable* cond) { std::ostringstream server_address; server_address << server_host << ":" << port_; ServerBuilder builder; @@ -314,9 +313,9 @@ class ClientLbEnd2endTest : public ::testing::Test { builder.AddListeningPort(server_address.str(), std::move(creds)); builder.RegisterService(&service_); server_ = builder.BuildAndStart(); - grpc::internal::MutexLock lock(mu); + std::lock_guard lock(*mu); server_ready_ = true; - cond->Signal(); + cond->notify_one(); } void Shutdown() { @@ -1375,7 +1374,7 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest { void TearDown() override { ClientLbEnd2endTest::TearDown(); } int trailers_intercepted() { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); return trailers_intercepted_; } @@ -1383,11 +1382,11 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest { static void ReportTrailerIntercepted(void* arg) { ClientLbInterceptTrailingMetadataTest* self = static_cast(arg); - grpc::internal::MutexLock lock(&self->mu_); + std::unique_lock lock(self->mu_); self->trailers_intercepted_++; } - grpc::internal::Mutex mu_; + std::mutex mu_; int trailers_intercepted_ = 0; }; diff --git a/test/cpp/end2end/grpclb_end2end_test.cc b/test/cpp/end2end/grpclb_end2end_test.cc index f8d887dd24d..0dc3746c2d7 100644 --- a/test/cpp/end2end/grpclb_end2end_test.cc +++ b/test/cpp/end2end/grpclb_end2end_test.cc @@ -30,7 +30,6 @@ #include #include #include -#include #include #include @@ -86,32 +85,32 @@ template class CountedService : public ServiceType { public: size_t request_count() { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); return request_count_; } size_t response_count() { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); return response_count_; } void IncreaseResponseCount() { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); ++response_count_; } void IncreaseRequestCount() { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); ++request_count_; } void ResetCounters() { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); request_count_ = 0; response_count_ = 0; } protected: - grpc::internal::Mutex mu_; + std::mutex mu_; private: size_t request_count_ = 0; @@ -149,18 +148,18 @@ class BackendServiceImpl : public BackendService { void Shutdown() {} std::set clients() { - grpc::internal::MutexLock lock(&clients_mu_); + std::unique_lock lock(clients_mu_); return clients_; } private: void AddClient(const grpc::string& client) { - grpc::internal::MutexLock lock(&clients_mu_); + std::unique_lock lock(clients_mu_); clients_.insert(client); } - grpc::internal::Mutex mu_; - grpc::internal::Mutex clients_mu_; + std::mutex mu_; + std::mutex clients_mu_; std::set clients_; }; @@ -211,7 +210,7 @@ class BalancerServiceImpl : public BalancerService { Status BalanceLoad(ServerContext* context, Stream* stream) override { gpr_log(GPR_INFO, "LB[%p]: BalanceLoad", this); { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); if (serverlist_done_) goto done; } { @@ -238,7 +237,7 @@ class BalancerServiceImpl : public BalancerService { } { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); responses_and_delays = responses_and_delays_; } for (const auto& response_and_delay : responses_and_delays) { @@ -246,8 +245,8 @@ class BalancerServiceImpl : public BalancerService { response_and_delay.second); } { - grpc::internal::MutexLock lock(&mu_); - serverlist_cond_.WaitUntil(&mu_, [this] { return serverlist_done_; }); + std::unique_lock lock(mu_); + serverlist_cond_.wait(lock, [this] { return serverlist_done_; }); } if (client_load_reporting_interval_seconds_ > 0) { @@ -258,7 +257,7 @@ class BalancerServiceImpl : public BalancerService { GPR_ASSERT(request.has_client_stats()); // We need to acquire the lock here in order to prevent the notify_one // below from firing before its corresponding wait is executed. - grpc::internal::MutexLock lock(&mu_); + std::lock_guard lock(mu_); client_stats_.num_calls_started += request.client_stats().num_calls_started(); client_stats_.num_calls_finished += @@ -275,7 +274,7 @@ class BalancerServiceImpl : public BalancerService { drop_token_count.num_calls(); } load_report_ready_ = true; - load_report_cond_.Signal(); + load_report_cond_.notify_one(); } } } @@ -285,12 +284,12 @@ class BalancerServiceImpl : public BalancerService { } void add_response(const LoadBalanceResponse& response, int send_after_ms) { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); responses_and_delays_.push_back(std::make_pair(response, send_after_ms)); } void Start() { - grpc::internal::MutexLock lock(&mu_); + std::lock_guard lock(mu_); serverlist_done_ = false; load_report_ready_ = false; responses_and_delays_.clear(); @@ -327,17 +326,17 @@ class BalancerServiceImpl : public BalancerService { } const ClientStats& WaitForLoadReport() { - grpc::internal::MutexLock lock(&mu_); - load_report_cond_.WaitUntil(&mu_, [this] { return load_report_ready_; }); + std::unique_lock lock(mu_); + load_report_cond_.wait(lock, [this] { return load_report_ready_; }); load_report_ready_ = false; return client_stats_; } void NotifyDoneWithServerlists() { - grpc::internal::MutexLock lock(&mu_); + std::lock_guard lock(mu_); if (!serverlist_done_) { serverlist_done_ = true; - serverlist_cond_.Broadcast(); + serverlist_cond_.notify_all(); } } @@ -356,10 +355,10 @@ class BalancerServiceImpl : public BalancerService { const int client_load_reporting_interval_seconds_; std::vector responses_and_delays_; - grpc::internal::Mutex mu_; - grpc::internal::CondVar load_report_cond_; + std::mutex mu_; + std::condition_variable load_report_cond_; bool load_report_ready_ = false; - grpc::internal::CondVar serverlist_cond_; + std::condition_variable serverlist_cond_; bool serverlist_done_ = false; ClientStats client_stats_; }; @@ -625,22 +624,22 @@ class GrpclbEnd2endTest : public ::testing::Test { GPR_ASSERT(!running_); running_ = true; service_.Start(); - grpc::internal::Mutex mu; + std::mutex mu; // We need to acquire the lock here in order to prevent the notify_one // by ServerThread::Serve from firing before the wait below is hit. - grpc::internal::MutexLock lock(&mu); - grpc::internal::CondVar cond; + std::unique_lock lock(mu); + std::condition_variable cond; thread_.reset(new std::thread( std::bind(&ServerThread::Serve, this, server_host, &mu, &cond))); - cond.Wait(&mu); + cond.wait(lock); gpr_log(GPR_INFO, "%s server startup complete", type_.c_str()); } - void Serve(const grpc::string& server_host, grpc::internal::Mutex* mu, - grpc::internal::CondVar* cond) { + void Serve(const grpc::string& server_host, std::mutex* mu, + std::condition_variable* cond) { // We need to acquire the lock here in order to prevent the notify_one // below from firing before its corresponding wait is executed. - grpc::internal::MutexLock lock(mu); + std::lock_guard lock(*mu); std::ostringstream server_address; server_address << server_host << ":" << port_; ServerBuilder builder; @@ -649,7 +648,7 @@ class GrpclbEnd2endTest : public ::testing::Test { builder.AddListeningPort(server_address.str(), creds); builder.RegisterService(&service_); server_ = builder.BuildAndStart(); - cond->Signal(); + cond->notify_one(); } void Shutdown() { diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc index 5b8af61ee33..e30ce0dbcbf 100644 --- a/test/cpp/end2end/thread_stress_test.cc +++ b/test/cpp/end2end/thread_stress_test.cc @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -189,7 +188,7 @@ class CommonStressTestAsyncServer : public BaseClass { } void TearDown() override { { - grpc::internal::MutexLock l(&mu_); + std::unique_lock l(mu_); this->TearDownStart(); shutting_down_ = true; cq_->Shutdown(); @@ -230,7 +229,7 @@ class CommonStressTestAsyncServer : public BaseClass { } } void RefreshContext(int i) { - grpc::internal::MutexLock l(&mu_); + std::unique_lock l(mu_); if (!shutting_down_) { contexts_[i].state = Context::READY; contexts_[i].srv_ctx.reset(new ServerContext); @@ -254,7 +253,7 @@ class CommonStressTestAsyncServer : public BaseClass { ::grpc::testing::EchoTestService::AsyncService service_; std::unique_ptr cq_; bool shutting_down_; - grpc::internal::Mutex mu_; + std::mutex mu_; std::vector server_threads_; }; @@ -342,9 +341,9 @@ class AsyncClientEnd2endTest : public ::testing::Test { } void Wait() { - grpc::internal::MutexLock l(&mu_); + std::unique_lock l(mu_); while (rpcs_outstanding_ != 0) { - cv_.Wait(&mu_); + cv_.wait(l); } cq_.Shutdown(); @@ -367,7 +366,7 @@ class AsyncClientEnd2endTest : public ::testing::Test { call->response_reader->Finish(&call->response, &call->status, (void*)call); - grpc::internal::MutexLock l(&mu_); + std::unique_lock l(mu_); rpcs_outstanding_++; } } @@ -385,20 +384,20 @@ class AsyncClientEnd2endTest : public ::testing::Test { bool notify; { - grpc::internal::MutexLock l(&mu_); + std::unique_lock l(mu_); rpcs_outstanding_--; notify = (rpcs_outstanding_ == 0); } if (notify) { - cv_.Signal(); + cv_.notify_all(); } } } Common common_; CompletionQueue cq_; - grpc::internal::Mutex mu_; - grpc::internal::CondVar cv_; + std::mutex mu_; + std::condition_variable cv_; int rpcs_outstanding_; }; diff --git a/test/cpp/end2end/xds_end2end_test.cc b/test/cpp/end2end/xds_end2end_test.cc index ee248239909..c767a4485ce 100644 --- a/test/cpp/end2end/xds_end2end_test.cc +++ b/test/cpp/end2end/xds_end2end_test.cc @@ -84,32 +84,32 @@ template class CountedService : public ServiceType { public: size_t request_count() { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); return request_count_; } size_t response_count() { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); return response_count_; } void IncreaseResponseCount() { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); ++response_count_; } void IncreaseRequestCount() { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); ++request_count_; } void ResetCounters() { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); request_count_ = 0; response_count_ = 0; } protected: - grpc::internal::Mutex mu_; + std::mutex mu_; private: size_t request_count_ = 0; @@ -145,18 +145,18 @@ class BackendServiceImpl : public BackendService { void Shutdown() {} std::set clients() { - grpc::internal::MutexLock lock(&clients_mu_); + std::unique_lock lock(clients_mu_); return clients_; } private: void AddClient(const grpc::string& client) { - grpc::internal::MutexLock lock(&clients_mu_); + std::unique_lock lock(clients_mu_); clients_.insert(client); } - grpc::internal::Mutex mu_; - grpc::internal::Mutex clients_mu_; + std::mutex mu_; + std::mutex clients_mu_; std::set clients_; }; @@ -208,7 +208,7 @@ class BalancerServiceImpl : public BalancerService { // TODO(juanlishen): Clean up the scoping. gpr_log(GPR_INFO, "LB[%p]: BalanceLoad", this); { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); if (serverlist_done_) goto done; } { @@ -234,7 +234,7 @@ class BalancerServiceImpl : public BalancerService { } { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); responses_and_delays = responses_and_delays_; } for (const auto& response_and_delay : responses_and_delays) { @@ -242,8 +242,8 @@ class BalancerServiceImpl : public BalancerService { response_and_delay.second); } { - grpc::internal::MutexLock lock(&mu_); - serverlist_cond_.WaitUntil(&mu_, [this] { return serverlist_done_; }); + std::unique_lock lock(mu_); + serverlist_cond_.wait(lock, [this] { return serverlist_done_; }); } if (client_load_reporting_interval_seconds_ > 0) { @@ -254,7 +254,7 @@ class BalancerServiceImpl : public BalancerService { GPR_ASSERT(request.has_client_stats()); // We need to acquire the lock here in order to prevent the notify_one // below from firing before its corresponding wait is executed. - grpc::internal::MutexLock lock(&mu_); + std::lock_guard lock(mu_); client_stats_.num_calls_started += request.client_stats().num_calls_started(); client_stats_.num_calls_finished += @@ -271,7 +271,7 @@ class BalancerServiceImpl : public BalancerService { drop_token_count.num_calls(); } load_report_ready_ = true; - load_report_cond_.Signal(); + load_report_cond_.notify_one(); } } } @@ -281,12 +281,12 @@ class BalancerServiceImpl : public BalancerService { } void add_response(const LoadBalanceResponse& response, int send_after_ms) { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); responses_and_delays_.push_back(std::make_pair(response, send_after_ms)); } void Shutdown() { - grpc::internal::MutexLock lock(&mu_); + std::unique_lock lock(mu_); NotifyDoneWithServerlistsLocked(); responses_and_delays_.clear(); client_stats_.Reset(); @@ -318,21 +318,21 @@ class BalancerServiceImpl : public BalancerService { } const ClientStats& WaitForLoadReport() { - grpc::internal::MutexLock lock(&mu_); - load_report_cond_.WaitUntil(&mu_, [this] { return load_report_ready_; }); + std::unique_lock lock(mu_); + load_report_cond_.wait(lock, [this] { return load_report_ready_; }); load_report_ready_ = false; return client_stats_; } void NotifyDoneWithServerlists() { - grpc::internal::MutexLock lock(&mu_); + std::lock_guard lock(mu_); NotifyDoneWithServerlistsLocked(); } void NotifyDoneWithServerlistsLocked() { if (!serverlist_done_) { serverlist_done_ = true; - serverlist_cond_.Broadcast(); + serverlist_cond_.notify_all(); } } @@ -351,10 +351,10 @@ class BalancerServiceImpl : public BalancerService { const int client_load_reporting_interval_seconds_; std::vector responses_and_delays_; - grpc::internal::Mutex mu_; - grpc::internal::CondVar load_report_cond_; + std::mutex mu_; + std::condition_variable load_report_cond_; bool load_report_ready_ = false; - grpc::internal::CondVar serverlist_cond_; + std::condition_variable serverlist_cond_; bool serverlist_done_ = false; ClientStats client_stats_; }; @@ -637,22 +637,22 @@ class XdsEnd2endTest : public ::testing::Test { gpr_log(GPR_INFO, "starting %s server on port %d", type_.c_str(), port_); GPR_ASSERT(!running_); running_ = true; - grpc::internal::Mutex mu; + std::mutex mu; // We need to acquire the lock here in order to prevent the notify_one // by ServerThread::Serve from firing before the wait below is hit. - grpc::internal::MutexLock lock(&mu); - grpc::internal::CondVar cond; + std::unique_lock lock(mu); + std::condition_variable cond; thread_.reset(new std::thread( std::bind(&ServerThread::Serve, this, server_host, &mu, &cond))); - cond.Wait(&mu); + cond.wait(lock); gpr_log(GPR_INFO, "%s server startup complete", type_.c_str()); } - void Serve(const grpc::string& server_host, grpc::internal::Mutex* mu, - grpc::internal::CondVar* cond) { + void Serve(const grpc::string& server_host, std::mutex* mu, + std::condition_variable* cond) { // We need to acquire the lock here in order to prevent the notify_one // below from firing before its corresponding wait is executed. - grpc::internal::MutexLock lock(mu); + std::lock_guard lock(*mu); std::ostringstream server_address; server_address << server_host << ":" << port_; ServerBuilder builder; @@ -661,7 +661,7 @@ class XdsEnd2endTest : public ::testing::Test { builder.AddListeningPort(server_address.str(), creds); builder.RegisterService(&service_); server_ = builder.BuildAndStart(); - cond->Signal(); + cond->notify_one(); } void Shutdown() { diff --git a/test/cpp/util/metrics_server.h b/test/cpp/util/metrics_server.h index 08f6034c28e..2d6ddf08043 100644 --- a/test/cpp/util/metrics_server.h +++ b/test/cpp/util/metrics_server.h @@ -21,8 +21,6 @@ #include #include -#include - #include "src/proto/grpc/testing/metrics.grpc.pb.h" #include "src/proto/grpc/testing/metrics.pb.h" diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 67bbb4efa6b..7274f9588b3 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -987,7 +987,6 @@ include/grpcpp/impl/codegen/status.h \ include/grpcpp/impl/codegen/status_code_enum.h \ include/grpcpp/impl/codegen/string_ref.h \ include/grpcpp/impl/codegen/stub_options.h \ -include/grpcpp/impl/codegen/sync.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ include/grpcpp/impl/grpc_library.h \ @@ -1013,7 +1012,6 @@ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ include/grpcpp/server_builder_impl.h \ include/grpcpp/server_context.h \ -include/grpcpp/server_impl.h \ include/grpcpp/server_posix.h \ include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 438cb98dbae..f169199ae96 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -989,7 +989,6 @@ include/grpcpp/impl/codegen/status.h \ include/grpcpp/impl/codegen/status_code_enum.h \ include/grpcpp/impl/codegen/string_ref.h \ include/grpcpp/impl/codegen/stub_options.h \ -include/grpcpp/impl/codegen/sync.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ include/grpcpp/impl/grpc_library.h \ @@ -1015,7 +1014,6 @@ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ include/grpcpp/server_builder_impl.h \ include/grpcpp/server_context.h \ -include/grpcpp/server_impl.h \ include/grpcpp/server_posix.h \ include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ @@ -1087,12 +1085,12 @@ src/core/lib/gprpp/inlined_vector.h \ src/core/lib/gprpp/manual_constructor.h \ src/core/lib/gprpp/map.h \ src/core/lib/gprpp/memory.h \ +src/core/lib/gprpp/mutex_lock.h \ src/core/lib/gprpp/optional.h \ src/core/lib/gprpp/orphanable.h \ src/core/lib/gprpp/pair.h \ src/core/lib/gprpp/ref_counted.h \ src/core/lib/gprpp/ref_counted_ptr.h \ -src/core/lib/gprpp/sync.h \ src/core/lib/gprpp/thd.h \ src/core/lib/http/format_request.h \ src/core/lib/http/httpcli.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 1817be44bc3..e68e758c64e 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1166,12 +1166,12 @@ src/core/lib/gprpp/inlined_vector.h \ src/core/lib/gprpp/manual_constructor.h \ src/core/lib/gprpp/map.h \ src/core/lib/gprpp/memory.h \ +src/core/lib/gprpp/mutex_lock.h \ src/core/lib/gprpp/optional.h \ src/core/lib/gprpp/orphanable.h \ src/core/lib/gprpp/pair.h \ src/core/lib/gprpp/ref_counted.h \ src/core/lib/gprpp/ref_counted_ptr.h \ -src/core/lib/gprpp/sync.h \ src/core/lib/gprpp/thd.h \ src/core/lib/gprpp/thd_posix.cc \ src/core/lib/gprpp/thd_windows.cc \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 8534e71e2ce..29fd6f32e59 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -8033,8 +8033,8 @@ "src/core/lib/gprpp/manual_constructor.h", "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", + "src/core/lib/gprpp/mutex_lock.h", "src/core/lib/gprpp/pair.h", - "src/core/lib/gprpp/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/profiling/timers.h" ], @@ -8081,8 +8081,8 @@ "src/core/lib/gprpp/manual_constructor.h", "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", + "src/core/lib/gprpp/mutex_lock.h", "src/core/lib/gprpp/pair.h", - "src/core/lib/gprpp/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/profiling/timers.h" ], @@ -9860,7 +9860,6 @@ }, { "deps": [ - "grpc++_internal_hdrs_only", "grpc_codegen" ], "headers": [ @@ -10057,7 +10056,6 @@ "gpr", "gpr_base_headers", "grpc++_codegen_base", - "grpc++_internal_hdrs_only", "grpc_base_headers", "grpc_transport_inproc_headers", "health_proto", @@ -10152,7 +10150,6 @@ "include/grpcpp/server_builder.h", "include/grpcpp/server_builder_impl.h", "include/grpcpp/server_context.h", - "include/grpcpp/server_impl.h", "include/grpcpp/server_posix.h", "include/grpcpp/server_posix_impl.h", "include/grpcpp/support/async_stream.h", @@ -10273,7 +10270,6 @@ "include/grpcpp/server_builder.h", "include/grpcpp/server_builder_impl.h", "include/grpcpp/server_context.h", - "include/grpcpp/server_impl.h", "include/grpcpp/server_posix.h", "include/grpcpp/server_posix_impl.h", "include/grpcpp/support/async_stream.h", @@ -10354,20 +10350,6 @@ "third_party": false, "type": "filegroup" }, - { - "deps": [], - "headers": [ - "include/grpcpp/impl/codegen/sync.h" - ], - "is_filegroup": true, - "language": "c++", - "name": "grpc++_internal_hdrs_only", - "src": [ - "include/grpcpp/impl/codegen/sync.h" - ], - "third_party": false, - "type": "filegroup" - }, { "deps": [], "headers": [ From e85dd2e644fb13056f818947efc72db625a34e71 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Mon, 8 Apr 2019 20:10:09 -0400 Subject: [PATCH 237/242] Fix build errors --- BUILD | 14 +- BUILD.gn | 5 +- CMakeLists.txt | 5 + Makefile | 5 + build.yaml | 8 +- gRPC-C++.podspec | 7 +- gRPC-Core.podspec | 4 +- grpc.gemspec | 2 +- include/grpcpp/channel.h | 3 +- include/grpcpp/impl/codegen/client_context.h | 3 +- include/grpcpp/impl/codegen/sync.h | 138 ++++++++++++++++++ include/grpcpp/server.h | 8 +- include/grpcpp/server_impl.h | 8 +- package.xml | 2 +- .../filters/client_channel/client_channel.cc | 2 +- .../health/health_check_client.cc | 4 +- .../health/health_check_client.h | 3 +- .../client_channel/http_connect_handshaker.cc | 2 +- .../client_channel/lb_policy/grpclb/grpclb.cc | 1 - .../lb_policy/grpclb/grpclb_client_stats.cc | 2 +- .../lb_policy/grpclb/grpclb_client_stats.h | 6 +- .../lb_policy/pick_first/pick_first.cc | 6 +- .../lb_policy/round_robin/round_robin.cc | 6 +- .../client_channel/lb_policy/xds/xds.cc | 19 +-- .../client_channel/resolving_lb_policy.cc | 2 +- .../ext/filters/client_channel/subchannel.cc | 70 ++++----- .../ext/filters/client_channel/subchannel.h | 3 +- src/core/lib/channel/channelz_registry.cc | 2 +- src/core/lib/channel/handshaker.h | 2 +- src/core/lib/gprpp/mutex_lock.h | 42 ------ src/core/lib/gprpp/sync.h | 126 ++++++++++++++++ src/core/lib/iomgr/ev_epollex_linux.cc | 2 +- src/core/lib/surface/init.cc | 2 +- .../ssl/session_cache/ssl_session_cache.cc | 2 +- src/cpp/client/channel_cc.cc | 2 +- src/cpp/client/client_context.cc | 5 +- src/cpp/server/dynamic_thread_pool.cc | 23 +-- src/cpp/server/dynamic_thread_pool.h | 7 +- .../health/default_health_check_service.cc | 28 ++-- .../health/default_health_check_service.h | 7 +- src/cpp/server/load_reporter/load_reporter.cc | 18 +-- src/cpp/server/load_reporter/load_reporter.h | 5 +- .../load_reporter_async_service_impl.cc | 24 +-- .../load_reporter_async_service_impl.h | 3 +- src/cpp/server/server_cc.cc | 24 +-- src/cpp/server/server_context.cc | 14 +- src/cpp/thread_manager/thread_manager.cc | 34 ++--- src/cpp/thread_manager/thread_manager.h | 7 +- test/cpp/client/client_channel_stress_test.cc | 17 ++- test/cpp/end2end/client_lb_end2end_test.cc | 37 ++--- test/cpp/end2end/grpclb_end2end_test.cc | 67 ++++----- test/cpp/end2end/thread_stress_test.cc | 21 +-- test/cpp/end2end/xds_end2end_test.cc | 66 ++++----- tools/doxygen/Doxyfile.c++ | 1 + tools/doxygen/Doxyfile.c++.internal | 3 +- tools/doxygen/Doxyfile.core.internal | 2 +- .../generated/sources_and_headers.json | 20 ++- 57 files changed, 611 insertions(+), 340 deletions(-) create mode 100644 include/grpcpp/impl/codegen/sync.h delete mode 100644 src/core/lib/gprpp/mutex_lock.h create mode 100644 src/core/lib/gprpp/sync.h diff --git a/BUILD b/BUILD index 8837ed8075f..b0c501455d1 100644 --- a/BUILD +++ b/BUILD @@ -525,6 +525,17 @@ grpc_cc_library( ], ) +grpc_cc_library( + name = "grpc++_internal_hdrs_only", + hdrs = [ + "include/grpcpp/impl/codegen/sync.h", + ], + language = "c++", + deps = [ + "gpr_codegen", + ], +) + grpc_cc_library( name = "gpr_base", srcs = [ @@ -590,8 +601,8 @@ grpc_cc_library( "src/core/lib/gprpp/manual_constructor.h", "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", - "src/core/lib/gprpp/mutex_lock.h", "src/core/lib/gprpp/pair.h", + "src/core/lib/gprpp/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/profiling/timers.h", ], @@ -2145,6 +2156,7 @@ grpc_cc_library( "include/grpcpp/impl/codegen/time.h", ], deps = [ + "grpc++_internal_hdrs_only", "grpc_codegen", ], ) diff --git a/BUILD.gn b/BUILD.gn index 1417f1db5ea..7f5157377a7 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -186,8 +186,8 @@ config("grpc_config") { "src/core/lib/gprpp/manual_constructor.h", "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", - "src/core/lib/gprpp/mutex_lock.h", "src/core/lib/gprpp/pair.h", + "src/core/lib/gprpp/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/gprpp/thd_posix.cc", "src/core/lib/gprpp/thd_windows.cc", @@ -1064,6 +1064,7 @@ config("grpc_config") { "include/grpcpp/impl/codegen/status_code_enum.h", "include/grpcpp/impl/codegen/string_ref.h", "include/grpcpp/impl/codegen/stub_options.h", + "include/grpcpp/impl/codegen/sync.h", "include/grpcpp/impl/codegen/sync_stream.h", "include/grpcpp/impl/codegen/time.h", "include/grpcpp/impl/grpc_library.h", @@ -1158,12 +1159,12 @@ config("grpc_config") { "src/core/lib/gprpp/manual_constructor.h", "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", - "src/core/lib/gprpp/mutex_lock.h", "src/core/lib/gprpp/optional.h", "src/core/lib/gprpp/orphanable.h", "src/core/lib/gprpp/pair.h", "src/core/lib/gprpp/ref_counted.h", "src/core/lib/gprpp/ref_counted_ptr.h", + "src/core/lib/gprpp/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b99a57633a..cce21957659 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3181,6 +3181,7 @@ foreach(_hdr include/grpcpp/impl/codegen/stub_options.h include/grpcpp/impl/codegen/sync_stream.h include/grpcpp/impl/codegen/time.h + include/grpcpp/impl/codegen/sync.h include/grpc++/impl/codegen/proto_utils.h include/grpcpp/impl/codegen/proto_buffer_reader.h include/grpcpp/impl/codegen/proto_buffer_writer.h @@ -3783,6 +3784,7 @@ foreach(_hdr include/grpcpp/impl/codegen/stub_options.h include/grpcpp/impl/codegen/sync_stream.h include/grpcpp/impl/codegen/time.h + include/grpcpp/impl/codegen/sync.h include/grpc/census.h ) string(REPLACE "include/" "" _path ${_hdr}) @@ -4237,6 +4239,7 @@ foreach(_hdr include/grpc/impl/codegen/sync_generic.h include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h + include/grpcpp/impl/codegen/sync.h include/grpc++/impl/codegen/proto_utils.h include/grpcpp/impl/codegen/proto_buffer_reader.h include/grpcpp/impl/codegen/proto_buffer_writer.h @@ -4433,6 +4436,7 @@ foreach(_hdr include/grpc/impl/codegen/sync_generic.h include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h + include/grpcpp/impl/codegen/sync.h include/grpc++/impl/codegen/proto_utils.h include/grpcpp/impl/codegen/proto_buffer_reader.h include/grpcpp/impl/codegen/proto_buffer_writer.h @@ -4759,6 +4763,7 @@ foreach(_hdr include/grpcpp/impl/codegen/stub_options.h include/grpcpp/impl/codegen/sync_stream.h include/grpcpp/impl/codegen/time.h + include/grpcpp/impl/codegen/sync.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) diff --git a/Makefile b/Makefile index 2e6e6070c43..d972215250a 100644 --- a/Makefile +++ b/Makefile @@ -5516,6 +5516,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/stub_options.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ + include/grpcpp/impl/codegen/sync.h \ include/grpc++/impl/codegen/proto_utils.h \ include/grpcpp/impl/codegen/proto_buffer_reader.h \ include/grpcpp/impl/codegen/proto_buffer_writer.h \ @@ -6126,6 +6127,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/stub_options.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ + include/grpcpp/impl/codegen/sync.h \ include/grpc/census.h \ LIBGRPC++_CRONET_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_CRONET_SRC)))) @@ -6552,6 +6554,7 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ + include/grpcpp/impl/codegen/sync.h \ include/grpc++/impl/codegen/proto_utils.h \ include/grpcpp/impl/codegen/proto_buffer_reader.h \ include/grpcpp/impl/codegen/proto_buffer_writer.h \ @@ -6719,6 +6722,7 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ + include/grpcpp/impl/codegen/sync.h \ include/grpc++/impl/codegen/proto_utils.h \ include/grpcpp/impl/codegen/proto_buffer_reader.h \ include/grpcpp/impl/codegen/proto_buffer_writer.h \ @@ -7051,6 +7055,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/stub_options.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ + include/grpcpp/impl/codegen/sync.h \ LIBGRPC++_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_UNSECURE_SRC)))) diff --git a/build.yaml b/build.yaml index 5e8c803e56f..9e78ec4efa3 100644 --- a/build.yaml +++ b/build.yaml @@ -196,8 +196,8 @@ filegroups: - src/core/lib/gprpp/manual_constructor.h - src/core/lib/gprpp/map.h - src/core/lib/gprpp/memory.h - - src/core/lib/gprpp/mutex_lock.h - src/core/lib/gprpp/pair.h + - src/core/lib/gprpp/sync.h - src/core/lib/gprpp/thd.h - src/core/lib/profiling/timers.h uses: @@ -1276,6 +1276,7 @@ filegroups: - include/grpcpp/impl/codegen/time.h uses: - grpc_codegen + - grpc++_internal_hdrs_only - name: grpc++_codegen_base_src language: c++ src: @@ -1450,6 +1451,7 @@ filegroups: - grpc_base_headers - grpc_transport_inproc_headers - grpc++_codegen_base + - grpc++_internal_hdrs_only - nanopb_headers - health_proto - name: grpc++_config_proto @@ -1457,6 +1459,10 @@ filegroups: public_headers: - include/grpc++/impl/codegen/config_protobuf.h - include/grpcpp/impl/codegen/config_protobuf.h +- name: grpc++_internal_hdrs_only + language: c++ + public_headers: + - include/grpcpp/impl/codegen/sync.h - name: grpc++_reflection_proto language: c++ src: diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index b8f3f56a83f..b8e4d80b838 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -183,7 +183,8 @@ Pod::Spec.new do |s| 'include/grpcpp/impl/codegen/string_ref.h', 'include/grpcpp/impl/codegen/stub_options.h', 'include/grpcpp/impl/codegen/sync_stream.h', - 'include/grpcpp/impl/codegen/time.h' + 'include/grpcpp/impl/codegen/time.h', + 'include/grpcpp/impl/codegen/sync.h' end s.subspec 'Implementation' do |ss| @@ -266,8 +267,8 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/manual_constructor.h', 'src/core/lib/gprpp/map.h', 'src/core/lib/gprpp/memory.h', - 'src/core/lib/gprpp/mutex_lock.h', 'src/core/lib/gprpp/pair.h', + 'src/core/lib/gprpp/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/ext/transport/chttp2/transport/bin_decoder.h', @@ -583,8 +584,8 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/manual_constructor.h', 'src/core/lib/gprpp/map.h', 'src/core/lib/gprpp/memory.h', - 'src/core/lib/gprpp/mutex_lock.h', 'src/core/lib/gprpp/pair.h', + 'src/core/lib/gprpp/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/lib/avl/avl.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index bab7ce4378e..c58152cf7f8 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -210,8 +210,8 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/manual_constructor.h', 'src/core/lib/gprpp/map.h', 'src/core/lib/gprpp/memory.h', - 'src/core/lib/gprpp/mutex_lock.h', 'src/core/lib/gprpp/pair.h', + 'src/core/lib/gprpp/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/lib/gpr/alloc.cc', @@ -889,8 +889,8 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/manual_constructor.h', 'src/core/lib/gprpp/map.h', 'src/core/lib/gprpp/memory.h', - 'src/core/lib/gprpp/mutex_lock.h', 'src/core/lib/gprpp/pair.h', + 'src/core/lib/gprpp/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/ext/transport/chttp2/transport/bin_decoder.h', diff --git a/grpc.gemspec b/grpc.gemspec index b9d2107ee48..c41db6f6293 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -104,8 +104,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/gprpp/manual_constructor.h ) s.files += %w( src/core/lib/gprpp/map.h ) s.files += %w( src/core/lib/gprpp/memory.h ) - s.files += %w( src/core/lib/gprpp/mutex_lock.h ) s.files += %w( src/core/lib/gprpp/pair.h ) + s.files += %w( src/core/lib/gprpp/sync.h ) s.files += %w( src/core/lib/gprpp/thd.h ) s.files += %w( src/core/lib/profiling/timers.h ) s.files += %w( src/core/lib/gpr/alloc.cc ) diff --git a/include/grpcpp/channel.h b/include/grpcpp/channel.h index ee833960698..c4d5ab1177b 100644 --- a/include/grpcpp/channel.h +++ b/include/grpcpp/channel.h @@ -28,6 +28,7 @@ #include #include #include +#include struct grpc_channel; @@ -97,7 +98,7 @@ class Channel final : public ChannelInterface, grpc_channel* const c_channel_; // owned // mu_ protects callback_cq_ (the per-channel callbackable completion queue) - std::mutex mu_; + grpc::internal::Mutex mu_; // callback_cq_ references the callbackable completion queue associated // with this channel (if any). It is set on the first call to CallbackCQ(). diff --git a/include/grpcpp/impl/codegen/client_context.h b/include/grpcpp/impl/codegen/client_context.h index 5946488566e..85bbf36f06d 100644 --- a/include/grpcpp/impl/codegen/client_context.h +++ b/include/grpcpp/impl/codegen/client_context.h @@ -51,6 +51,7 @@ #include #include #include +#include #include struct census_context; @@ -457,7 +458,7 @@ class ClientContext { bool idempotent_; bool cacheable_; std::shared_ptr channel_; - std::mutex mu_; + grpc::internal::Mutex mu_; grpc_call* call_; bool call_canceled_; gpr_timespec deadline_; diff --git a/include/grpcpp/impl/codegen/sync.h b/include/grpcpp/impl/codegen/sync.h new file mode 100644 index 00000000000..2ed71eeb9f2 --- /dev/null +++ b/include/grpcpp/impl/codegen/sync.h @@ -0,0 +1,138 @@ +/* + * + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_IMPL_CODEGEN_SYNC_H +#define GRPCPP_IMPL_CODEGEN_SYNC_H + +#include +#include +#include + +#include + +// The core library is not accessible in C++ codegen headers, and vice versa. +// Thus, we need to have duplicate headers with similar functionality. +// Make sure any change to this file is also reflected in +// src/core/lib/gprpp/sync.h too. +// +// Whenever possible, prefer "src/core/lib/gprpp/sync.h" over this file, +// since in core we do not rely on g_core_codegen_interface and hence do not +// pay the costs of virtual function calls. + +namespace grpc { +namespace internal { + +class Mutex { + public: + Mutex() { g_core_codegen_interface->gpr_mu_init(&mu_); } + ~Mutex() { g_core_codegen_interface->gpr_mu_destroy(&mu_); } + + Mutex(const Mutex&) = delete; + Mutex& operator=(const Mutex&) = delete; + + gpr_mu* get() { return &mu_; } + const gpr_mu* get() const { return &mu_; } + + private: + gpr_mu mu_; +}; + +// MutexLock is a std:: +class MutexLock { + public: + explicit MutexLock(Mutex* mu) : mu_(mu->get()) { + g_core_codegen_interface->gpr_mu_lock(mu_); + } + explicit MutexLock(gpr_mu* mu) : mu_(mu) { + g_core_codegen_interface->gpr_mu_lock(mu_); + } + ~MutexLock() { g_core_codegen_interface->gpr_mu_unlock(mu_); } + + MutexLock(const MutexLock&) = delete; + MutexLock& operator=(const MutexLock&) = delete; + + private: + gpr_mu* const mu_; +}; + +class ReleasableMutexLock { + public: + explicit ReleasableMutexLock(Mutex* mu) : mu_(mu->get()) { + g_core_codegen_interface->gpr_mu_lock(mu_); + } + explicit ReleasableMutexLock(gpr_mu* mu) : mu_(mu) { + g_core_codegen_interface->gpr_mu_lock(mu_); + } + ~ReleasableMutexLock() { + if (!released_) g_core_codegen_interface->gpr_mu_unlock(mu_); + } + + ReleasableMutexLock(const ReleasableMutexLock&) = delete; + ReleasableMutexLock& operator=(const ReleasableMutexLock&) = delete; + + void Lock() { + GPR_DEBUG_ASSERT(released_); + g_core_codegen_interface->gpr_mu_lock(mu_); + released_ = false; + } + + void Unlock() { + GPR_DEBUG_ASSERT(!released_); + released_ = true; + g_core_codegen_interface->gpr_mu_unlock(mu_); + } + + private: + gpr_mu* const mu_; + bool released_ = false; +}; + +class CondVar { + public: + CondVar() { g_core_codegen_interface->gpr_cv_init(&cv_); } + ~CondVar() { g_core_codegen_interface->gpr_cv_destroy(&cv_); } + + CondVar(const CondVar&) = delete; + CondVar& operator=(const CondVar&) = delete; + + void Signal() { g_core_codegen_interface->gpr_cv_signal(&cv_); } + void Broadcast() { g_core_codegen_interface->gpr_cv_broadcast(&cv_); } + + int Wait(Mutex* mu) { + return Wait(mu, + g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME)); + } + int Wait(Mutex* mu, const gpr_timespec& deadline) { + return g_core_codegen_interface->gpr_cv_wait(&cv_, mu->get(), deadline); + } + + template + void WaitUntil(Mutex* mu, Predicate pred) { + while (!pred()) { + Wait(mu, g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME)); + } + } + + private: + gpr_cv cv_; +}; + +} // namespace internal +} // namespace grpc + +#endif // GRPCPP_IMPL_CODEGEN_SYNC_H diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index 2ae9d712012..8aff0663fe2 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -297,12 +297,12 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { experimental_registration_type experimental_registration_{this}; // Server status - std::mutex mu_; + grpc::internal::Mutex mu_; bool started_; bool shutdown_; bool shutdown_notified_; // Was notify called on the shutdown_cv_ - std::condition_variable shutdown_cv_; + grpc::internal::CondVar shutdown_cv_; // It is ok (but not required) to nest callback_reqs_mu_ under mu_ . // Incrementing callback_reqs_outstanding_ is ok without a lock but it must be @@ -311,8 +311,8 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { // during periods of increasing load; the decrement happens only when memory // is maxed out, during server shutdown, or (possibly in a future version) // during decreasing load, so it is less performance-critical. - std::mutex callback_reqs_mu_; - std::condition_variable callback_reqs_done_cv_; + grpc::internal::Mutex callback_reqs_mu_; + grpc::internal::CondVar callback_reqs_done_cv_; std::atomic_int callback_reqs_outstanding_{0}; std::shared_ptr global_callbacks_; diff --git a/include/grpcpp/server_impl.h b/include/grpcpp/server_impl.h index 771a3a10be9..14b16a06f4e 100644 --- a/include/grpcpp/server_impl.h +++ b/include/grpcpp/server_impl.h @@ -304,12 +304,12 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen { experimental_registration_type experimental_registration_{this}; // Server status - std::mutex mu_; + grpc::internal::Mutex mu_; bool started_; bool shutdown_; bool shutdown_notified_; // Was notify called on the shutdown_cv_ - std::condition_variable shutdown_cv_; + grpc::internal::CondVar shutdown_cv_; // It is ok (but not required) to nest callback_reqs_mu_ under mu_ . // Incrementing callback_reqs_outstanding_ is ok without a lock but it must be @@ -318,8 +318,8 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen { // during periods of increasing load; the decrement happens only when memory // is maxed out, during server shutdown, or (possibly in a future version) // during decreasing load, so it is less performance-critical. - std::mutex callback_reqs_mu_; - std::condition_variable callback_reqs_done_cv_; + grpc::internal::Mutex callback_reqs_mu_; + grpc::internal::CondVar callback_reqs_done_cv_; std::atomic_int callback_reqs_outstanding_{0}; std::shared_ptr global_callbacks_; diff --git a/package.xml b/package.xml index f3bbb449ac5..5be3d24365d 100644 --- a/package.xml +++ b/package.xml @@ -109,8 +109,8 @@ - + diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 86938a51d9b..cd552739732 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -51,7 +51,7 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/manual_constructor.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/polling_entity.h" diff --git a/src/core/ext/filters/client_channel/health/health_check_client.cc b/src/core/ext/filters/client_channel/health/health_check_client.cc index a22d6450cbd..a99f1e54062 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.cc +++ b/src/core/ext/filters/client_channel/health/health_check_client.cc @@ -27,7 +27,7 @@ #include "pb_encode.h" #include "src/core/ext/filters/client_channel/health/health.pb.h" #include "src/core/lib/debug/trace.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/transport/error_utils.h" #include "src/core/lib/transport/status_metadata.h" @@ -69,7 +69,6 @@ HealthCheckClient::HealthCheckClient( } GRPC_CLOSURE_INIT(&retry_timer_callback_, OnRetryTimer, this, grpc_schedule_on_exec_ctx); - gpr_mu_init(&mu_); StartCall(); } @@ -78,7 +77,6 @@ HealthCheckClient::~HealthCheckClient() { gpr_log(GPR_INFO, "destroying HealthCheckClient %p", this); } GRPC_ERROR_UNREF(error_); - gpr_mu_destroy(&mu_); } void HealthCheckClient::NotifyOnHealthChange(grpc_connectivity_state* state, diff --git a/src/core/ext/filters/client_channel/health/health_check_client.h b/src/core/ext/filters/client_channel/health/health_check_client.h index 1fa4487c403..6e0123e4925 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.h +++ b/src/core/ext/filters/client_channel/health/health_check_client.h @@ -31,6 +31,7 @@ #include "src/core/lib/gprpp/atomic.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/call_combiner.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/polling_entity.h" @@ -157,7 +158,7 @@ class HealthCheckClient : public InternallyRefCounted { grpc_pollset_set* interested_parties_; // Do not own. RefCountedPtr channelz_node_; - gpr_mu mu_; + Mutex mu_; grpc_connectivity_state state_ = GRPC_CHANNEL_CONNECTING; grpc_error* error_ = GRPC_ERROR_NONE; grpc_connectivity_state* notify_state_ = nullptr; diff --git a/src/core/ext/filters/client_channel/http_connect_handshaker.cc b/src/core/ext/filters/client_channel/http_connect_handshaker.cc index 2b1eb92bbd4..90a79843458 100644 --- a/src/core/ext/filters/client_channel/http_connect_handshaker.cc +++ b/src/core/ext/filters/client_channel/http_connect_handshaker.cc @@ -33,7 +33,7 @@ #include "src/core/lib/channel/handshaker_registry.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/http/format_request.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/slice/slice_internal.h" diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index aebd2fd3faa..ead15308f49 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -88,7 +88,6 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/gprpp/memory.h" -#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/combiner.h" diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc index 84b9c41a734..35123633feb 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc @@ -25,7 +25,7 @@ #include #include -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" namespace grpc_core { diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h index fdebdf55c17..bcc6598c105 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h @@ -26,6 +26,7 @@ #include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/gprpp/sync.h" namespace grpc_core { @@ -41,9 +42,6 @@ class GrpcLbClientStats : public RefCounted { typedef InlinedVector DroppedCallCounts; - GrpcLbClientStats() { gpr_mu_init(&drop_count_mu_); } - ~GrpcLbClientStats() { gpr_mu_destroy(&drop_count_mu_); } - void AddCallStarted(); void AddCallFinished(bool finished_with_client_failed_to_send, bool finished_known_received); @@ -66,7 +64,7 @@ class GrpcLbClientStats : public RefCounted { gpr_atm num_calls_finished_ = 0; gpr_atm num_calls_finished_with_client_failed_to_send_ = 0; gpr_atm num_calls_finished_known_received_ = 0; - gpr_mu drop_count_mu_; // Guards drop_token_counts_. + Mutex drop_count_mu_; // Guards drop_token_counts_. UniquePtr drop_token_counts_; }; diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index 332f66808e0..892472e1c9b 100644 --- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -27,7 +27,7 @@ #include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" @@ -154,13 +154,12 @@ class PickFirst : public LoadBalancingPolicy { /// Lock and data used to capture snapshots of this channels child /// channels and subchannels. This data is consumed by channelz. - gpr_mu child_refs_mu_; + Mutex child_refs_mu_; channelz::ChildRefsList child_subchannels_; channelz::ChildRefsList child_channels_; }; PickFirst::PickFirst(Args args) : LoadBalancingPolicy(std::move(args)) { - gpr_mu_init(&child_refs_mu_); if (grpc_lb_pick_first_trace.enabled()) { gpr_log(GPR_INFO, "Pick First %p created.", this); } @@ -170,7 +169,6 @@ PickFirst::~PickFirst() { if (grpc_lb_pick_first_trace.enabled()) { gpr_log(GPR_INFO, "Destroying Pick First %p", this); } - gpr_mu_destroy(&child_refs_mu_); GPR_ASSERT(subchannel_list_ == nullptr); GPR_ASSERT(latest_pending_subchannel_list_ == nullptr); } diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc index d3faaaddc98..29cfe972f78 100644 --- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc @@ -36,8 +36,8 @@ #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/debug/trace.h" -#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" @@ -193,7 +193,7 @@ class RoundRobin : public LoadBalancingPolicy { bool shutdown_ = false; /// Lock and data used to capture snapshots of this channel's child /// channels and subchannels. This data is consumed by channelz. - gpr_mu child_refs_mu_; + Mutex child_refs_mu_; channelz::ChildRefsList child_subchannels_; channelz::ChildRefsList child_channels_; }; @@ -245,7 +245,6 @@ RoundRobin::PickResult RoundRobin::Picker::Pick(PickArgs* pick, // RoundRobin::RoundRobin(Args args) : LoadBalancingPolicy(std::move(args)) { - gpr_mu_init(&child_refs_mu_); if (grpc_lb_round_robin_trace.enabled()) { gpr_log(GPR_INFO, "[RR %p] Created", this); } @@ -255,7 +254,6 @@ RoundRobin::~RoundRobin() { if (grpc_lb_round_robin_trace.enabled()) { gpr_log(GPR_INFO, "[RR %p] Destroying Round Robin policy", this); } - gpr_mu_destroy(&child_refs_mu_); GPR_ASSERT(subchannel_list_ == nullptr); GPR_ASSERT(latest_pending_subchannel_list_ == nullptr); } diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc b/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc index fe49e9aca03..443deb01274 100644 --- a/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +++ b/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc @@ -89,9 +89,9 @@ #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/gprpp/map.h" #include "src/core/lib/gprpp/memory.h" -#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" @@ -278,10 +278,8 @@ class XdsLb : public LoadBalancingPolicy { class LocalityEntry : public InternallyRefCounted { public: explicit LocalityEntry(RefCountedPtr parent) - : parent_(std::move(parent)) { - gpr_mu_init(&child_policy_mu_); - } - ~LocalityEntry() { gpr_mu_destroy(&child_policy_mu_); } + : parent_(std::move(parent)) {} + ~LocalityEntry() = default; void UpdateLocked(xds_grpclb_serverlist* serverlist, LoadBalancingPolicy::Config* child_policy_config, @@ -323,13 +321,10 @@ class XdsLb : public LoadBalancingPolicy { OrphanablePtr pending_child_policy_; // Lock held when modifying the value of child_policy_ or // pending_child_policy_. - gpr_mu child_policy_mu_; + Mutex child_policy_mu_; RefCountedPtr parent_; }; - LocalityMap() { gpr_mu_init(&child_refs_mu_); } - ~LocalityMap() { gpr_mu_destroy(&child_refs_mu_); } - void UpdateLocked(const LocalityList& locality_list, LoadBalancingPolicy::Config* child_policy_config, const grpc_channel_args* args, XdsLb* parent); @@ -343,7 +338,7 @@ class XdsLb : public LoadBalancingPolicy { Map, OrphanablePtr, StringLess> map_; // Lock held while filling child refs for all localities // inside the map - gpr_mu child_refs_mu_; + Mutex child_refs_mu_; }; struct LocalityServerlistEntry { @@ -397,7 +392,7 @@ class XdsLb : public LoadBalancingPolicy { // Mutex to protect the channel to the LB server. This is used when // processing a channelz request. // TODO(juanlishen): Replace this with atomic. - gpr_mu lb_chand_mu_; + Mutex lb_chand_mu_; // Timeout in milliseconds for the LB call. 0 means no deadline. int lb_call_timeout_ms_ = 0; @@ -1090,7 +1085,6 @@ XdsLb::XdsLb(Args args) : LoadBalancingPolicy(std::move(args)), locality_map_(), locality_serverlist_() { - gpr_mu_init(&lb_chand_mu_); // Record server name. const grpc_arg* arg = grpc_channel_args_find(args.args, GRPC_ARG_SERVER_URI); const char* server_uri = grpc_channel_arg_get_string(arg); @@ -1114,7 +1108,6 @@ XdsLb::XdsLb(Args args) } XdsLb::~XdsLb() { - gpr_mu_destroy(&lb_chand_mu_); gpr_free((void*)server_name_); grpc_channel_args_destroy(args_); locality_serverlist_.clear(); diff --git a/src/core/ext/filters/client_channel/resolving_lb_policy.cc b/src/core/ext/filters/client_channel/resolving_lb_policy.cc index d15af908b3f..a2367e09d9b 100644 --- a/src/core/ext/filters/client_channel/resolving_lb_policy.cc +++ b/src/core/ext/filters/client_channel/resolving_lb_policy.cc @@ -48,7 +48,7 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/manual_constructor.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/polling_entity.h" diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 20a6023f71c..b38bd4b701e 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -42,8 +42,8 @@ #include "src/core/lib/gpr/alloc.h" #include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/gprpp/manual_constructor.h" -#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" @@ -457,13 +457,14 @@ struct Subchannel::ExternalStateWatcher { grpc_pollset_set_del_pollset_set(w->subchannel->pollset_set_, w->pollset_set); } - gpr_mu_lock(&w->subchannel->mu_); - if (w->subchannel->external_state_watcher_list_ == w) { - w->subchannel->external_state_watcher_list_ = w->next; + { + MutexLock lock(&w->subchannel->mu_); + if (w->subchannel->external_state_watcher_list_ == w) { + w->subchannel->external_state_watcher_list_ = w->next; + } + if (w->next != nullptr) w->next->prev = w->prev; + if (w->prev != nullptr) w->prev->next = w->next; } - if (w->next != nullptr) w->next->prev = w->prev; - if (w->prev != nullptr) w->prev->next = w->next; - gpr_mu_unlock(&w->subchannel->mu_); GRPC_SUBCHANNEL_WEAK_UNREF(w->subchannel, "external_state_watcher+done"); Delete(w); GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error)); @@ -585,7 +586,6 @@ Subchannel::Subchannel(SubchannelKey* key, grpc_connector* connector, "subchannel"); grpc_connectivity_state_init(&state_and_health_tracker_, GRPC_CHANNEL_IDLE, "subchannel"); - gpr_mu_init(&mu_); // Check whether we should enable health checking. const char* service_config_json = grpc_channel_arg_get_string( grpc_channel_args_find(args_, GRPC_ARG_SERVICE_CONFIG)); @@ -632,7 +632,6 @@ Subchannel::~Subchannel() { grpc_connector_unref(connector_); grpc_pollset_set_destroy(pollset_set_); Delete(key_); - gpr_mu_destroy(&mu_); } Subchannel* Subchannel::Create(grpc_connector* connector, @@ -908,7 +907,9 @@ void Subchannel::MaybeStartConnectingLocked() { void Subchannel::OnRetryAlarm(void* arg, grpc_error* error) { Subchannel* c = static_cast(arg); - gpr_mu_lock(&c->mu_); + // TODO(soheilhy): Once subchannel refcounting is simplified, we can get use + // MutexLock instead of ReleasableMutexLock, here. + ReleasableMutexLock lock(&c->mu_); c->have_retry_alarm_ = false; if (c->disconnected_) { error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected", @@ -922,9 +923,9 @@ void Subchannel::OnRetryAlarm(void* arg, grpc_error* error) { if (error == GRPC_ERROR_NONE) { gpr_log(GPR_INFO, "Failed to connect to channel, retrying"); c->ContinueConnectingLocked(); - gpr_mu_unlock(&c->mu_); + lock.Unlock(); } else { - gpr_mu_unlock(&c->mu_); + lock.Unlock(); GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); } GRPC_ERROR_UNREF(error); @@ -951,29 +952,30 @@ void Subchannel::OnConnectingFinished(void* arg, grpc_error* error) { auto* c = static_cast(arg); grpc_channel_args* delete_channel_args = c->connecting_result_.channel_args; GRPC_SUBCHANNEL_WEAK_REF(c, "on_connecting_finished"); - gpr_mu_lock(&c->mu_); - c->connecting_ = false; - if (c->connecting_result_.transport != nullptr && - c->PublishTransportLocked()) { - // Do nothing, transport was published. - } else if (c->disconnected_) { - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); - } else { - const char* errmsg = grpc_error_string(error); - gpr_log(GPR_INFO, "Connect failed: %s", errmsg); - error = - grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Connect Failed", &error, 1), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); - c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, - GRPC_ERROR_REF(error), "connect_failed"); - grpc_connectivity_state_set(&c->state_and_health_tracker_, - GRPC_CHANNEL_TRANSIENT_FAILURE, error, - "connect_failed"); - c->MaybeStartConnectingLocked(); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + { + MutexLock lock(&c->mu_); + c->connecting_ = false; + if (c->connecting_result_.transport != nullptr && + c->PublishTransportLocked()) { + // Do nothing, transport was published. + } else if (c->disconnected_) { + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + } else { + const char* errmsg = grpc_error_string(error); + gpr_log(GPR_INFO, "Connect failed: %s", errmsg); + error = grpc_error_set_int( + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Connect Failed", + &error, 1), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); + c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, + GRPC_ERROR_REF(error), "connect_failed"); + grpc_connectivity_state_set(&c->state_and_health_tracker_, + GRPC_CHANNEL_TRANSIENT_FAILURE, error, + "connect_failed"); + c->MaybeStartConnectingLocked(); + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + } } - gpr_mu_unlock(&c->mu_); GRPC_SUBCHANNEL_WEAK_UNREF(c, "on_connecting_finished"); grpc_channel_args_destroy(delete_channel_args); } diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 968fc74e22a..83b57dd7ff3 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -29,6 +29,7 @@ #include "src/core/lib/gpr/arena.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/transport/connectivity_state.h" @@ -264,7 +265,7 @@ class Subchannel { // pollset_set tracking who's interested in a connection being setup. grpc_pollset_set* pollset_set_; // Protects the other members. - gpr_mu mu_; + Mutex mu_; // Refcount // - lower INTERNAL_REF_BITS bits are for internal references: // these do not keep the subchannel open. diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index 9f0169aeaab..b6a660b18fd 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -23,7 +23,7 @@ #include "src/core/lib/channel/channelz_registry.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/memory.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include #include diff --git a/src/core/lib/channel/handshaker.h b/src/core/lib/channel/handshaker.h index 912d524c8db..b68799b6e0e 100644 --- a/src/core/lib/channel/handshaker.h +++ b/src/core/lib/channel/handshaker.h @@ -27,8 +27,8 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/inlined_vector.h" -#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/exec_ctx.h" diff --git a/src/core/lib/gprpp/mutex_lock.h b/src/core/lib/gprpp/mutex_lock.h deleted file mode 100644 index 54751d5fe46..00000000000 --- a/src/core/lib/gprpp/mutex_lock.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef GRPC_CORE_LIB_GPRPP_MUTEX_LOCK_H -#define GRPC_CORE_LIB_GPRPP_MUTEX_LOCK_H - -#include - -#include - -namespace grpc_core { - -class MutexLock { - public: - explicit MutexLock(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu); } - ~MutexLock() { gpr_mu_unlock(mu_); } - - MutexLock(const MutexLock&) = delete; - MutexLock& operator=(const MutexLock&) = delete; - - private: - gpr_mu* const mu_; -}; - -} // namespace grpc_core - -#endif /* GRPC_CORE_LIB_GPRPP_MUTEX_LOCK_H */ diff --git a/src/core/lib/gprpp/sync.h b/src/core/lib/gprpp/sync.h new file mode 100644 index 00000000000..895ca60fec0 --- /dev/null +++ b/src/core/lib/gprpp/sync.h @@ -0,0 +1,126 @@ +/* + * + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_GPRPP_SYNC_H +#define GRPC_CORE_LIB_GPRPP_SYNC_H + +#include + +#include +#include +#include +#include + +// The core library is not accessible in C++ codegen headers, and vice versa. +// Thus, we need to have duplicate headers with similar functionality. +// Make sure any change to this file is also reflected in +// include/grpcpp/impl/codegen/sync.h. +// +// Whenever possible, prefer using this file over +// since this file doesn't rely on g_core_codegen_interface and hence does not +// pay the costs of virtual function calls. + +namespace grpc_core { + +class Mutex { + public: + Mutex() { gpr_mu_init(&mu_); } + ~Mutex() { gpr_mu_destroy(&mu_); } + + Mutex(const Mutex&) = delete; + Mutex& operator=(const Mutex&) = delete; + + gpr_mu* get() { return &mu_; } + const gpr_mu* get() const { return &mu_; } + + private: + gpr_mu mu_; +}; + +// MutexLock is a std:: +class MutexLock { + public: + explicit MutexLock(Mutex* mu) : mu_(mu->get()) { gpr_mu_lock(mu_); } + explicit MutexLock(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu_); } + ~MutexLock() { gpr_mu_unlock(mu_); } + + MutexLock(const MutexLock&) = delete; + MutexLock& operator=(const MutexLock&) = delete; + + private: + gpr_mu* const mu_; +}; + +class ReleasableMutexLock { + public: + explicit ReleasableMutexLock(Mutex* mu) : mu_(mu->get()) { gpr_mu_lock(mu_); } + explicit ReleasableMutexLock(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu_); } + ~ReleasableMutexLock() { + if (!released_) gpr_mu_unlock(mu_); + } + + ReleasableMutexLock(const ReleasableMutexLock&) = delete; + ReleasableMutexLock& operator=(const ReleasableMutexLock&) = delete; + + void Lock() { + GPR_DEBUG_ASSERT(released_); + gpr_mu_lock(mu_); + released_ = false; + } + + void Unlock() { + GPR_DEBUG_ASSERT(!released_); + released_ = true; + gpr_mu_unlock(mu_); + } + + private: + gpr_mu* const mu_; + bool released_ = false; +}; + +class CondVar { + public: + CondVar() { gpr_cv_init(&cv_); } + ~CondVar() { gpr_cv_destroy(&cv_); } + + CondVar(const CondVar&) = delete; + CondVar& operator=(const CondVar&) = delete; + + void Signal() { gpr_cv_signal(&cv_); } + void Broadcast() { gpr_cv_broadcast(&cv_); } + + int Wait(Mutex* mu) { return Wait(mu, gpr_inf_future(GPR_CLOCK_REALTIME)); } + int Wait(Mutex* mu, const gpr_timespec& deadline) { + return gpr_cv_wait(&cv_, mu->get(), deadline); + } + + template + void WaitUntil(Mutex* mu, Predicate pred) { + while (!pred()) { + Wait(mu, gpr_inf_future(GPR_CLOCK_REALTIME)); + } + } + + private: + gpr_cv cv_; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_GPRPP_SYNC_H */ diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc index 01be46c9f68..c387f8359a0 100644 --- a/src/core/lib/iomgr/ev_epollex_linux.cc +++ b/src/core/lib/iomgr/ev_epollex_linux.cc @@ -47,7 +47,7 @@ #include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/manual_constructor.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/block_annotate.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/is_epollexclusive_available.h" diff --git a/src/core/lib/surface/init.cc b/src/core/lib/surface/init.cc index b67d4f12252..57d975564b1 100644 --- a/src/core/lib/surface/init.cc +++ b/src/core/lib/surface/init.cc @@ -33,7 +33,7 @@ #include "src/core/lib/debug/stats.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/gprpp/fork.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/call_combiner.h" #include "src/core/lib/iomgr/combiner.h" diff --git a/src/core/tsi/ssl/session_cache/ssl_session_cache.cc b/src/core/tsi/ssl/session_cache/ssl_session_cache.cc index f9184bcc34f..ba0745a2359 100644 --- a/src/core/tsi/ssl/session_cache/ssl_session_cache.cc +++ b/src/core/tsi/ssl/session_cache/ssl_session_cache.cc @@ -18,7 +18,7 @@ #include -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/tsi/ssl/session_cache/ssl_session.h" #include "src/core/tsi/ssl/session_cache/ssl_session_cache.h" diff --git a/src/cpp/client/channel_cc.cc b/src/cpp/client/channel_cc.cc index db59d4d8416..2d5e74163a9 100644 --- a/src/cpp/client/channel_cc.cc +++ b/src/cpp/client/channel_cc.cc @@ -232,7 +232,7 @@ class ShutdownCallback : public grpc_experimental_completion_queue_functor { CompletionQueue* Channel::CallbackCQ() { // TODO(vjpai): Consider using a single global CQ for the default CQ // if there is no explicit per-channel CQ registered - std::lock_guard l(mu_); + grpc::internal::MutexLock l(&mu_); if (callback_cq_ == nullptr) { auto* shutdown_callback = new ShutdownCallback; callback_cq_ = new CompletionQueue(grpc_completion_queue_attributes{ diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc index efb59c71a8c..b4fce79b99a 100644 --- a/src/cpp/client/client_context.cc +++ b/src/cpp/client/client_context.cc @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -84,7 +85,7 @@ void ClientContext::AddMetadata(const grpc::string& meta_key, void ClientContext::set_call(grpc_call* call, const std::shared_ptr& channel) { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); GPR_ASSERT(call_ == nullptr); call_ = call; channel_ = channel; @@ -114,7 +115,7 @@ void ClientContext::set_compression_algorithm( } void ClientContext::TryCancel() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); if (call_) { SendCancelToInterceptors(); grpc_call_cancel(call_, nullptr); diff --git a/src/cpp/server/dynamic_thread_pool.cc b/src/cpp/server/dynamic_thread_pool.cc index ef99d6459f7..c8bdbdea7e6 100644 --- a/src/cpp/server/dynamic_thread_pool.cc +++ b/src/cpp/server/dynamic_thread_pool.cc @@ -21,6 +21,7 @@ #include #include +#include #include "src/core/lib/gprpp/thd.h" @@ -40,27 +41,27 @@ DynamicThreadPool::DynamicThread::~DynamicThread() { thd_.Join(); } void DynamicThreadPool::DynamicThread::ThreadFunc() { pool_->ThreadFunc(); // Now that we have killed ourselves, we should reduce the thread count - std::unique_lock lock(pool_->mu_); + grpc_core::MutexLock lock(&pool_->mu_); pool_->nthreads_--; // Move ourselves to dead list pool_->dead_threads_.push_back(this); if ((pool_->shutdown_) && (pool_->nthreads_ == 0)) { - pool_->shutdown_cv_.notify_one(); + pool_->shutdown_cv_.Signal(); } } void DynamicThreadPool::ThreadFunc() { for (;;) { // Wait until work is available or we are shutting down. - std::unique_lock lock(mu_); + grpc_core::ReleasableMutexLock lock(&mu_); if (!shutdown_ && callbacks_.empty()) { // If there are too many threads waiting, then quit this thread if (threads_waiting_ >= reserve_threads_) { break; } threads_waiting_++; - cv_.wait(lock); + cv_.Wait(&mu_); threads_waiting_--; } // Drain callbacks before considering shutdown to ensure all work @@ -68,7 +69,7 @@ void DynamicThreadPool::ThreadFunc() { if (!callbacks_.empty()) { auto cb = callbacks_.front(); callbacks_.pop(); - lock.unlock(); + lock.Unlock(); cb(); } else if (shutdown_) { break; @@ -82,7 +83,7 @@ DynamicThreadPool::DynamicThreadPool(int reserve_threads) nthreads_(0), threads_waiting_(0) { for (int i = 0; i < reserve_threads_; i++) { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); nthreads_++; new DynamicThread(this); } @@ -95,17 +96,17 @@ void DynamicThreadPool::ReapThreads(std::list* tlist) { } DynamicThreadPool::~DynamicThreadPool() { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); shutdown_ = true; - cv_.notify_all(); + cv_.Broadcast(); while (nthreads_ != 0) { - shutdown_cv_.wait(lock); + shutdown_cv_.Wait(&mu_); } ReapThreads(&dead_threads_); } void DynamicThreadPool::Add(const std::function& callback) { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); // Add works to the callbacks list callbacks_.push(callback); // Increase pool size or notify as needed @@ -114,7 +115,7 @@ void DynamicThreadPool::Add(const std::function& callback) { nthreads_++; new DynamicThread(this); } else { - cv_.notify_one(); + cv_.Signal(); } // Also use this chance to harvest dead threads if (!dead_threads_.empty()) { diff --git a/src/cpp/server/dynamic_thread_pool.h b/src/cpp/server/dynamic_thread_pool.h index 5df8cf2b043..4ae0257d40b 100644 --- a/src/cpp/server/dynamic_thread_pool.h +++ b/src/cpp/server/dynamic_thread_pool.h @@ -27,6 +27,7 @@ #include +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/thd.h" #include "src/cpp/server/thread_pool_interface.h" @@ -50,9 +51,9 @@ class DynamicThreadPool final : public ThreadPoolInterface { grpc_core::Thread thd_; void ThreadFunc(); }; - std::mutex mu_; - std::condition_variable cv_; - std::condition_variable shutdown_cv_; + grpc_core::Mutex mu_; + grpc_core::CondVar cv_; + grpc_core::CondVar shutdown_cv_; bool shutdown_; std::queue> callbacks_; int reserve_threads_; diff --git a/src/cpp/server/health/default_health_check_service.cc b/src/cpp/server/health/default_health_check_service.cc index 44aebd2f9d9..01bc51aa213 100644 --- a/src/cpp/server/health/default_health_check_service.cc +++ b/src/cpp/server/health/default_health_check_service.cc @@ -41,7 +41,7 @@ DefaultHealthCheckService::DefaultHealthCheckService() { void DefaultHealthCheckService::SetServingStatus( const grpc::string& service_name, bool serving) { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); if (shutdown_) { // Set to NOT_SERVING in case service_name is not in the map. serving = false; @@ -51,7 +51,7 @@ void DefaultHealthCheckService::SetServingStatus( void DefaultHealthCheckService::SetServingStatus(bool serving) { const ServingStatus status = serving ? SERVING : NOT_SERVING; - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); if (shutdown_) { return; } @@ -62,7 +62,7 @@ void DefaultHealthCheckService::SetServingStatus(bool serving) { } void DefaultHealthCheckService::Shutdown() { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); if (shutdown_) { return; } @@ -76,7 +76,7 @@ void DefaultHealthCheckService::Shutdown() { DefaultHealthCheckService::ServingStatus DefaultHealthCheckService::GetServingStatus( const grpc::string& service_name) const { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); auto it = services_map_.find(service_name); if (it == services_map_.end()) { return NOT_FOUND; @@ -88,7 +88,7 @@ DefaultHealthCheckService::GetServingStatus( void DefaultHealthCheckService::RegisterCallHandler( const grpc::string& service_name, std::shared_ptr handler) { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); ServiceData& service_data = services_map_[service_name]; service_data.AddCallHandler(handler /* copies ref */); HealthCheckServiceImpl::CallHandler* h = handler.get(); @@ -98,7 +98,7 @@ void DefaultHealthCheckService::RegisterCallHandler( void DefaultHealthCheckService::UnregisterCallHandler( const grpc::string& service_name, const std::shared_ptr& handler) { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); auto it = services_map_.find(service_name); if (it == services_map_.end()) return; ServiceData& service_data = it->second; @@ -166,7 +166,7 @@ DefaultHealthCheckService::HealthCheckServiceImpl::~HealthCheckServiceImpl() { // We will reach here after the server starts shutting down. shutdown_ = true; { - std::unique_lock lock(cq_shutdown_mu_); + grpc_core::MutexLock lock(&cq_shutdown_mu_); cq_->Shutdown(); } thread_->Join(); @@ -266,7 +266,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::CheckCallHandler:: std::make_shared(cq, database, service); CheckCallHandler* handler = static_cast(self.get()); { - std::unique_lock lock(service->cq_shutdown_mu_); + grpc_core::MutexLock lock(&service->cq_shutdown_mu_); if (service->shutdown_) return; // Request a Check() call. handler->next_ = @@ -311,7 +311,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::CheckCallHandler:: } // Send response. { - std::unique_lock lock(service_->cq_shutdown_mu_); + grpc_core::MutexLock lock(&service_->cq_shutdown_mu_); if (!service_->shutdown_) { next_ = CallableTag(std::bind(&CheckCallHandler::OnFinishDone, this, @@ -347,7 +347,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: std::make_shared(cq, database, service); WatchCallHandler* handler = static_cast(self.get()); { - std::unique_lock lock(service->cq_shutdown_mu_); + grpc_core::MutexLock lock(&service->cq_shutdown_mu_); if (service->shutdown_) return; // Request AsyncNotifyWhenDone(). handler->on_done_notified_ = @@ -402,7 +402,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: SendHealth(std::shared_ptr self, ServingStatus status) { - std::unique_lock lock(send_mu_); + grpc_core::MutexLock lock(&send_mu_); // If there's already a send in flight, cache the new status, and // we'll start a new send for it when the one in flight completes. if (send_in_flight_) { @@ -420,7 +420,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: ByteBuffer response; bool success = service_->EncodeResponse(status, &response); // Grab shutdown lock and send response. - std::unique_lock cq_lock(service_->cq_shutdown_mu_); + grpc_core::MutexLock cq_lock(&service_->cq_shutdown_mu_); if (service_->shutdown_) { SendFinishLocked(std::move(self), Status::CANCELLED); return; @@ -442,7 +442,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: SendFinish(std::move(self), Status::CANCELLED); return; } - std::unique_lock lock(send_mu_); + grpc_core::MutexLock lock(&send_mu_); send_in_flight_ = false; // If we got a new status since we started the last send, start a // new send for it. @@ -456,7 +456,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: SendFinish(std::shared_ptr self, const Status& status) { if (finish_called_) return; - std::unique_lock cq_lock(service_->cq_shutdown_mu_); + grpc_core::MutexLock cq_lock(&service_->cq_shutdown_mu_); if (service_->shutdown_) return; SendFinishLocked(std::move(self), status); } diff --git a/src/cpp/server/health/default_health_check_service.h b/src/cpp/server/health/default_health_check_service.h index 9551cd2e2cf..4b926efdfe8 100644 --- a/src/cpp/server/health/default_health_check_service.h +++ b/src/cpp/server/health/default_health_check_service.h @@ -31,6 +31,7 @@ #include #include +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/thd.h" namespace grpc { @@ -197,7 +198,7 @@ class DefaultHealthCheckService final : public HealthCheckServiceInterface { GenericServerAsyncWriter stream_; ServerContext ctx_; - std::mutex send_mu_; + grpc_core::Mutex send_mu_; bool send_in_flight_ = false; // Guarded by mu_. ServingStatus pending_status_ = NOT_FOUND; // Guarded by mu_. @@ -226,7 +227,7 @@ class DefaultHealthCheckService final : public HealthCheckServiceInterface { // To synchronize the operations related to shutdown state of cq_, so that // we don't enqueue new tags into cq_ after it is already shut down. - std::mutex cq_shutdown_mu_; + grpc_core::Mutex cq_shutdown_mu_; std::atomic_bool shutdown_{false}; std::unique_ptr<::grpc_core::Thread> thread_; }; @@ -273,7 +274,7 @@ class DefaultHealthCheckService final : public HealthCheckServiceInterface { const grpc::string& service_name, const std::shared_ptr& handler); - mutable std::mutex mu_; + mutable grpc_core::Mutex mu_; bool shutdown_ = false; // Guarded by mu_. std::map services_map_; // Guarded by mu_. std::unique_ptr impl_; diff --git a/src/cpp/server/load_reporter/load_reporter.cc b/src/cpp/server/load_reporter/load_reporter.cc index 464063a13ff..422ea62efd5 100644 --- a/src/cpp/server/load_reporter/load_reporter.cc +++ b/src/cpp/server/load_reporter/load_reporter.cc @@ -239,7 +239,7 @@ grpc::string LoadReporter::GenerateLbId() { ::grpc::lb::v1::LoadBalancingFeedback LoadReporter::GenerateLoadBalancingFeedback() { - std::unique_lock lock(feedback_mu_); + grpc_core::ReleasableMutexLock lock(&feedback_mu_); auto now = std::chrono::system_clock::now(); // Discard records outside the window until there is only one record // outside the window, which is used as the base for difference. @@ -277,7 +277,7 @@ LoadReporter::GenerateLoadBalancingFeedback() { double cpu_limit = newest->cpu_limit - oldest->cpu_limit; std::chrono::duration duration_seconds = newest->end_time - oldest->end_time; - lock.unlock(); + lock.Unlock(); ::grpc::lb::v1::LoadBalancingFeedback feedback; feedback.set_server_utilization(static_cast(cpu_usage / cpu_limit)); feedback.set_calls_per_second( @@ -290,7 +290,7 @@ LoadReporter::GenerateLoadBalancingFeedback() { ::google::protobuf::RepeatedPtrField<::grpc::lb::v1::Load> LoadReporter::GenerateLoads(const grpc::string& hostname, const grpc::string& lb_id) { - std::lock_guard lock(store_mu_); + grpc_core::MutexLock lock(&store_mu_); auto assigned_stores = load_data_store_.GetAssignedStores(hostname, lb_id); GPR_ASSERT(assigned_stores != nullptr); GPR_ASSERT(!assigned_stores->empty()); @@ -371,7 +371,7 @@ void LoadReporter::AppendNewFeedbackRecord(uint64_t rpcs, uint64_t errors) { // This will make the load balancing feedback generation a no-op. cpu_stats = {0, 0}; } - std::unique_lock lock(feedback_mu_); + grpc_core::MutexLock lock(&feedback_mu_); feedback_records_.emplace_back(std::chrono::system_clock::now(), rpcs, errors, cpu_stats.first, cpu_stats.second); } @@ -379,7 +379,7 @@ void LoadReporter::AppendNewFeedbackRecord(uint64_t rpcs, uint64_t errors) { void LoadReporter::ReportStreamCreated(const grpc::string& hostname, const grpc::string& lb_id, const grpc::string& load_key) { - std::lock_guard lock(store_mu_); + grpc_core::MutexLock lock(&store_mu_); load_data_store_.ReportStreamCreated(hostname, lb_id, load_key); gpr_log(GPR_INFO, "[LR %p] Report stream created (host: %s, LB ID: %s, load key: %s).", @@ -388,7 +388,7 @@ void LoadReporter::ReportStreamCreated(const grpc::string& hostname, void LoadReporter::ReportStreamClosed(const grpc::string& hostname, const grpc::string& lb_id) { - std::lock_guard lock(store_mu_); + grpc_core::MutexLock lock(&store_mu_); load_data_store_.ReportStreamClosed(hostname, lb_id); gpr_log(GPR_INFO, "[LR %p] Report stream closed (host: %s, LB ID: %s).", this, hostname.c_str(), lb_id.c_str()); @@ -407,7 +407,7 @@ void LoadReporter::ProcessViewDataCallStart( LoadRecordKey key(client_ip_and_token, user_id); LoadRecordValue value = LoadRecordValue(start_count); { - std::unique_lock lock(store_mu_); + grpc_core::MutexLock lock(&store_mu_); load_data_store_.MergeRow(host, key, value); } } @@ -459,7 +459,7 @@ void LoadReporter::ProcessViewDataCallEnd( LoadRecordValue value = LoadRecordValue( 0, ok_count, error_count, bytes_sent, bytes_received, latency_ms); { - std::unique_lock lock(store_mu_); + grpc_core::MutexLock lock(&store_mu_); load_data_store_.MergeRow(host, key, value); } } @@ -486,7 +486,7 @@ void LoadReporter::ProcessViewDataOtherCallMetrics( LoadRecordValue value = LoadRecordValue( metric_name, static_cast(num_calls), total_metric_value); { - std::unique_lock lock(store_mu_); + grpc_core::MutexLock lock(&store_mu_); load_data_store_.MergeRow(host, key, value); } } diff --git a/src/cpp/server/load_reporter/load_reporter.h b/src/cpp/server/load_reporter/load_reporter.h index b2254d56016..766e02a407a 100644 --- a/src/cpp/server/load_reporter/load_reporter.h +++ b/src/cpp/server/load_reporter/load_reporter.h @@ -29,6 +29,7 @@ #include #include +#include "src/core/lib/gprpp/sync.h" #include "src/cpp/server/load_reporter/load_data_store.h" #include "src/proto/grpc/lb/v1/load_reporter.grpc.pb.h" @@ -212,11 +213,11 @@ class LoadReporter { std::atomic next_lb_id_{0}; const std::chrono::seconds feedback_sample_window_seconds_; - std::mutex feedback_mu_; + grpc_core::Mutex feedback_mu_; std::deque feedback_records_; // TODO(juanlishen): Lock in finer grain. Locking the whole store may be // too expensive. - std::mutex store_mu_; + grpc_core::Mutex store_mu_; LoadDataStore load_data_store_; std::unique_ptr census_view_provider_; std::unique_ptr cpu_stats_provider_; diff --git a/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc b/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc index 859ad9946c8..9eaab5d6366 100644 --- a/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc +++ b/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc @@ -48,7 +48,7 @@ LoadReporterAsyncServiceImpl::~LoadReporterAsyncServiceImpl() { // We will reach here after the server starts shutting down. shutdown_ = true; { - std::unique_lock lock(cq_shutdown_mu_); + grpc_core::MutexLock lock(&cq_shutdown_mu_); cq_->Shutdown(); } if (next_fetch_and_sample_alarm_ != nullptr) @@ -62,7 +62,7 @@ void LoadReporterAsyncServiceImpl::ScheduleNextFetchAndSample() { gpr_time_from_millis(kFetchAndSampleIntervalSeconds * 1000, GPR_TIMESPAN)); { - std::unique_lock lock(cq_shutdown_mu_); + grpc_core::MutexLock lock(&cq_shutdown_mu_); if (shutdown_) return; // TODO(juanlishen): Improve the Alarm implementation to reuse a single // instance for multiple events. @@ -119,7 +119,7 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::CreateAndStart( std::make_shared(cq, service, load_reporter); ReportLoadHandler* p = handler.get(); { - std::unique_lock lock(service->cq_shutdown_mu_); + grpc_core::MutexLock lock(&service->cq_shutdown_mu_); if (service->shutdown_) return; p->on_done_notified_ = CallableTag(std::bind(&ReportLoadHandler::OnDoneNotified, p, @@ -164,9 +164,9 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::OnRequestDelivered( // instance will deallocate itself when it's done. CreateAndStart(cq_, service_, load_reporter_); { - std::unique_lock lock(service_->cq_shutdown_mu_); + grpc_core::ReleasableMutexLock lock(&service_->cq_shutdown_mu_); if (service_->shutdown_) { - lock.release()->unlock(); + lock.Unlock(); Shutdown(std::move(self), "OnRequestDelivered"); return; } @@ -222,9 +222,9 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::OnReadDone( SendReport(self, true /* ok */); // Expect this read to fail. { - std::unique_lock lock(service_->cq_shutdown_mu_); + grpc_core::ReleasableMutexLock lock(&service_->cq_shutdown_mu_); if (service_->shutdown_) { - lock.release()->unlock(); + lock.Unlock(); Shutdown(std::move(self), "OnReadDone"); return; } @@ -254,9 +254,9 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::ScheduleNextReport( gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_millis(load_report_interval_ms_, GPR_TIMESPAN)); { - std::unique_lock lock(service_->cq_shutdown_mu_); + grpc_core::ReleasableMutexLock lock(&service_->cq_shutdown_mu_); if (service_->shutdown_) { - lock.release()->unlock(); + lock.Unlock(); Shutdown(std::move(self), "ScheduleNextReport"); return; } @@ -294,9 +294,9 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::SendReport( call_status_ = INITIAL_RESPONSE_SENT; } { - std::unique_lock lock(service_->cq_shutdown_mu_); + grpc_core::ReleasableMutexLock lock(&service_->cq_shutdown_mu_); if (service_->shutdown_) { - lock.release()->unlock(); + lock.Unlock(); Shutdown(std::move(self), "SendReport"); return; } @@ -342,7 +342,7 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::Shutdown( // OnRequestDelivered() may be called after OnDoneNotified(), so we need to // try to Finish() every time we are in Shutdown(). if (call_status_ >= DELIVERED && call_status_ < FINISH_CALLED) { - std::unique_lock lock(service_->cq_shutdown_mu_); + grpc_core::MutexLock lock(&service_->cq_shutdown_mu_); if (!service_->shutdown_) { on_finish_done_ = CallableTag(std::bind(&ReportLoadHandler::OnFinishDone, this, diff --git a/src/cpp/server/load_reporter/load_reporter_async_service_impl.h b/src/cpp/server/load_reporter/load_reporter_async_service_impl.h index 6fc577ff493..3087cbfc04d 100644 --- a/src/cpp/server/load_reporter/load_reporter_async_service_impl.h +++ b/src/cpp/server/load_reporter/load_reporter_async_service_impl.h @@ -25,6 +25,7 @@ #include #include +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/thd.h" #include "src/cpp/server/load_reporter/load_reporter.h" @@ -181,7 +182,7 @@ class LoadReporterAsyncServiceImpl std::unique_ptr cq_; // To synchronize the operations related to shutdown state of cq_, so that we // don't enqueue new tags into cq_ after it is already shut down. - std::mutex cq_shutdown_mu_; + grpc_core::Mutex cq_shutdown_mu_; std::atomic_bool shutdown_{false}; std::unique_ptr<::grpc_core::Thread> thread_; std::unique_ptr load_reporter_; diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index aa9fdac9bea..64a6de97d7e 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -388,9 +388,9 @@ class Server::CallbackRequest final : public Server::CallbackRequestBase { // The counter of outstanding requests must be decremented // under a lock in case it causes the server shutdown. - std::lock_guard l(server_->callback_reqs_mu_); + grpc::internal::MutexLock l(&server_->callback_reqs_mu_); if (--server_->callback_reqs_outstanding_ == 0) { - server_->callback_reqs_done_cv_.notify_one(); + server_->callback_reqs_done_cv_.Signal(); } } @@ -814,12 +814,12 @@ Server::Server( Server::~Server() { { - std::unique_lock lock(mu_); + grpc::internal::ReleasableMutexLock lock(&mu_); if (callback_cq_ != nullptr) { callback_cq_->Shutdown(); } if (started_ && !shutdown_) { - lock.unlock(); + lock.Unlock(); Shutdown(); } else if (!started_) { // Shutdown the completion queues @@ -1051,7 +1051,7 @@ void Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) { } void Server::ShutdownInternal(gpr_timespec deadline) { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); if (shutdown_) { return; } @@ -1102,9 +1102,9 @@ void Server::ShutdownInternal(gpr_timespec deadline) { // will report a failure, indicating a shutdown and again we won't end // up incrementing the counter. { - std::unique_lock cblock(callback_reqs_mu_); - callback_reqs_done_cv_.wait( - cblock, [this] { return callback_reqs_outstanding_ == 0; }); + grpc::internal::MutexLock cblock(&callback_reqs_mu_); + callback_reqs_done_cv_.WaitUntil( + &callback_reqs_mu_, [this] { return callback_reqs_outstanding_ == 0; }); } // Drain the shutdown queue (if the previous call to AsyncNext() timed out @@ -1114,13 +1114,13 @@ void Server::ShutdownInternal(gpr_timespec deadline) { } shutdown_notified_ = true; - shutdown_cv_.notify_all(); + shutdown_cv_.Broadcast(); } void Server::Wait() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); while (started_ && !shutdown_notified_) { - shutdown_cv_.wait(lock); + shutdown_cv_.Wait(&mu_); } } @@ -1322,7 +1322,7 @@ class ShutdownCallback : public grpc_experimental_completion_queue_functor { CompletionQueue* Server::CallbackCQ() { // TODO(vjpai): Consider using a single global CQ for the default CQ // if there is no explicit per-server CQ registered - std::lock_guard l(mu_); + grpc::internal::MutexLock l(&mu_); if (callback_cq_ == nullptr) { auto* shutdown_callback = new ShutdownCallback; callback_cq_ = new CompletionQueue(grpc_completion_queue_attributes{ diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc index 73fd6a62c48..70c5cd8861e 100644 --- a/src/cpp/server/server_context.cc +++ b/src/cpp/server/server_context.cc @@ -33,6 +33,7 @@ #include #include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/surface/call.h" namespace grpc { @@ -96,7 +97,7 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { } void SetCancelCallback(std::function callback) { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); if (finalized_ && (cancelled_ != 0)) { callback(); @@ -107,7 +108,7 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { } void ClearCancelCallback() { - std::lock_guard g(mu_); + grpc_core::MutexLock g(&mu_); cancel_callback_ = nullptr; } @@ -144,7 +145,7 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { private: bool CheckCancelledNoPluck() { - std::lock_guard g(mu_); + grpc_core::MutexLock lock(&mu_); return finalized_ ? (cancelled_ != 0) : false; } @@ -154,7 +155,7 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { void* tag_; void* core_cq_tag_; grpc_core::RefCount refs_; - std::mutex mu_; + grpc_core::Mutex mu_; bool finalized_; int cancelled_; // This is an int (not bool) because it is passed to core std::function cancel_callback_; @@ -186,7 +187,7 @@ void ServerContext::CompletionOp::FillOps(internal::Call* call) { bool ServerContext::CompletionOp::FinalizeResult(void** tag, bool* status) { bool ret = false; - std::unique_lock lock(mu_); + grpc_core::ReleasableMutexLock lock(&mu_); if (done_intercepting_) { /* We are done intercepting. */ if (has_tag_) { @@ -216,12 +217,11 @@ bool ServerContext::CompletionOp::FinalizeResult(void** tag, bool* status) { // Release the lock since we are going to be calling a callback and // interceptors now - lock.unlock(); + lock.Unlock(); if (call_cancel && reactor_ != nullptr) { reactor_->OnCancel(); } - /* Add interception point and run through interceptors */ interceptor_methods_.AddInterceptionHookPoint( experimental::InterceptionHookPoints::POST_RECV_CLOSE); diff --git a/src/cpp/thread_manager/thread_manager.cc b/src/cpp/thread_manager/thread_manager.cc index 3e8606a76fd..2b65352f797 100644 --- a/src/cpp/thread_manager/thread_manager.cc +++ b/src/cpp/thread_manager/thread_manager.cc @@ -62,7 +62,7 @@ ThreadManager::ThreadManager(const char* name, ThreadManager::~ThreadManager() { { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); GPR_ASSERT(num_threads_ == 0); } @@ -72,38 +72,38 @@ ThreadManager::~ThreadManager() { } void ThreadManager::Wait() { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); while (num_threads_ != 0) { - shutdown_cv_.wait(lock); + shutdown_cv_.Wait(&mu_); } } void ThreadManager::Shutdown() { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); shutdown_ = true; } bool ThreadManager::IsShutdown() { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); return shutdown_; } int ThreadManager::GetMaxActiveThreadsSoFar() { - std::lock_guard list_lock(list_mu_); + grpc_core::MutexLock list_lock(&list_mu_); return max_active_threads_sofar_; } void ThreadManager::MarkAsCompleted(WorkerThread* thd) { { - std::lock_guard list_lock(list_mu_); + grpc_core::MutexLock list_lock(&list_mu_); completed_threads_.push_back(thd); } { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); num_threads_--; if (num_threads_ == 0) { - shutdown_cv_.notify_one(); + shutdown_cv_.Signal(); } } @@ -116,7 +116,7 @@ void ThreadManager::CleanupCompletedThreads() { { // swap out the completed threads list: allows other threads to clean up // more quickly - std::unique_lock lock(list_mu_); + grpc_core::MutexLock lock(&list_mu_); completed_threads.swap(completed_threads_); } for (auto thd : completed_threads) delete thd; @@ -132,7 +132,7 @@ void ThreadManager::Initialize() { } { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); num_pollers_ = min_pollers_; num_threads_ = min_pollers_; max_active_threads_sofar_ = min_pollers_; @@ -149,7 +149,7 @@ void ThreadManager::MainWorkLoop() { bool ok; WorkStatus work_status = PollForWork(&tag, &ok); - std::unique_lock lock(mu_); + grpc_core::ReleasableMutexLock lock(&mu_); // Reduce the number of pollers by 1 and check what happened with the poll num_pollers_--; bool done = false; @@ -176,30 +176,30 @@ void ThreadManager::MainWorkLoop() { max_active_threads_sofar_ = num_threads_; } // Drop lock before spawning thread to avoid contention - lock.unlock(); + lock.Unlock(); new WorkerThread(this); } else if (num_pollers_ > 0) { // There is still at least some thread polling, so we can go on // even though we are below the number of pollers that we would // like to have (min_pollers_) - lock.unlock(); + lock.Unlock(); } else { // There are no pollers to spare and we couldn't allocate // a new thread, so resources are exhausted! - lock.unlock(); + lock.Unlock(); resource_exhausted = true; } } else { // There are a sufficient number of pollers available so we can do // the work and continue polling with our existing poller threads - lock.unlock(); + lock.Unlock(); } // Lock is always released at this point - do the application work // or return resource exhausted if there is new work but we couldn't // get a thread in which to do it. DoWork(tag, ok, !resource_exhausted); // Take the lock again to check post conditions - lock.lock(); + lock.Lock(); // If we're shutdown, we should finish at this point. if (shutdown_) done = true; break; diff --git a/src/cpp/thread_manager/thread_manager.h b/src/cpp/thread_manager/thread_manager.h index 6f0bd17c5fe..2fbf309d421 100644 --- a/src/cpp/thread_manager/thread_manager.h +++ b/src/cpp/thread_manager/thread_manager.h @@ -26,6 +26,7 @@ #include +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/thd.h" #include "src/core/lib/iomgr/resource_quota.h" @@ -140,10 +141,10 @@ class ThreadManager { // Protects shutdown_, num_pollers_, num_threads_ and // max_active_threads_sofar_ - std::mutex mu_; + grpc_core::Mutex mu_; bool shutdown_; - std::condition_variable shutdown_cv_; + grpc_core::CondVar shutdown_cv_; // The resource user object to use when requesting quota to create threads // @@ -169,7 +170,7 @@ class ThreadManager { // ever set so far int max_active_threads_sofar_; - std::mutex list_mu_; + grpc_core::Mutex list_mu_; std::list completed_threads_; }; diff --git a/test/cpp/client/client_channel_stress_test.cc b/test/cpp/client/client_channel_stress_test.cc index 91419cb257b..d326b2ed37e 100644 --- a/test/cpp/client/client_channel_stress_test.cc +++ b/test/cpp/client/client_channel_stress_test.cc @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -168,24 +169,24 @@ class ClientChannelStressTest { explicit ServerThread(const grpc::string& type, const grpc::string& server_host, T* service) : type_(type), service_(service) { - std::mutex mu; + grpc::internal::Mutex mu; // We need to acquire the lock here in order to prevent the notify_one // by ServerThread::Start from firing before the wait below is hit. - std::unique_lock lock(mu); + grpc::internal::MutexLock lock(&mu); port_ = grpc_pick_unused_port_or_die(); gpr_log(GPR_INFO, "starting %s server on port %d", type_.c_str(), port_); - std::condition_variable cond; + grpc::internal::CondVar cond; thread_.reset(new std::thread( std::bind(&ServerThread::Start, this, server_host, &mu, &cond))); - cond.wait(lock); + cond.Wait(&mu); gpr_log(GPR_INFO, "%s server startup complete", type_.c_str()); } - void Start(const grpc::string& server_host, std::mutex* mu, - std::condition_variable* cond) { + void Start(const grpc::string& server_host, grpc::internal::Mutex* mu, + grpc::internal::CondVar* cond) { // We need to acquire the lock here in order to prevent the notify_one // below from firing before its corresponding wait is executed. - std::lock_guard lock(*mu); + grpc::internal::MutexLock lock(mu); std::ostringstream server_address; server_address << server_host << ":" << port_; ServerBuilder builder; @@ -193,7 +194,7 @@ class ClientChannelStressTest { InsecureServerCredentials()); builder.RegisterService(service_); server_ = builder.BuildAndStart(); - cond->notify_one(); + cond->Signal(); } void Shutdown() { diff --git a/test/cpp/end2end/client_lb_end2end_test.cc b/test/cpp/end2end/client_lb_end2end_test.cc index 77f9db94acc..6623a2ff55f 100644 --- a/test/cpp/end2end/client_lb_end2end_test.cc +++ b/test/cpp/end2end/client_lb_end2end_test.cc @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -98,7 +99,7 @@ class MyTestServiceImpl : public TestServiceImpl { Status Echo(ServerContext* context, const EchoRequest* request, EchoResponse* response) override { { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); ++request_count_; } AddClient(context->peer()); @@ -106,29 +107,29 @@ class MyTestServiceImpl : public TestServiceImpl { } int request_count() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); return request_count_; } void ResetCounters() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); request_count_ = 0; } std::set clients() { - std::unique_lock lock(clients_mu_); + grpc::internal::MutexLock lock(&clients_mu_); return clients_; } private: void AddClient(const grpc::string& client) { - std::unique_lock lock(clients_mu_); + grpc::internal::MutexLock lock(&clients_mu_); clients_.insert(client); } - std::mutex mu_; + grpc::internal::Mutex mu_; int request_count_; - std::mutex clients_mu_; + grpc::internal::Mutex clients_mu_; std::set clients_; }; @@ -293,18 +294,18 @@ class ClientLbEnd2endTest : public ::testing::Test { void Start(const grpc::string& server_host) { gpr_log(GPR_INFO, "starting server on port %d", port_); started_ = true; - std::mutex mu; - std::unique_lock lock(mu); - std::condition_variable cond; + grpc::internal::Mutex mu; + grpc::internal::MutexLock lock(&mu); + grpc::internal::CondVar cond; thread_.reset(new std::thread( std::bind(&ServerData::Serve, this, server_host, &mu, &cond))); - cond.wait(lock, [this] { return server_ready_; }); + cond.WaitUntil(&mu, [this] { return server_ready_; }); server_ready_ = false; gpr_log(GPR_INFO, "server startup complete"); } - void Serve(const grpc::string& server_host, std::mutex* mu, - std::condition_variable* cond) { + void Serve(const grpc::string& server_host, grpc::internal::Mutex* mu, + grpc::internal::CondVar* cond) { std::ostringstream server_address; server_address << server_host << ":" << port_; ServerBuilder builder; @@ -313,9 +314,9 @@ class ClientLbEnd2endTest : public ::testing::Test { builder.AddListeningPort(server_address.str(), std::move(creds)); builder.RegisterService(&service_); server_ = builder.BuildAndStart(); - std::lock_guard lock(*mu); + grpc::internal::MutexLock lock(mu); server_ready_ = true; - cond->notify_one(); + cond->Signal(); } void Shutdown() { @@ -1374,7 +1375,7 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest { void TearDown() override { ClientLbEnd2endTest::TearDown(); } int trailers_intercepted() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); return trailers_intercepted_; } @@ -1382,11 +1383,11 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest { static void ReportTrailerIntercepted(void* arg) { ClientLbInterceptTrailingMetadataTest* self = static_cast(arg); - std::unique_lock lock(self->mu_); + grpc::internal::MutexLock lock(&self->mu_); self->trailers_intercepted_++; } - std::mutex mu_; + grpc::internal::Mutex mu_; int trailers_intercepted_ = 0; }; diff --git a/test/cpp/end2end/grpclb_end2end_test.cc b/test/cpp/end2end/grpclb_end2end_test.cc index 0dc3746c2d7..f8d887dd24d 100644 --- a/test/cpp/end2end/grpclb_end2end_test.cc +++ b/test/cpp/end2end/grpclb_end2end_test.cc @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -85,32 +86,32 @@ template class CountedService : public ServiceType { public: size_t request_count() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); return request_count_; } size_t response_count() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); return response_count_; } void IncreaseResponseCount() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); ++response_count_; } void IncreaseRequestCount() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); ++request_count_; } void ResetCounters() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); request_count_ = 0; response_count_ = 0; } protected: - std::mutex mu_; + grpc::internal::Mutex mu_; private: size_t request_count_ = 0; @@ -148,18 +149,18 @@ class BackendServiceImpl : public BackendService { void Shutdown() {} std::set clients() { - std::unique_lock lock(clients_mu_); + grpc::internal::MutexLock lock(&clients_mu_); return clients_; } private: void AddClient(const grpc::string& client) { - std::unique_lock lock(clients_mu_); + grpc::internal::MutexLock lock(&clients_mu_); clients_.insert(client); } - std::mutex mu_; - std::mutex clients_mu_; + grpc::internal::Mutex mu_; + grpc::internal::Mutex clients_mu_; std::set clients_; }; @@ -210,7 +211,7 @@ class BalancerServiceImpl : public BalancerService { Status BalanceLoad(ServerContext* context, Stream* stream) override { gpr_log(GPR_INFO, "LB[%p]: BalanceLoad", this); { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); if (serverlist_done_) goto done; } { @@ -237,7 +238,7 @@ class BalancerServiceImpl : public BalancerService { } { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); responses_and_delays = responses_and_delays_; } for (const auto& response_and_delay : responses_and_delays) { @@ -245,8 +246,8 @@ class BalancerServiceImpl : public BalancerService { response_and_delay.second); } { - std::unique_lock lock(mu_); - serverlist_cond_.wait(lock, [this] { return serverlist_done_; }); + grpc::internal::MutexLock lock(&mu_); + serverlist_cond_.WaitUntil(&mu_, [this] { return serverlist_done_; }); } if (client_load_reporting_interval_seconds_ > 0) { @@ -257,7 +258,7 @@ class BalancerServiceImpl : public BalancerService { GPR_ASSERT(request.has_client_stats()); // We need to acquire the lock here in order to prevent the notify_one // below from firing before its corresponding wait is executed. - std::lock_guard lock(mu_); + grpc::internal::MutexLock lock(&mu_); client_stats_.num_calls_started += request.client_stats().num_calls_started(); client_stats_.num_calls_finished += @@ -274,7 +275,7 @@ class BalancerServiceImpl : public BalancerService { drop_token_count.num_calls(); } load_report_ready_ = true; - load_report_cond_.notify_one(); + load_report_cond_.Signal(); } } } @@ -284,12 +285,12 @@ class BalancerServiceImpl : public BalancerService { } void add_response(const LoadBalanceResponse& response, int send_after_ms) { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); responses_and_delays_.push_back(std::make_pair(response, send_after_ms)); } void Start() { - std::lock_guard lock(mu_); + grpc::internal::MutexLock lock(&mu_); serverlist_done_ = false; load_report_ready_ = false; responses_and_delays_.clear(); @@ -326,17 +327,17 @@ class BalancerServiceImpl : public BalancerService { } const ClientStats& WaitForLoadReport() { - std::unique_lock lock(mu_); - load_report_cond_.wait(lock, [this] { return load_report_ready_; }); + grpc::internal::MutexLock lock(&mu_); + load_report_cond_.WaitUntil(&mu_, [this] { return load_report_ready_; }); load_report_ready_ = false; return client_stats_; } void NotifyDoneWithServerlists() { - std::lock_guard lock(mu_); + grpc::internal::MutexLock lock(&mu_); if (!serverlist_done_) { serverlist_done_ = true; - serverlist_cond_.notify_all(); + serverlist_cond_.Broadcast(); } } @@ -355,10 +356,10 @@ class BalancerServiceImpl : public BalancerService { const int client_load_reporting_interval_seconds_; std::vector responses_and_delays_; - std::mutex mu_; - std::condition_variable load_report_cond_; + grpc::internal::Mutex mu_; + grpc::internal::CondVar load_report_cond_; bool load_report_ready_ = false; - std::condition_variable serverlist_cond_; + grpc::internal::CondVar serverlist_cond_; bool serverlist_done_ = false; ClientStats client_stats_; }; @@ -624,22 +625,22 @@ class GrpclbEnd2endTest : public ::testing::Test { GPR_ASSERT(!running_); running_ = true; service_.Start(); - std::mutex mu; + grpc::internal::Mutex mu; // We need to acquire the lock here in order to prevent the notify_one // by ServerThread::Serve from firing before the wait below is hit. - std::unique_lock lock(mu); - std::condition_variable cond; + grpc::internal::MutexLock lock(&mu); + grpc::internal::CondVar cond; thread_.reset(new std::thread( std::bind(&ServerThread::Serve, this, server_host, &mu, &cond))); - cond.wait(lock); + cond.Wait(&mu); gpr_log(GPR_INFO, "%s server startup complete", type_.c_str()); } - void Serve(const grpc::string& server_host, std::mutex* mu, - std::condition_variable* cond) { + void Serve(const grpc::string& server_host, grpc::internal::Mutex* mu, + grpc::internal::CondVar* cond) { // We need to acquire the lock here in order to prevent the notify_one // below from firing before its corresponding wait is executed. - std::lock_guard lock(*mu); + grpc::internal::MutexLock lock(mu); std::ostringstream server_address; server_address << server_host << ":" << port_; ServerBuilder builder; @@ -648,7 +649,7 @@ class GrpclbEnd2endTest : public ::testing::Test { builder.AddListeningPort(server_address.str(), creds); builder.RegisterService(&service_); server_ = builder.BuildAndStart(); - cond->notify_one(); + cond->Signal(); } void Shutdown() { diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc index e30ce0dbcbf..5b8af61ee33 100644 --- a/test/cpp/end2end/thread_stress_test.cc +++ b/test/cpp/end2end/thread_stress_test.cc @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -188,7 +189,7 @@ class CommonStressTestAsyncServer : public BaseClass { } void TearDown() override { { - std::unique_lock l(mu_); + grpc::internal::MutexLock l(&mu_); this->TearDownStart(); shutting_down_ = true; cq_->Shutdown(); @@ -229,7 +230,7 @@ class CommonStressTestAsyncServer : public BaseClass { } } void RefreshContext(int i) { - std::unique_lock l(mu_); + grpc::internal::MutexLock l(&mu_); if (!shutting_down_) { contexts_[i].state = Context::READY; contexts_[i].srv_ctx.reset(new ServerContext); @@ -253,7 +254,7 @@ class CommonStressTestAsyncServer : public BaseClass { ::grpc::testing::EchoTestService::AsyncService service_; std::unique_ptr cq_; bool shutting_down_; - std::mutex mu_; + grpc::internal::Mutex mu_; std::vector server_threads_; }; @@ -341,9 +342,9 @@ class AsyncClientEnd2endTest : public ::testing::Test { } void Wait() { - std::unique_lock l(mu_); + grpc::internal::MutexLock l(&mu_); while (rpcs_outstanding_ != 0) { - cv_.wait(l); + cv_.Wait(&mu_); } cq_.Shutdown(); @@ -366,7 +367,7 @@ class AsyncClientEnd2endTest : public ::testing::Test { call->response_reader->Finish(&call->response, &call->status, (void*)call); - std::unique_lock l(mu_); + grpc::internal::MutexLock l(&mu_); rpcs_outstanding_++; } } @@ -384,20 +385,20 @@ class AsyncClientEnd2endTest : public ::testing::Test { bool notify; { - std::unique_lock l(mu_); + grpc::internal::MutexLock l(&mu_); rpcs_outstanding_--; notify = (rpcs_outstanding_ == 0); } if (notify) { - cv_.notify_all(); + cv_.Signal(); } } } Common common_; CompletionQueue cq_; - std::mutex mu_; - std::condition_variable cv_; + grpc::internal::Mutex mu_; + grpc::internal::CondVar cv_; int rpcs_outstanding_; }; diff --git a/test/cpp/end2end/xds_end2end_test.cc b/test/cpp/end2end/xds_end2end_test.cc index c767a4485ce..ee248239909 100644 --- a/test/cpp/end2end/xds_end2end_test.cc +++ b/test/cpp/end2end/xds_end2end_test.cc @@ -84,32 +84,32 @@ template class CountedService : public ServiceType { public: size_t request_count() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); return request_count_; } size_t response_count() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); return response_count_; } void IncreaseResponseCount() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); ++response_count_; } void IncreaseRequestCount() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); ++request_count_; } void ResetCounters() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); request_count_ = 0; response_count_ = 0; } protected: - std::mutex mu_; + grpc::internal::Mutex mu_; private: size_t request_count_ = 0; @@ -145,18 +145,18 @@ class BackendServiceImpl : public BackendService { void Shutdown() {} std::set clients() { - std::unique_lock lock(clients_mu_); + grpc::internal::MutexLock lock(&clients_mu_); return clients_; } private: void AddClient(const grpc::string& client) { - std::unique_lock lock(clients_mu_); + grpc::internal::MutexLock lock(&clients_mu_); clients_.insert(client); } - std::mutex mu_; - std::mutex clients_mu_; + grpc::internal::Mutex mu_; + grpc::internal::Mutex clients_mu_; std::set clients_; }; @@ -208,7 +208,7 @@ class BalancerServiceImpl : public BalancerService { // TODO(juanlishen): Clean up the scoping. gpr_log(GPR_INFO, "LB[%p]: BalanceLoad", this); { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); if (serverlist_done_) goto done; } { @@ -234,7 +234,7 @@ class BalancerServiceImpl : public BalancerService { } { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); responses_and_delays = responses_and_delays_; } for (const auto& response_and_delay : responses_and_delays) { @@ -242,8 +242,8 @@ class BalancerServiceImpl : public BalancerService { response_and_delay.second); } { - std::unique_lock lock(mu_); - serverlist_cond_.wait(lock, [this] { return serverlist_done_; }); + grpc::internal::MutexLock lock(&mu_); + serverlist_cond_.WaitUntil(&mu_, [this] { return serverlist_done_; }); } if (client_load_reporting_interval_seconds_ > 0) { @@ -254,7 +254,7 @@ class BalancerServiceImpl : public BalancerService { GPR_ASSERT(request.has_client_stats()); // We need to acquire the lock here in order to prevent the notify_one // below from firing before its corresponding wait is executed. - std::lock_guard lock(mu_); + grpc::internal::MutexLock lock(&mu_); client_stats_.num_calls_started += request.client_stats().num_calls_started(); client_stats_.num_calls_finished += @@ -271,7 +271,7 @@ class BalancerServiceImpl : public BalancerService { drop_token_count.num_calls(); } load_report_ready_ = true; - load_report_cond_.notify_one(); + load_report_cond_.Signal(); } } } @@ -281,12 +281,12 @@ class BalancerServiceImpl : public BalancerService { } void add_response(const LoadBalanceResponse& response, int send_after_ms) { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); responses_and_delays_.push_back(std::make_pair(response, send_after_ms)); } void Shutdown() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); NotifyDoneWithServerlistsLocked(); responses_and_delays_.clear(); client_stats_.Reset(); @@ -318,21 +318,21 @@ class BalancerServiceImpl : public BalancerService { } const ClientStats& WaitForLoadReport() { - std::unique_lock lock(mu_); - load_report_cond_.wait(lock, [this] { return load_report_ready_; }); + grpc::internal::MutexLock lock(&mu_); + load_report_cond_.WaitUntil(&mu_, [this] { return load_report_ready_; }); load_report_ready_ = false; return client_stats_; } void NotifyDoneWithServerlists() { - std::lock_guard lock(mu_); + grpc::internal::MutexLock lock(&mu_); NotifyDoneWithServerlistsLocked(); } void NotifyDoneWithServerlistsLocked() { if (!serverlist_done_) { serverlist_done_ = true; - serverlist_cond_.notify_all(); + serverlist_cond_.Broadcast(); } } @@ -351,10 +351,10 @@ class BalancerServiceImpl : public BalancerService { const int client_load_reporting_interval_seconds_; std::vector responses_and_delays_; - std::mutex mu_; - std::condition_variable load_report_cond_; + grpc::internal::Mutex mu_; + grpc::internal::CondVar load_report_cond_; bool load_report_ready_ = false; - std::condition_variable serverlist_cond_; + grpc::internal::CondVar serverlist_cond_; bool serverlist_done_ = false; ClientStats client_stats_; }; @@ -637,22 +637,22 @@ class XdsEnd2endTest : public ::testing::Test { gpr_log(GPR_INFO, "starting %s server on port %d", type_.c_str(), port_); GPR_ASSERT(!running_); running_ = true; - std::mutex mu; + grpc::internal::Mutex mu; // We need to acquire the lock here in order to prevent the notify_one // by ServerThread::Serve from firing before the wait below is hit. - std::unique_lock lock(mu); - std::condition_variable cond; + grpc::internal::MutexLock lock(&mu); + grpc::internal::CondVar cond; thread_.reset(new std::thread( std::bind(&ServerThread::Serve, this, server_host, &mu, &cond))); - cond.wait(lock); + cond.Wait(&mu); gpr_log(GPR_INFO, "%s server startup complete", type_.c_str()); } - void Serve(const grpc::string& server_host, std::mutex* mu, - std::condition_variable* cond) { + void Serve(const grpc::string& server_host, grpc::internal::Mutex* mu, + grpc::internal::CondVar* cond) { // We need to acquire the lock here in order to prevent the notify_one // below from firing before its corresponding wait is executed. - std::lock_guard lock(*mu); + grpc::internal::MutexLock lock(mu); std::ostringstream server_address; server_address << server_host << ":" << port_; ServerBuilder builder; @@ -661,7 +661,7 @@ class XdsEnd2endTest : public ::testing::Test { builder.AddListeningPort(server_address.str(), creds); builder.RegisterService(&service_); server_ = builder.BuildAndStart(); - cond->notify_one(); + cond->Signal(); } void Shutdown() { diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 7274f9588b3..a0a6e952409 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -987,6 +987,7 @@ include/grpcpp/impl/codegen/status.h \ include/grpcpp/impl/codegen/status_code_enum.h \ include/grpcpp/impl/codegen/string_ref.h \ include/grpcpp/impl/codegen/stub_options.h \ +include/grpcpp/impl/codegen/sync.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ include/grpcpp/impl/grpc_library.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index f169199ae96..21e5b49440f 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -989,6 +989,7 @@ include/grpcpp/impl/codegen/status.h \ include/grpcpp/impl/codegen/status_code_enum.h \ include/grpcpp/impl/codegen/string_ref.h \ include/grpcpp/impl/codegen/stub_options.h \ +include/grpcpp/impl/codegen/sync.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ include/grpcpp/impl/grpc_library.h \ @@ -1085,12 +1086,12 @@ src/core/lib/gprpp/inlined_vector.h \ src/core/lib/gprpp/manual_constructor.h \ src/core/lib/gprpp/map.h \ src/core/lib/gprpp/memory.h \ -src/core/lib/gprpp/mutex_lock.h \ src/core/lib/gprpp/optional.h \ src/core/lib/gprpp/orphanable.h \ src/core/lib/gprpp/pair.h \ src/core/lib/gprpp/ref_counted.h \ src/core/lib/gprpp/ref_counted_ptr.h \ +src/core/lib/gprpp/sync.h \ src/core/lib/gprpp/thd.h \ src/core/lib/http/format_request.h \ src/core/lib/http/httpcli.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index e68e758c64e..1817be44bc3 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1166,12 +1166,12 @@ src/core/lib/gprpp/inlined_vector.h \ src/core/lib/gprpp/manual_constructor.h \ src/core/lib/gprpp/map.h \ src/core/lib/gprpp/memory.h \ -src/core/lib/gprpp/mutex_lock.h \ src/core/lib/gprpp/optional.h \ src/core/lib/gprpp/orphanable.h \ src/core/lib/gprpp/pair.h \ src/core/lib/gprpp/ref_counted.h \ src/core/lib/gprpp/ref_counted_ptr.h \ +src/core/lib/gprpp/sync.h \ src/core/lib/gprpp/thd.h \ src/core/lib/gprpp/thd_posix.cc \ src/core/lib/gprpp/thd_windows.cc \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 29fd6f32e59..29372824822 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -8033,8 +8033,8 @@ "src/core/lib/gprpp/manual_constructor.h", "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", - "src/core/lib/gprpp/mutex_lock.h", "src/core/lib/gprpp/pair.h", + "src/core/lib/gprpp/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/profiling/timers.h" ], @@ -8081,8 +8081,8 @@ "src/core/lib/gprpp/manual_constructor.h", "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", - "src/core/lib/gprpp/mutex_lock.h", "src/core/lib/gprpp/pair.h", + "src/core/lib/gprpp/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/profiling/timers.h" ], @@ -9860,6 +9860,7 @@ }, { "deps": [ + "grpc++_internal_hdrs_only", "grpc_codegen" ], "headers": [ @@ -10056,6 +10057,7 @@ "gpr", "gpr_base_headers", "grpc++_codegen_base", + "grpc++_internal_hdrs_only", "grpc_base_headers", "grpc_transport_inproc_headers", "health_proto", @@ -10350,6 +10352,20 @@ "third_party": false, "type": "filegroup" }, + { + "deps": [], + "headers": [ + "include/grpcpp/impl/codegen/sync.h" + ], + "is_filegroup": true, + "language": "c++", + "name": "grpc++_internal_hdrs_only", + "src": [ + "include/grpcpp/impl/codegen/sync.h" + ], + "third_party": false, + "type": "filegroup" + }, { "deps": [], "headers": [ From bec72481b597f8e47c5e624af9639eafa16f0993 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 10 Apr 2019 16:19:13 -0700 Subject: [PATCH 238/242] Fix thread safety issue --- src/core/ext/transport/cronet/transport/cronet_transport.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.cc b/src/core/ext/transport/cronet/transport/cronet_transport.cc index 9551b4ba496..7ae178612c5 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.cc +++ b/src/core/ext/transport/cronet/transport/cronet_transport.cc @@ -177,7 +177,7 @@ struct op_and_state { bool done = false; struct stream_obj* s; /* Pointer back to the stream object */ /* next op_and_state in the linked list */ - struct op_and_state* next; + struct op_and_state* next = nullptr; }; struct op_storage { @@ -324,7 +324,7 @@ static grpc_error* make_error_with_desc(int error_code, const char* desc) { inline op_and_state::op_and_state(stream_obj* s, const grpc_transport_stream_op_batch& op) - : op(op), state(s->arena), s(s), next(s->storage.head) {} + : op(op), state(s->arena), s(s) {} /* Add a new stream op to op storage. @@ -339,6 +339,7 @@ static void add_to_storage(struct stream_obj* s, // TODO (mxyan): check if this is indeed necessary. new_op->done = false; gpr_mu_lock(&s->mu); + new_op->next = storage->head; storage->head = new_op; storage->num_pending_ops++; if (op->send_message) { From f371fce8871fbf67ed8af0fd3d51919d3bdacf5b Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 10 Apr 2019 16:20:31 -0700 Subject: [PATCH 239/242] Remove previous fix proposal proved to be wrong --- src/core/ext/transport/cronet/transport/cronet_transport.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.cc b/src/core/ext/transport/cronet/transport/cronet_transport.cc index 7ae178612c5..76a32dc4049 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.cc +++ b/src/core/ext/transport/cronet/transport/cronet_transport.cc @@ -335,9 +335,6 @@ static void add_to_storage(struct stream_obj* s, /* add new op at the beginning of the linked list. The memory is freed in remove_from_storage */ op_and_state* new_op = grpc_core::New(s, *op); - // Pontential fix to crash on GPR_ASSERT(!curr->done) - // TODO (mxyan): check if this is indeed necessary. - new_op->done = false; gpr_mu_lock(&s->mu); new_op->next = storage->head; storage->head = new_op; From 56d09be51d006779c9296d7e79e86e3434d338e5 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 9 Apr 2019 11:31:32 -0700 Subject: [PATCH 240/242] Update CFStream doc --- src/objective-c/README-CFSTREAM.md | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/objective-c/README-CFSTREAM.md b/src/objective-c/README-CFSTREAM.md index 0cb25ab237b..184d5679cbb 100644 --- a/src/objective-c/README-CFSTREAM.md +++ b/src/objective-c/README-CFSTREAM.md @@ -6,24 +6,19 @@ sockets) for networking. Using CFStream resolves a bunch of network connectivity (see the [doc](https://github.com/grpc/grpc/blob/master/src/objective-c/NetworkTransitionBehavior.md) for more information). -CFStream integration is now in experimental state. You will need explicit opt-in to use it to get +CFStream integration is now in experimental state. You will need explicit opt-in to use it to get the benefits of resolving the issues above. We expect to make CFStream the default networking -interface that gRPC uses when it is ready for production. +interface that gRPC uses when it is ready for production. + +As of v1.21.0, CFStream integration is now the default networking stack being used by gRPC +Objective-C on iOS layer. You get to use it automatically without special configuration needed. See +below on how to disable CFStream in case of problem. ## Usage -If you use gRPC following the instructions in -[README.md](https://github.com/grpc/grpc/blob/master/src/objective-c/README.md): -- Replace the -dependency on `gRPC-ProtoRPC` with `gRPC-ProtoRPC/CFStream`. -- Enable CFStream with environment variable `grpc_cfstream=1`. This can be done either in Xcode - console or by your code with `setenv()` before gRPC is initialized. - -If your project directly depends on podspecs other than `gRPC-ProtoRPC` (e.g. `gRPC` or -`gRPC-Core`): - -- Make your projects depend on subspecs corresponding to CFStream in each gRPC podspec. -- Enable CFStream with environment variable `grpc_cfstream=1`. This can be done either in Xcode - console or by your code with `setenv()` before gRPC is initialized. +If you use gRPC Objective-C library on iOS, CFStream is on automatically. If you use it on other +platforms, you can turn it on with macro `GRPC_CFSTREAM=1` for the pod 'gRPC-Core' and 'gRPC'. In +case of problem and you want to disable CFStream on iOS, you can set environment variable +"grpc\_cfstream=0". ## Notes From 453cde5fb9813cf61085a8ca3bf032bccd5d4d9f Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 11 Apr 2019 11:47:10 -0400 Subject: [PATCH 241/242] use bazel 0.23.2 for macos bazel build --- tools/internal_ci/macos/grpc_run_bazel_tests.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/internal_ci/macos/grpc_run_bazel_tests.sh b/tools/internal_ci/macos/grpc_run_bazel_tests.sh index ef02a675d5b..56fae8fd75f 100644 --- a/tools/internal_ci/macos/grpc_run_bazel_tests.sh +++ b/tools/internal_ci/macos/grpc_run_bazel_tests.sh @@ -18,6 +18,13 @@ set -ex # change to grpc repo root cd $(dirname $0)/../../.. +# Download bazel +temp_dir="$(mktemp -d)" +wget -q https://github.com/bazelbuild/bazel/releases/download/0.23.2/bazel-0.23.2-darwin-x86_64 -O "${temp_dir}/bazel" +chmod 755 "${temp_dir}/bazel" +export PATH="${temp_dir}:${PATH}" +# This should show ${temp_dir}/bazel +which bazel ./tools/run_tests/start_port_server.py From 167540efd441731db57f9110ea73957d4642a8b7 Mon Sep 17 00:00:00 2001 From: Richard Belleville Date: Thu, 11 Apr 2019 10:10:29 -0700 Subject: [PATCH 242/242] Revert "Merge pull request #18564 from grpc/compression" This reverts commit 9dfeb14be077a4f8d6d7778dfc8dd9d872ce72d4, reversing changes made to 7009f2df5838854ea909b47a19f0016f3d74ca71. --- .pylintrc | 4 +- doc/python/sphinx/grpc.rst | 6 - src/python/grpcio/grpc/BUILD.bazel | 8 - src/python/grpcio/grpc/__init__.py | 96 +---- src/python/grpcio/grpc/_channel.py | 114 +++--- src/python/grpcio/grpc/_compression.py | 55 --- .../grpcio/grpc/_cython/_cygrpc/grpc.pxi | 8 +- .../grpc/_cython/_cygrpc/records.pyx.pxi | 5 - src/python/grpcio/grpc/_interceptor.py | 139 +++---- src/python/grpcio/grpc/_server.py | 88 +--- .../grpc_testing/_server/_servicer_context.py | 6 - src/python/grpcio_tests/commands.py | 1 - .../grpcio_tests/tests/unit/BUILD.bazel | 6 - .../grpcio_tests/tests/unit/_api_test.py | 1 - .../tests/unit/_compression_test.py | 375 +++--------------- .../grpcio_tests/tests/unit/_tcp_proxy.py | 164 -------- 16 files changed, 189 insertions(+), 887 deletions(-) delete mode 100644 src/python/grpcio/grpc/_compression.py delete mode 100644 src/python/grpcio_tests/tests/unit/_tcp_proxy.py diff --git a/.pylintrc b/.pylintrc index fcc8e73cb41..ba74decb047 100644 --- a/.pylintrc +++ b/.pylintrc @@ -6,8 +6,6 @@ ignore= src/python/grpcio/grpc/framework/foundation, src/python/grpcio/grpc/framework/interfaces, -extension-pkg-whitelist=grpc._cython.cygrpc - [VARIABLES] # TODO(https://github.com/PyCQA/pylint/issues/1345): How does the inspection @@ -19,7 +17,7 @@ dummy-variables-rgx=^ignored_|^unused_ # NOTE(nathaniel): Not particularly attached to this value; it just seems to # be what works for us at the moment (excepting the dead-code-walking Beta # API). -max-args=7 +max-args=6 [MISCELLANEOUS] diff --git a/doc/python/sphinx/grpc.rst b/doc/python/sphinx/grpc.rst index 0934db7188b..f534d25c639 100644 --- a/doc/python/sphinx/grpc.rst +++ b/doc/python/sphinx/grpc.rst @@ -172,9 +172,3 @@ Future Interfaces .. autoexception:: FutureTimeoutError .. autoexception:: FutureCancelledError .. autoclass:: Future - - -Compression -^^^^^^^^^^^ - -.. autoclass:: Compression diff --git a/src/python/grpcio/grpc/BUILD.bazel b/src/python/grpcio/grpc/BUILD.bazel index a2bedae4bea..27d5d2e4bb2 100644 --- a/src/python/grpcio/grpc/BUILD.bazel +++ b/src/python/grpcio/grpc/BUILD.bazel @@ -12,7 +12,6 @@ py_library( ":channel", ":interceptor", ":server", - ":compression", "//src/python/grpcio/grpc/_cython:cygrpc", "//src/python/grpcio/grpc/experimental", "//src/python/grpcio/grpc/framework", @@ -32,18 +31,12 @@ py_library( srcs = ["_auth.py"], ) -py_library( - name = "compression", - srcs = ["_compression.py"], -) - py_library( name = "channel", srcs = ["_channel.py"], deps = [ ":common", ":grpcio_metadata", - ":compression", ], ) @@ -75,7 +68,6 @@ py_library( srcs = ["_server.py"], deps = [ ":common", - ":compression", ":interceptor", ], ) diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py index 6175180e92a..76314106ca4 100644 --- a/src/python/grpcio/grpc/__init__.py +++ b/src/python/grpcio/grpc/__init__.py @@ -21,7 +21,6 @@ import sys import six from grpc._cython import cygrpc as _cygrpc -from grpc import _compression logging.getLogger(__name__).addHandler(logging.NullHandler()) @@ -414,8 +413,6 @@ class ClientCallDetails(six.with_metaclass(abc.ABCMeta)): credentials: An optional CallCredentials for the RPC. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag t enable wait for ready mechanism. - compression: An element of grpc.compression, e.g. - grpc.compression.Gzip. This is an EXPERIMENTAL option. """ @@ -672,8 +669,7 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): """Synchronously invokes the underlying RPC. Args: @@ -685,8 +681,6 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): credentials: An optional CallCredentials for the RPC. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag to enable wait for ready mechanism - compression: An element of grpc.compression, e.g. - grpc.compression.Gzip. This is an EXPERIMENTAL option. Returns: The response value for the RPC. @@ -704,8 +698,7 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): """Synchronously invokes the underlying RPC. Args: @@ -717,8 +710,6 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): credentials: An optional CallCredentials for the RPC. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag to enable wait for ready mechanism - compression: An element of grpc.compression, e.g. - grpc.compression.Gzip. This is an EXPERIMENTAL option. Returns: The response value for the RPC and a Call value for the RPC. @@ -736,8 +727,7 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): """Asynchronously invokes the underlying RPC. Args: @@ -749,8 +739,6 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): credentials: An optional CallCredentials for the RPC. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag to enable wait for ready mechanism - compression: An element of grpc.compression, e.g. - grpc.compression.Gzip. This is an EXPERIMENTAL option. Returns: An object that is both a Call for the RPC and a Future. @@ -771,8 +759,7 @@ class UnaryStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): """Invokes the underlying RPC. Args: @@ -784,8 +771,6 @@ class UnaryStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): credentials: An optional CallCredentials for the RPC. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag to enable wait for ready mechanism - compression: An element of grpc.compression, e.g. - grpc.compression.Gzip. This is an EXPERIMENTAL option. Returns: An object that is both a Call for the RPC and an iterator of @@ -805,8 +790,7 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): """Synchronously invokes the underlying RPC. Args: @@ -819,8 +803,6 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): credentials: An optional CallCredentials for the RPC. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag to enable wait for ready mechanism - compression: An element of grpc.compression, e.g. - grpc.compression.Gzip. This is an EXPERIMENTAL option. Returns: The response value for the RPC. @@ -838,8 +820,7 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): """Synchronously invokes the underlying RPC on the client. Args: @@ -852,8 +833,6 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): credentials: An optional CallCredentials for the RPC. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag to enable wait for ready mechanism - compression: An element of grpc.compression, e.g. - grpc.compression.Gzip. This is an EXPERIMENTAL option. Returns: The response value for the RPC and a Call object for the RPC. @@ -871,8 +850,7 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): """Asynchronously invokes the underlying RPC on the client. Args: @@ -884,8 +862,6 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): credentials: An optional CallCredentials for the RPC. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag to enable wait for ready mechanism - compression: An element of grpc.compression, e.g. - grpc.compression.Gzip. This is an EXPERIMENTAL option. Returns: An object that is both a Call for the RPC and a Future. @@ -906,8 +882,7 @@ class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): """Invokes the underlying RPC on the client. Args: @@ -919,8 +894,6 @@ class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): credentials: An optional CallCredentials for the RPC. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag to enable wait for ready mechanism - compression: An element of grpc.compression, e.g. - grpc.compression.Gzip. This is an EXPERIMENTAL option. Returns: An object that is both a Call for the RPC and an iterator of @@ -1124,17 +1097,6 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): """ raise NotImplementedError() - def set_compression(self, compression): - """Set the compression algorithm to be used for the entire call. - - This is an EXPERIMENTAL method. - - Args: - compression: An element of grpc.compression, e.g. - grpc.compression.Gzip. - """ - raise NotImplementedError() - @abc.abstractmethod def send_initial_metadata(self, initial_metadata): """Sends the initial metadata value to the client. @@ -1222,16 +1184,6 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): """ raise NotImplementedError() - def disable_next_message_compression(self): - """Disables compression for the next response message. - - This is an EXPERIMENTAL method. - - This method will override any compression configuration set during - server creation or set on the call. - """ - raise NotImplementedError() - ##################### Service-Side Handler Interfaces ######################## @@ -1730,7 +1682,7 @@ def channel_ready_future(channel): return _utilities.channel_ready_future(channel) -def insecure_channel(target, options=None, compression=None): +def insecure_channel(target, options=None): """Creates an insecure Channel to a server. The returned Channel is thread-safe. @@ -1739,18 +1691,15 @@ def insecure_channel(target, options=None, compression=None): target: The server address options: An optional list of key-value pairs (channel args in gRPC Core runtime) to configure the channel. - compression: An optional value indicating the compression method to be - used over the lifetime of the channel. This is an EXPERIMENTAL option. Returns: A Channel. """ from grpc import _channel # pylint: disable=cyclic-import - return _channel.Channel(target, () - if options is None else options, None, compression) + return _channel.Channel(target, () if options is None else options, None) -def secure_channel(target, credentials, options=None, compression=None): +def secure_channel(target, credentials, options=None): """Creates a secure Channel to a server. The returned Channel is thread-safe. @@ -1760,15 +1709,13 @@ def secure_channel(target, credentials, options=None, compression=None): credentials: A ChannelCredentials instance. options: An optional list of key-value pairs (channel args in gRPC Core runtime) to configure the channel. - compression: An optional value indicating the compression method to be - used over the lifetime of the channel. This is an EXPERIMENTAL option. Returns: A Channel. """ from grpc import _channel # pylint: disable=cyclic-import return _channel.Channel(target, () if options is None else options, - credentials._credentials, compression) + credentials._credentials) def intercept_channel(channel, *interceptors): @@ -1803,8 +1750,7 @@ def server(thread_pool, handlers=None, interceptors=None, options=None, - maximum_concurrent_rpcs=None, - compression=None): + maximum_concurrent_rpcs=None): """Creates a Server with which RPCs can be serviced. Args: @@ -1822,9 +1768,6 @@ def server(thread_pool, maximum_concurrent_rpcs: The maximum number of concurrent RPCs this server will service before returning RESOURCE_EXHAUSTED status, or None to indicate no limit. - compression: An element of grpc.compression, e.g. - grpc.compression.Gzip. This compression algorithm will be used for the - lifetime of the server unless overridden. This is an EXPERIMENTAL option. Returns: A Server object. @@ -1834,7 +1777,7 @@ def server(thread_pool, if handlers is None else handlers, () if interceptors is None else interceptors, () if options is None else options, - maximum_concurrent_rpcs, compression) + maximum_concurrent_rpcs) @contextlib.contextmanager @@ -1845,16 +1788,6 @@ def _create_servicer_context(rpc_event, state, request_deserializer): context._finalize_state() # pylint: disable=protected-access -class Compression(enum.IntEnum): - """Indicates the compression method to be used for an RPC. - - This enumeration is part of an EXPERIMENTAL API. - """ - NoCompression = _compression.NoCompression - Deflate = _compression.Deflate - Gzip = _compression.Gzip - - ################################### __all__ ################################# __all__ = ( @@ -1872,7 +1805,6 @@ __all__ = ( 'AuthMetadataContext', 'AuthMetadataPluginCallback', 'AuthMetadataPlugin', - 'Compression', 'ClientCallDetails', 'ServerCertificateConfiguration', 'ServerCredentials', diff --git a/src/python/grpcio/grpc/_channel.py b/src/python/grpcio/grpc/_channel.py index 1272ee802bc..ed4c871b684 100644 --- a/src/python/grpcio/grpc/_channel.py +++ b/src/python/grpcio/grpc/_channel.py @@ -19,7 +19,6 @@ import threading import time import grpc -from grpc import _compression from grpc import _common from grpc import _grpcio_metadata from grpc._cython import cygrpc @@ -513,19 +512,17 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): self._response_deserializer = response_deserializer self._context = cygrpc.build_census_context() - def _prepare(self, request, timeout, metadata, wait_for_ready, compression): + def _prepare(self, request, timeout, metadata, wait_for_ready): deadline, serialized_request, rendezvous = _start_unary_request( request, timeout, self._request_serializer) initial_metadata_flags = _InitialMetadataFlags().with_wait_for_ready( wait_for_ready) - augmented_metadata = _compression.augment_metadata( - metadata, compression) if serialized_request is None: return None, None, None, rendezvous else: state = _RPCState(_UNARY_UNARY_INITIAL_DUE, None, None, None, None) operations = ( - cygrpc.SendInitialMetadataOperation(augmented_metadata, + cygrpc.SendInitialMetadataOperation(metadata, initial_metadata_flags), cygrpc.SendMessageOperation(serialized_request, _EMPTY_FLAGS), cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS), @@ -535,17 +532,18 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): ) return state, operations, deadline, None - def _blocking(self, request, timeout, metadata, credentials, wait_for_ready, - compression): + def _blocking(self, request, timeout, metadata, credentials, + wait_for_ready): state, operations, deadline, rendezvous = self._prepare( - request, timeout, metadata, wait_for_ready, compression) + request, timeout, metadata, wait_for_ready) if state is None: raise rendezvous # pylint: disable-msg=raising-bad-type else: + deadline_to_propagate = _determine_deadline(deadline) call = self._channel.segregated_call( cygrpc.PropagationConstants.GRPC_PROPAGATE_DEFAULTS, - self._method, None, _determine_deadline(deadline), metadata, - None if credentials is None else credentials._credentials, (( + self._method, None, deadline_to_propagate, metadata, None + if credentials is None else credentials._credentials, (( operations, None, ),), self._context) @@ -558,10 +556,9 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): state, call, = self._blocking(request, timeout, metadata, credentials, - wait_for_ready, compression) + wait_for_ready) return _end_unary_response_blocking(state, call, False, None) def with_call(self, @@ -569,10 +566,9 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): state, call, = self._blocking(request, timeout, metadata, credentials, - wait_for_ready, compression) + wait_for_ready) return _end_unary_response_blocking(state, call, True, None) def future(self, @@ -580,10 +576,9 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): state, operations, deadline, rendezvous = self._prepare( - request, timeout, metadata, wait_for_ready, compression) + request, timeout, metadata, wait_for_ready) if state is None: raise rendezvous # pylint: disable-msg=raising-bad-type else: @@ -609,14 +604,12 @@ class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable): self._response_deserializer = response_deserializer self._context = cygrpc.build_census_context() - def __call__( # pylint: disable=too-many-locals - self, - request, - timeout=None, - metadata=None, - credentials=None, - wait_for_ready=None, - compression=None): + def __call__(self, + request, + timeout=None, + metadata=None, + credentials=None, + wait_for_ready=None): deadline, serialized_request, rendezvous = _start_unary_request( request, timeout, self._request_serializer) initial_metadata_flags = _InitialMetadataFlags().with_wait_for_ready( @@ -624,12 +617,10 @@ class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable): if serialized_request is None: raise rendezvous # pylint: disable-msg=raising-bad-type else: - augmented_metadata = _compression.augment_metadata( - metadata, compression) state = _RPCState(_UNARY_STREAM_INITIAL_DUE, None, None, None, None) operationses = ( ( - cygrpc.SendInitialMetadataOperation(augmented_metadata, + cygrpc.SendInitialMetadataOperation(metadata, initial_metadata_flags), cygrpc.SendMessageOperation(serialized_request, _EMPTY_FLAGS), @@ -638,13 +629,12 @@ class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable): ), (cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),), ) + event_handler = _event_handler(state, self._response_deserializer) call = self._managed_call( cygrpc.PropagationConstants.GRPC_PROPAGATE_DEFAULTS, self._method, None, _determine_deadline(deadline), metadata, - None if credentials is None else - credentials._credentials, operationses, - _event_handler(state, - self._response_deserializer), self._context) + None if credentials is None else credentials._credentials, + operationses, event_handler, self._context) return _Rendezvous(state, call, self._response_deserializer, deadline) @@ -662,19 +652,18 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): self._context = cygrpc.build_census_context() def _blocking(self, request_iterator, timeout, metadata, credentials, - wait_for_ready, compression): + wait_for_ready): deadline = _deadline(timeout) state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None) initial_metadata_flags = _InitialMetadataFlags().with_wait_for_ready( wait_for_ready) - augmented_metadata = _compression.augment_metadata( - metadata, compression) + deadline_to_propagate = _determine_deadline(deadline) call = self._channel.segregated_call( cygrpc.PropagationConstants.GRPC_PROPAGATE_DEFAULTS, self._method, - None, _determine_deadline(deadline), augmented_metadata, None + None, deadline_to_propagate, metadata, None if credentials is None else credentials._credentials, _stream_unary_invocation_operationses_and_tags( - augmented_metadata, initial_metadata_flags), self._context) + metadata, initial_metadata_flags), self._context) _consume_request_iterator(request_iterator, state, call, self._request_serializer, None) while True: @@ -691,10 +680,9 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): state, call, = self._blocking(request_iterator, timeout, metadata, - credentials, wait_for_ready, compression) + credentials, wait_for_ready) return _end_unary_response_blocking(state, call, False, None) def with_call(self, @@ -702,10 +690,9 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): state, call, = self._blocking(request_iterator, timeout, metadata, - credentials, wait_for_ready, compression) + credentials, wait_for_ready) return _end_unary_response_blocking(state, call, True, None) def future(self, @@ -713,18 +700,15 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): deadline = _deadline(timeout) state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None) event_handler = _event_handler(state, self._response_deserializer) initial_metadata_flags = _InitialMetadataFlags().with_wait_for_ready( wait_for_ready) - augmented_metadata = _compression.augment_metadata( - metadata, compression) call = self._managed_call( cygrpc.PropagationConstants.GRPC_PROPAGATE_DEFAULTS, self._method, - None, deadline, augmented_metadata, None + None, deadline, metadata, None if credentials is None else credentials._credentials, _stream_unary_invocation_operationses( metadata, initial_metadata_flags), event_handler, self._context) @@ -750,26 +734,24 @@ class _StreamStreamMultiCallable(grpc.StreamStreamMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): deadline = _deadline(timeout) state = _RPCState(_STREAM_STREAM_INITIAL_DUE, None, None, None, None) initial_metadata_flags = _InitialMetadataFlags().with_wait_for_ready( wait_for_ready) - augmented_metadata = _compression.augment_metadata( - metadata, compression) operationses = ( ( - cygrpc.SendInitialMetadataOperation(augmented_metadata, + cygrpc.SendInitialMetadataOperation(metadata, initial_metadata_flags), cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS), ), (cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),), ) event_handler = _event_handler(state, self._response_deserializer) + deadline_to_propagate = _determine_deadline(deadline) call = self._managed_call( cygrpc.PropagationConstants.GRPC_PROPAGATE_DEFAULTS, self._method, - None, _determine_deadline(deadline), augmented_metadata, None + None, deadline_to_propagate, metadata, None if credentials is None else credentials._credentials, operationses, event_handler, self._context) _consume_request_iterator(request_iterator, state, call, @@ -1000,30 +982,28 @@ def _unsubscribe(state, callback): break -def _augment_options(base_options, compression): - compression_option = _compression.create_channel_option(compression) - return tuple(base_options) + compression_option + (( - cygrpc.ChannelArgKey.primary_user_agent_string, - _USER_AGENT, - ),) +def _options(options): + return list(options) + [ + ( + cygrpc.ChannelArgKey.primary_user_agent_string, + _USER_AGENT, + ), + ] class Channel(grpc.Channel): """A cygrpc.Channel-backed implementation of grpc.Channel.""" - def __init__(self, target, options, credentials, compression): + def __init__(self, target, options, credentials): """Constructor. Args: target: The target to which to connect. options: Configuration options for the channel. credentials: A cygrpc.ChannelCredentials or None. - compression: An optional value indicating the compression method to be - used over the lifetime of the channel. """ self._channel = cygrpc.Channel( - _common.encode(target), _augment_options(options, compression), - credentials) + _common.encode(target), _options(options), credentials) self._call_state = _ChannelCallState(self._channel) self._connectivity_state = _ChannelConnectivityState(self._channel) cygrpc.fork_register_channel(self) diff --git a/src/python/grpcio/grpc/_compression.py b/src/python/grpcio/grpc/_compression.py deleted file mode 100644 index 45339c3afe2..00000000000 --- a/src/python/grpcio/grpc/_compression.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright 2019 The gRPC authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from grpc._cython import cygrpc - -NoCompression = cygrpc.CompressionAlgorithm.none -Deflate = cygrpc.CompressionAlgorithm.deflate -Gzip = cygrpc.CompressionAlgorithm.gzip - -_METADATA_STRING_MAPPING = { - NoCompression: 'identity', - Deflate: 'deflate', - Gzip: 'gzip', -} - - -def _compression_algorithm_to_metadata_value(compression): - return _METADATA_STRING_MAPPING[compression] - - -def compression_algorithm_to_metadata(compression): - return (cygrpc.GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY, - _compression_algorithm_to_metadata_value(compression)) - - -def create_channel_option(compression): - return ((cygrpc.GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, - int(compression)),) if compression else () - - -def augment_metadata(metadata, compression): - if not metadata and not compression: - return None - base_metadata = tuple(metadata) if metadata else () - compression_metadata = ( - compression_algorithm_to_metadata(compression),) if compression else () - return base_metadata + compression_metadata - - -__all__ = ( - "NoCompression", - "Deflate", - "Gzip", -) diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi index 057d0776983..0a35002a9d4 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi @@ -140,8 +140,7 @@ cdef extern from "grpc/grpc.h": const char *GRPC_ARG_SECONDARY_USER_AGENT_STRING const char *GRPC_SSL_TARGET_NAME_OVERRIDE_ARG const char *GRPC_SSL_SESSION_CACHE_ARG - const char *_GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM \ - "GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM" + const char *GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM const char *GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL const char *GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET @@ -619,8 +618,3 @@ cdef extern from "grpc/compression.h": int grpc_compression_options_is_algorithm_enabled( const grpc_compression_options *opts, grpc_compression_algorithm algorithm) nogil - -cdef extern from "grpc/impl/codegen/compression_types.h": - - const char *_GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY \ - "GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY" diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi index 308d677695f..02c904b43fc 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi @@ -108,11 +108,6 @@ class OperationType: receive_status_on_client = GRPC_OP_RECV_STATUS_ON_CLIENT receive_close_on_server = GRPC_OP_RECV_CLOSE_ON_SERVER -GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM= ( - _GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM) - -GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY = ( - _GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY) class CompressionAlgorithm: none = GRPC_COMPRESS_NONE diff --git a/src/python/grpcio/grpc/_interceptor.py b/src/python/grpcio/grpc/_interceptor.py index 4ec2e6bb733..6c4e396ac23 100644 --- a/src/python/grpcio/grpc/_interceptor.py +++ b/src/python/grpcio/grpc/_interceptor.py @@ -44,9 +44,9 @@ def service_pipeline(interceptors): class _ClientCallDetails( - collections.namedtuple('_ClientCallDetails', - ('method', 'timeout', 'metadata', 'credentials', - 'wait_for_ready', 'compression')), + collections.namedtuple( + '_ClientCallDetails', + ('method', 'timeout', 'metadata', 'credentials', 'wait_for_ready')), grpc.ClientCallDetails): pass @@ -77,12 +77,7 @@ def _unwrap_client_call_details(call_details, default_details): except AttributeError: wait_for_ready = default_details.wait_for_ready - try: - compression = call_details.compression - except AttributeError: - compression = default_details.compression - - return method, timeout, metadata, credentials, wait_for_ready, compression + return method, timeout, metadata, credentials, wait_for_ready class _FailureOutcome(grpc.RpcError, grpc.Future, grpc.Call): # pylint: disable=too-many-ancestors @@ -211,15 +206,13 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): response, ignored_call = self._with_call( request, timeout=timeout, metadata=metadata, credentials=credentials, - wait_for_ready=wait_for_ready, - compression=compression) + wait_for_ready=wait_for_ready) return response def _with_call(self, @@ -227,25 +220,20 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): - client_call_details = _ClientCallDetails(self._method, timeout, - metadata, credentials, - wait_for_ready, compression) + wait_for_ready=None): + client_call_details = _ClientCallDetails( + self._method, timeout, metadata, credentials, wait_for_ready) def continuation(new_details, request): - (new_method, new_timeout, new_metadata, new_credentials, - new_wait_for_ready, - new_compression) = (_unwrap_client_call_details( - new_details, client_call_details)) + new_method, new_timeout, new_metadata, new_credentials, new_wait_for_ready = ( + _unwrap_client_call_details(new_details, client_call_details)) try: response, call = self._thunk(new_method).with_call( request, timeout=new_timeout, metadata=new_metadata, credentials=new_credentials, - wait_for_ready=new_wait_for_ready, - compression=new_compression) + wait_for_ready=new_wait_for_ready) return _UnaryOutcome(response, call) except grpc.RpcError as rpc_error: return rpc_error @@ -261,39 +249,32 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): return self._with_call( request, timeout=timeout, metadata=metadata, credentials=credentials, - wait_for_ready=wait_for_ready, - compression=compression) + wait_for_ready=wait_for_ready) def future(self, request, timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): - client_call_details = _ClientCallDetails(self._method, timeout, - metadata, credentials, - wait_for_ready, compression) + wait_for_ready=None): + client_call_details = _ClientCallDetails( + self._method, timeout, metadata, credentials, wait_for_ready) def continuation(new_details, request): - (new_method, new_timeout, new_metadata, new_credentials, - new_wait_for_ready, - new_compression) = (_unwrap_client_call_details( - new_details, client_call_details)) + new_method, new_timeout, new_metadata, new_credentials, new_wait_for_ready = ( + _unwrap_client_call_details(new_details, client_call_details)) return self._thunk(new_method).future( request, timeout=new_timeout, metadata=new_metadata, credentials=new_credentials, - wait_for_ready=new_wait_for_ready, - compression=new_compression) + wait_for_ready=new_wait_for_ready) try: return self._interceptor.intercept_unary_unary( @@ -314,24 +295,19 @@ class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): - client_call_details = _ClientCallDetails(self._method, timeout, - metadata, credentials, - wait_for_ready, compression) + wait_for_ready=None): + client_call_details = _ClientCallDetails( + self._method, timeout, metadata, credentials, wait_for_ready) def continuation(new_details, request): - (new_method, new_timeout, new_metadata, new_credentials, - new_wait_for_ready, - new_compression) = (_unwrap_client_call_details( - new_details, client_call_details)) + new_method, new_timeout, new_metadata, new_credentials, new_wait_for_ready = ( + _unwrap_client_call_details(new_details, client_call_details)) return self._thunk(new_method)( request, timeout=new_timeout, metadata=new_metadata, credentials=new_credentials, - wait_for_ready=new_wait_for_ready, - compression=new_compression) + wait_for_ready=new_wait_for_ready) try: return self._interceptor.intercept_unary_stream( @@ -352,15 +328,13 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): response, ignored_call = self._with_call( request_iterator, timeout=timeout, metadata=metadata, credentials=credentials, - wait_for_ready=wait_for_ready, - compression=compression) + wait_for_ready=wait_for_ready) return response def _with_call(self, @@ -368,25 +342,20 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): - client_call_details = _ClientCallDetails(self._method, timeout, - metadata, credentials, - wait_for_ready, compression) + wait_for_ready=None): + client_call_details = _ClientCallDetails( + self._method, timeout, metadata, credentials, wait_for_ready) def continuation(new_details, request_iterator): - (new_method, new_timeout, new_metadata, new_credentials, - new_wait_for_ready, - new_compression) = (_unwrap_client_call_details( - new_details, client_call_details)) + new_method, new_timeout, new_metadata, new_credentials, new_wait_for_ready = ( + _unwrap_client_call_details(new_details, client_call_details)) try: response, call = self._thunk(new_method).with_call( request_iterator, timeout=new_timeout, metadata=new_metadata, credentials=new_credentials, - wait_for_ready=new_wait_for_ready, - compression=new_compression) + wait_for_ready=new_wait_for_ready) return _UnaryOutcome(response, call) except grpc.RpcError as rpc_error: return rpc_error @@ -402,39 +371,32 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): + wait_for_ready=None): return self._with_call( request_iterator, timeout=timeout, metadata=metadata, credentials=credentials, - wait_for_ready=wait_for_ready, - compression=compression) + wait_for_ready=wait_for_ready) def future(self, request_iterator, timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): - client_call_details = _ClientCallDetails(self._method, timeout, - metadata, credentials, - wait_for_ready, compression) + wait_for_ready=None): + client_call_details = _ClientCallDetails( + self._method, timeout, metadata, credentials, wait_for_ready) def continuation(new_details, request_iterator): - (new_method, new_timeout, new_metadata, new_credentials, - new_wait_for_ready, - new_compression) = (_unwrap_client_call_details( - new_details, client_call_details)) + new_method, new_timeout, new_metadata, new_credentials, new_wait_for_ready = ( + _unwrap_client_call_details(new_details, client_call_details)) return self._thunk(new_method).future( request_iterator, timeout=new_timeout, metadata=new_metadata, credentials=new_credentials, - wait_for_ready=new_wait_for_ready, - compression=new_compression) + wait_for_ready=new_wait_for_ready) try: return self._interceptor.intercept_stream_unary( @@ -455,24 +417,19 @@ class _StreamStreamMultiCallable(grpc.StreamStreamMultiCallable): timeout=None, metadata=None, credentials=None, - wait_for_ready=None, - compression=None): - client_call_details = _ClientCallDetails(self._method, timeout, - metadata, credentials, - wait_for_ready, compression) + wait_for_ready=None): + client_call_details = _ClientCallDetails( + self._method, timeout, metadata, credentials, wait_for_ready) def continuation(new_details, request_iterator): - (new_method, new_timeout, new_metadata, new_credentials, - new_wait_for_ready, - new_compression) = (_unwrap_client_call_details( - new_details, client_call_details)) + new_method, new_timeout, new_metadata, new_credentials, new_wait_for_ready = ( + _unwrap_client_call_details(new_details, client_call_details)) return self._thunk(new_method)( request_iterator, timeout=new_timeout, metadata=new_metadata, credentials=new_credentials, - wait_for_ready=new_wait_for_ready, - compression=new_compression) + wait_for_ready=new_wait_for_ready) try: return self._interceptor.intercept_stream_stream( diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py index 370c81100af..90136aef3c2 100644 --- a/src/python/grpcio/grpc/_server.py +++ b/src/python/grpcio/grpc/_server.py @@ -24,7 +24,6 @@ import six import grpc from grpc import _common -from grpc import _compression from grpc import _interceptor from grpc._cython import cygrpc @@ -95,7 +94,6 @@ class _RPCState(object): self.request = None self.client = _OPEN self.initial_metadata_allowed = True - self.compression_algorithm = None self.disable_next_compression = False self.trailing_metadata = None self.code = None @@ -131,33 +129,13 @@ def _send_status_from_server(state, token): return send_status_from_server -def _get_initial_metadata(state, metadata): - with state.condition: - if state.compression_algorithm: - compression_metadata = ( - _compression.compression_algorithm_to_metadata( - state.compression_algorithm),) - if metadata is None: - return compression_metadata - else: - return compression_metadata + tuple(metadata) - else: - return metadata - - -def _get_initial_metadata_operation(state, metadata): - operation = cygrpc.SendInitialMetadataOperation( - _get_initial_metadata(state, metadata), _EMPTY_FLAGS) - return operation - - def _abort(state, call, code, details): if state.client is not _CANCELLED: effective_code = _abortion_code(state, code) effective_details = details if state.details is None else state.details if state.initial_metadata_allowed: operations = ( - _get_initial_metadata_operation(state, None), + cygrpc.SendInitialMetadataOperation(None, _EMPTY_FLAGS), cygrpc.SendStatusFromServerOperation( state.trailing_metadata, effective_code, effective_details, _EMPTY_FLAGS), @@ -281,18 +259,14 @@ class _Context(grpc.ServicerContext): cygrpc.auth_context(self._rpc_event.call)) } - def set_compression(self, compression): - with self._state.condition: - self._state.compression_algorithm = compression - def send_initial_metadata(self, initial_metadata): with self._state.condition: if self._state.client is _CANCELLED: _raise_rpc_error(self._state) else: if self._state.initial_metadata_allowed: - operation = _get_initial_metadata_operation( - self._state, initial_metadata) + operation = cygrpc.SendInitialMetadataOperation( + initial_metadata, _EMPTY_FLAGS) self._rpc_event.call.start_server_batch( (operation,), _send_initial_metadata(self._state)) self._state.initial_metadata_allowed = False @@ -426,13 +400,10 @@ def _call_behavior(rpc_event, with _create_servicer_context(rpc_event, state, request_deserializer) as context: try: - response_or_iterator = None if send_response_callback is not None: - response_or_iterator = behavior(argument, context, - send_response_callback) + return behavior(argument, context, send_response_callback), True else: - response_or_iterator = behavior(argument, context) - return response_or_iterator, True + return behavior(argument, context), True except Exception as exception: # pylint: disable=broad-except with state.condition: if state.aborted: @@ -476,18 +447,6 @@ def _serialize_response(rpc_event, state, response, response_serializer): return serialized_response -def _get_send_message_op_flags_from_state(state): - if state.disable_next_compression: - return cygrpc.WriteFlag.no_compress - else: - return _EMPTY_FLAGS - - -def _reset_per_message_state(state): - with state.condition: - state.disable_next_compression = False - - def _send_response(rpc_event, state, serialized_response): with state.condition: if not _is_rpc_state_active(state): @@ -495,22 +454,19 @@ def _send_response(rpc_event, state, serialized_response): else: if state.initial_metadata_allowed: operations = ( - _get_initial_metadata_operation(state, None), - cygrpc.SendMessageOperation( - serialized_response, - _get_send_message_op_flags_from_state(state)), + cygrpc.SendInitialMetadataOperation(None, _EMPTY_FLAGS), + cygrpc.SendMessageOperation(serialized_response, + _EMPTY_FLAGS), ) state.initial_metadata_allowed = False token = _SEND_INITIAL_METADATA_AND_SEND_MESSAGE_TOKEN else: operations = (cygrpc.SendMessageOperation( - serialized_response, - _get_send_message_op_flags_from_state(state)),) + serialized_response, _EMPTY_FLAGS),) token = _SEND_MESSAGE_TOKEN rpc_event.call.start_server_batch(operations, _send_message(state, token)) state.due.add(token) - _reset_per_message_state(state) while True: state.condition.wait() if token not in state.due: @@ -527,17 +483,16 @@ def _status(rpc_event, state, serialized_response): state.trailing_metadata, code, details, _EMPTY_FLAGS), ] if state.initial_metadata_allowed: - operations.append(_get_initial_metadata_operation(state, None)) + operations.append( + cygrpc.SendInitialMetadataOperation(None, _EMPTY_FLAGS)) if serialized_response is not None: operations.append( - cygrpc.SendMessageOperation( - serialized_response, - _get_send_message_op_flags_from_state(state))) + cygrpc.SendMessageOperation(serialized_response, + _EMPTY_FLAGS)) rpc_event.call.start_server_batch( operations, _send_status_from_server(state, _SEND_STATUS_FROM_SERVER_TOKEN)) state.statused = True - _reset_per_message_state(state) state.due.add(_SEND_STATUS_FROM_SERVER_TOKEN) @@ -684,13 +639,13 @@ def _find_method_handler(rpc_event, generic_handlers, interceptor_pipeline): def _reject_rpc(rpc_event, status, details): - rpc_state = _RPCState() operations = ( - _get_initial_metadata_operation(rpc_state, None), + cygrpc.SendInitialMetadataOperation(None, _EMPTY_FLAGS), cygrpc.ReceiveCloseOnServerOperation(_EMPTY_FLAGS), cygrpc.SendStatusFromServerOperation(None, status, details, _EMPTY_FLAGS), ) + rpc_state = _RPCState() rpc_event.call.start_server_batch(operations, lambda ignored_event: (rpc_state, (),)) return rpc_state @@ -928,18 +883,13 @@ def _validate_generic_rpc_handlers(generic_rpc_handlers): 'not have "service" method!'.format(generic_rpc_handler)) -def _augment_options(base_options, compression): - compression_option = _compression.create_channel_option(compression) - return tuple(base_options) + compression_option - - class _Server(grpc.Server): # pylint: disable=too-many-arguments def __init__(self, thread_pool, generic_handlers, interceptors, options, - maximum_concurrent_rpcs, compression): + maximum_concurrent_rpcs): completion_queue = cygrpc.CompletionQueue() - server = cygrpc.Server(_augment_options(options, compression)) + server = cygrpc.Server(options) server.register_completion_queue(completion_queue) self._state = _ServerState(completion_queue, server, generic_handlers, _interceptor.service_pipeline(interceptors), @@ -970,7 +920,7 @@ class _Server(grpc.Server): def create_server(thread_pool, generic_rpc_handlers, interceptors, options, - maximum_concurrent_rpcs, compression): + maximum_concurrent_rpcs): _validate_generic_rpc_handlers(generic_rpc_handlers) return _Server(thread_pool, generic_rpc_handlers, interceptors, options, - maximum_concurrent_rpcs, compression) + maximum_concurrent_rpcs) diff --git a/src/python/grpcio_testing/grpc_testing/_server/_servicer_context.py b/src/python/grpcio_testing/grpc_testing/_server/_servicer_context.py index 63a1b1aec95..5b1dfeacdf5 100644 --- a/src/python/grpcio_testing/grpc_testing/_server/_servicer_context.py +++ b/src/python/grpcio_testing/grpc_testing/_server/_servicer_context.py @@ -56,9 +56,6 @@ class ServicerContext(grpc.ServicerContext): def auth_context(self): raise NotImplementedError() - def set_compression(self): - raise NotImplementedError() - def send_initial_metadata(self, initial_metadata): initial_metadata_sent = self._rpc.send_initial_metadata( _common.fuss_with_metadata(initial_metadata)) @@ -66,9 +63,6 @@ class ServicerContext(grpc.ServicerContext): raise ValueError( 'ServicerContext.send_initial_metadata called too late!') - def disable_next_message_compression(self): - raise NotImplementedError() - def set_trailing_metadata(self, trailing_metadata): self._rpc.set_trailing_metadata( _common.fuss_with_metadata(trailing_metadata)) diff --git a/src/python/grpcio_tests/commands.py b/src/python/grpcio_tests/commands.py index e9b6333c891..7a441feb84e 100644 --- a/src/python/grpcio_tests/commands.py +++ b/src/python/grpcio_tests/commands.py @@ -117,7 +117,6 @@ class TestGevent(setuptools.Command): # eventually succeed, but need to dig into performance issues. 'unit._cython._no_messages_server_completion_queue_per_call_test.Test.test_rpcs', 'unit._cython._no_messages_single_server_completion_queue_test.Test.test_rpcs', - 'unit._compression_test', # TODO(https://github.com/grpc/grpc/issues/16890) enable this test 'unit._cython._channel_test.ChannelTest.test_multiple_channels_lonely_connectivity', # I have no idea why this doesn't work in gevent, but it shouldn't even be diff --git a/src/python/grpcio_tests/tests/unit/BUILD.bazel b/src/python/grpcio_tests/tests/unit/BUILD.bazel index 04f91e63a18..54b3c9b6f6a 100644 --- a/src/python/grpcio_tests/tests/unit/BUILD.bazel +++ b/src/python/grpcio_tests/tests/unit/BUILD.bazel @@ -33,11 +33,6 @@ GRPCIO_TESTS_UNIT = [ "_session_cache_test.py", ] -py_library( - name = "_tcp_proxy", - srcs = ["_tcp_proxy.py"], -) - py_library( name = "resources", srcs = ["resources.py"], @@ -85,7 +80,6 @@ py_library( ":_exit_scenarios", ":_server_shutdown_scenarios", ":_from_grpc_import_star", - ":_tcp_proxy", "//src/python/grpcio_tests/tests/unit/framework/common", "//src/python/grpcio_tests/tests/testing", requirement('six'), diff --git a/src/python/grpcio_tests/tests/unit/_api_test.py b/src/python/grpcio_tests/tests/unit/_api_test.py index 127dab336bf..0dc6a8718c3 100644 --- a/src/python/grpcio_tests/tests/unit/_api_test.py +++ b/src/python/grpcio_tests/tests/unit/_api_test.py @@ -31,7 +31,6 @@ class AllTest(unittest.TestCase): 'FutureCancelledError', 'Future', 'ChannelConnectivity', - 'Compression', 'StatusCode', 'Status', 'RpcError', diff --git a/src/python/grpcio_tests/tests/unit/_compression_test.py b/src/python/grpcio_tests/tests/unit/_compression_test.py index 66f9f0ae40f..87884a19dc0 100644 --- a/src/python/grpcio_tests/tests/unit/_compression_test.py +++ b/src/python/grpcio_tests/tests/unit/_compression_test.py @@ -13,130 +13,37 @@ # limitations under the License. """Tests server and client side compression.""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - import unittest -import contextlib -from concurrent import futures -import functools -import itertools import logging -import os - import grpc from grpc import _grpcio_metadata from tests.unit import test_common from tests.unit.framework.common import test_constants -from tests.unit import _tcp_proxy _UNARY_UNARY = '/test/UnaryUnary' -_UNARY_STREAM = '/test/UnaryStream' -_STREAM_UNARY = '/test/StreamUnary' _STREAM_STREAM = '/test/StreamStream' -# Cut down on test time. -_STREAM_LENGTH = test_constants.STREAM_LENGTH // 8 -_HOST = 'localhost' - -_REQUEST = b'\x00' * 100 -_COMPRESSION_RATIO_THRESHOLD = 0.1 -_COMPRESSION_METHODS = ( - None, - # Disabled for test tractability. - # grpc.Compression.NoCompression, - grpc.Compression.Deflate, - grpc.Compression.Gzip, -) -_COMPRESSION_NAMES = { - None: 'Uncompressed', - grpc.Compression.NoCompression: 'NoCompression', - grpc.Compression.Deflate: 'DeflateCompression', - grpc.Compression.Gzip: 'GzipCompression', -} - -_TEST_OPTIONS = { - 'client_streaming': (True, False), - 'server_streaming': (True, False), - 'channel_compression': _COMPRESSION_METHODS, - 'multicallable_compression': _COMPRESSION_METHODS, - 'server_compression': _COMPRESSION_METHODS, - 'server_call_compression': _COMPRESSION_METHODS, -} +def handle_unary(request, servicer_context): + servicer_context.send_initial_metadata([('grpc-internal-encoding-request', + 'gzip')]) + return request -def _make_handle_unary_unary(pre_response_callback): - - def _handle_unary(request, servicer_context): - if pre_response_callback: - pre_response_callback(request, servicer_context) - return request - - return _handle_unary - - -def _make_handle_unary_stream(pre_response_callback): - - def _handle_unary_stream(request, servicer_context): - if pre_response_callback: - pre_response_callback(request, servicer_context) - for _ in range(_STREAM_LENGTH): - yield request - - return _handle_unary_stream - - -def _make_handle_stream_unary(pre_response_callback): - - def _handle_stream_unary(request_iterator, servicer_context): - if pre_response_callback: - pre_response_callback(request_iterator, servicer_context) - response = None - for request in request_iterator: - if not response: - response = request - return response - - return _handle_stream_unary - - -def _make_handle_stream_stream(pre_response_callback): - - def _handle_stream(request_iterator, servicer_context): - # TODO(issue:#6891) We should be able to remove this loop, - # and replace with return; yield - for request in request_iterator: - if pre_response_callback: - pre_response_callback(request, servicer_context) - yield request - - return _handle_stream - - -def set_call_compression(compression_method, request_or_iterator, - servicer_context): - del request_or_iterator - servicer_context.set_compression(compression_method) - - -def disable_next_compression(request, servicer_context): - del request - servicer_context.disable_next_message_compression() - - -def disable_first_compression(request, servicer_context): - if int(request.decode('ascii')) == 0: - servicer_context.disable_next_message_compression() +def handle_stream(request_iterator, servicer_context): + # TODO(issue:#6891) We should be able to remove this loop, + # and replace with return; yield + servicer_context.send_initial_metadata([('grpc-internal-encoding-request', + 'gzip')]) + for request in request_iterator: + yield request class _MethodHandler(grpc.RpcMethodHandler): - def __init__(self, request_streaming, response_streaming, - pre_response_callback): + def __init__(self, request_streaming, response_streaming): self.request_streaming = request_streaming self.response_streaming = response_streaming self.request_deserializer = None @@ -145,239 +52,75 @@ class _MethodHandler(grpc.RpcMethodHandler): self.unary_stream = None self.stream_unary = None self.stream_stream = None - if self.request_streaming and self.response_streaming: - self.stream_stream = _make_handle_stream_stream( - pre_response_callback) + self.stream_stream = handle_stream elif not self.request_streaming and not self.response_streaming: - self.unary_unary = _make_handle_unary_unary(pre_response_callback) - elif not self.request_streaming and self.response_streaming: - self.unary_stream = _make_handle_unary_stream(pre_response_callback) - else: - self.stream_unary = _make_handle_stream_unary(pre_response_callback) + self.unary_unary = handle_unary class _GenericHandler(grpc.GenericRpcHandler): - def __init__(self, pre_response_callback): - self._pre_response_callback = pre_response_callback - def service(self, handler_call_details): if handler_call_details.method == _UNARY_UNARY: - return _MethodHandler(False, False, self._pre_response_callback) - elif handler_call_details.method == _UNARY_STREAM: - return _MethodHandler(False, True, self._pre_response_callback) - elif handler_call_details.method == _STREAM_UNARY: - return _MethodHandler(True, False, self._pre_response_callback) + return _MethodHandler(False, False) elif handler_call_details.method == _STREAM_STREAM: - return _MethodHandler(True, True, self._pre_response_callback) + return _MethodHandler(True, True) else: return None -@contextlib.contextmanager -def _instrumented_client_server_pair(channel_kwargs, server_kwargs, - server_handler): - server = grpc.server(futures.ThreadPoolExecutor(), **server_kwargs) - server.add_generic_rpc_handlers((server_handler,)) - server_port = server.add_insecure_port('{}:0'.format(_HOST)) - server.start() - with _tcp_proxy.TcpProxy(_HOST, _HOST, server_port) as proxy: - proxy_port = proxy.get_port() - with grpc.insecure_channel('{}:{}'.format(_HOST, proxy_port), - **channel_kwargs) as client_channel: - try: - yield client_channel, proxy, server - finally: - server.stop(None) - - -def _get_byte_counts(channel_kwargs, multicallable_kwargs, client_function, - server_kwargs, server_handler, message): - with _instrumented_client_server_pair(channel_kwargs, server_kwargs, - server_handler) as pipeline: - client_channel, proxy, server = pipeline - client_function(client_channel, multicallable_kwargs, message) - return proxy.get_byte_count() - - -def _get_compression_ratios(client_function, first_channel_kwargs, - first_multicallable_kwargs, first_server_kwargs, - first_server_handler, second_channel_kwargs, - second_multicallable_kwargs, second_server_kwargs, - second_server_handler, message): - try: - # This test requires the byte length of each connection to be deterministic. As - # it turns out, flow control puts bytes on the wire in a nondeterministic - # manner. We disable it here in order to measure compression ratios - # deterministically. - os.environ['GRPC_EXPERIMENTAL_DISABLE_FLOW_CONTROL'] = 'true' - first_bytes_sent, first_bytes_received = _get_byte_counts( - first_channel_kwargs, first_multicallable_kwargs, client_function, - first_server_kwargs, first_server_handler, message) - second_bytes_sent, second_bytes_received = _get_byte_counts( - second_channel_kwargs, second_multicallable_kwargs, client_function, - second_server_kwargs, second_server_handler, message) - return (( - second_bytes_sent - first_bytes_sent) / float(first_bytes_sent), - (second_bytes_received - first_bytes_received) / - float(first_bytes_received)) - finally: - del os.environ['GRPC_EXPERIMENTAL_DISABLE_FLOW_CONTROL'] - - -def _unary_unary_client(channel, multicallable_kwargs, message): - multi_callable = channel.unary_unary(_UNARY_UNARY) - response = multi_callable(message, **multicallable_kwargs) - if response != message: - raise RuntimeError("Request '{}' != Response '{}'".format( - message, response)) - - -def _unary_stream_client(channel, multicallable_kwargs, message): - multi_callable = channel.unary_stream(_UNARY_STREAM) - response_iterator = multi_callable(message, **multicallable_kwargs) - for response in response_iterator: - if response != message: - raise RuntimeError("Request '{}' != Response '{}'".format( - message, response)) - - -def _stream_unary_client(channel, multicallable_kwargs, message): - multi_callable = channel.stream_unary(_STREAM_UNARY) - requests = (_REQUEST for _ in range(_STREAM_LENGTH)) - response = multi_callable(requests, **multicallable_kwargs) - if response != message: - raise RuntimeError("Request '{}' != Response '{}'".format( - message, response)) - - -def _stream_stream_client(channel, multicallable_kwargs, message): - multi_callable = channel.stream_stream(_STREAM_STREAM) - request_prefix = str(0).encode('ascii') * 100 - requests = ( - request_prefix + str(i).encode('ascii') for i in range(_STREAM_LENGTH)) - response_iterator = multi_callable(requests, **multicallable_kwargs) - for i, response in enumerate(response_iterator): - if int(response.decode('ascii')) != i: - raise RuntimeError("Request '{}' != Response '{}'".format( - i, response)) - - class CompressionTest(unittest.TestCase): - def assertCompressed(self, compression_ratio): - self.assertLess( - compression_ratio, - -1.0 * _COMPRESSION_RATIO_THRESHOLD, - msg='Actual compression ratio: {}'.format(compression_ratio)) + def setUp(self): + self._server = test_common.test_server() + self._server.add_generic_rpc_handlers((_GenericHandler(),)) + self._port = self._server.add_insecure_port('[::]:0') + self._server.start() - def assertNotCompressed(self, compression_ratio): - self.assertGreaterEqual( - compression_ratio, - -1.0 * _COMPRESSION_RATIO_THRESHOLD, - msg='Actual compession ratio: {}'.format(compression_ratio)) + def tearDown(self): + self._server.stop(None) - def assertConfigurationCompressed( - self, client_streaming, server_streaming, channel_compression, - multicallable_compression, server_compression, - server_call_compression): - client_side_compressed = channel_compression or multicallable_compression - server_side_compressed = server_compression or server_call_compression - channel_kwargs = { - 'compression': channel_compression, - } if channel_compression else {} - multicallable_kwargs = { - 'compression': multicallable_compression, - } if multicallable_compression else {} + def testUnary(self): + request = b'\x00' * 100 - client_function = None - if not client_streaming and not server_streaming: - client_function = _unary_unary_client - elif not client_streaming and server_streaming: - client_function = _unary_stream_client - elif client_streaming and not server_streaming: - client_function = _stream_unary_client - else: - client_function = _stream_stream_client + # Client -> server compressed through default client channel compression + # settings. Server -> client compressed via server-side metadata setting. + # TODO(https://github.com/grpc/grpc/issues/4078): replace the "1" integer + # literal with proper use of the public API. + compressed_channel = grpc.insecure_channel( + 'localhost:%d' % self._port, + options=[('grpc.default_compression_algorithm', 1)]) + multi_callable = compressed_channel.unary_unary(_UNARY_UNARY) + response = multi_callable(request) + self.assertEqual(request, response) - server_kwargs = { - 'compression': server_compression, - } if server_compression else {} - server_handler = _GenericHandler( - functools.partial(set_call_compression, grpc.Compression.Gzip) - ) if server_call_compression else _GenericHandler(None) - sent_ratio, received_ratio = _get_compression_ratios( - client_function, {}, {}, {}, _GenericHandler(None), channel_kwargs, - multicallable_kwargs, server_kwargs, server_handler, _REQUEST) + # Client -> server compressed through client metadata setting. Server -> + # client compressed via server-side metadata setting. + # TODO(https://github.com/grpc/grpc/issues/4078): replace the "0" integer + # literal with proper use of the public API. + uncompressed_channel = grpc.insecure_channel( + 'localhost:%d' % self._port, + options=[('grpc.default_compression_algorithm', 0)]) + multi_callable = compressed_channel.unary_unary(_UNARY_UNARY) + response = multi_callable( + request, metadata=[('grpc-internal-encoding-request', 'gzip')]) + self.assertEqual(request, response) + compressed_channel.close() - if client_side_compressed: - self.assertCompressed(sent_ratio) - else: - self.assertNotCompressed(sent_ratio) + def testStreaming(self): + request = b'\x00' * 100 - if server_side_compressed: - self.assertCompressed(received_ratio) - else: - self.assertNotCompressed(received_ratio) + # TODO(https://github.com/grpc/grpc/issues/4078): replace the "1" integer + # literal with proper use of the public API. + compressed_channel = grpc.insecure_channel( + 'localhost:%d' % self._port, + options=[('grpc.default_compression_algorithm', 1)]) + multi_callable = compressed_channel.stream_stream(_STREAM_STREAM) + call = multi_callable(iter([request] * test_constants.STREAM_LENGTH)) + for response in call: + self.assertEqual(request, response) + compressed_channel.close() - def testDisableNextCompressionStreaming(self): - server_kwargs = { - 'compression': grpc.Compression.Deflate, - } - _, received_ratio = _get_compression_ratios( - _stream_stream_client, {}, {}, {}, _GenericHandler(None), {}, {}, - server_kwargs, _GenericHandler(disable_next_compression), _REQUEST) - self.assertNotCompressed(received_ratio) - - def testDisableNextCompressionStreamingResets(self): - server_kwargs = { - 'compression': grpc.Compression.Deflate, - } - _, received_ratio = _get_compression_ratios( - _stream_stream_client, {}, {}, {}, _GenericHandler(None), {}, {}, - server_kwargs, _GenericHandler(disable_first_compression), _REQUEST) - self.assertCompressed(received_ratio) - - -def _get_compression_str(name, value): - return '{}{}'.format(name, _COMPRESSION_NAMES[value]) - - -def _get_compression_test_name(client_streaming, server_streaming, - channel_compression, multicallable_compression, - server_compression, server_call_compression): - client_arity = 'Stream' if client_streaming else 'Unary' - server_arity = 'Stream' if server_streaming else 'Unary' - arity = '{}{}'.format(client_arity, server_arity) - channel_compression_str = _get_compression_str('Channel', - channel_compression) - multicallable_compression_str = _get_compression_str( - 'Multicallable', multicallable_compression) - server_compression_str = _get_compression_str('Server', server_compression) - server_call_compression_str = _get_compression_str('ServerCall', - server_call_compression) - return 'test{}{}{}{}{}'.format( - arity, channel_compression_str, multicallable_compression_str, - server_compression_str, server_call_compression_str) - - -def _test_options(): - for test_parameters in itertools.product(*_TEST_OPTIONS.values()): - yield dict(zip(_TEST_OPTIONS.keys(), test_parameters)) - - -for options in _test_options(): - - def test_compression(**kwargs): - - def _test_compression(self): - self.assertConfigurationCompressed(**kwargs) - - return _test_compression - - setattr(CompressionTest, _get_compression_test_name(**options), - test_compression(**options)) if __name__ == '__main__': logging.basicConfig() diff --git a/src/python/grpcio_tests/tests/unit/_tcp_proxy.py b/src/python/grpcio_tests/tests/unit/_tcp_proxy.py deleted file mode 100644 index 5ad0bf8f028..00000000000 --- a/src/python/grpcio_tests/tests/unit/_tcp_proxy.py +++ /dev/null @@ -1,164 +0,0 @@ -# Copyright 2019 the gRPC authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" Proxies a TCP connection between a single client-server pair. - -This proxy is not suitable for production, but should work well for cases in -which a test needs to spy on the bytes put on the wire between a server and -a client. -""" - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import datetime -import select -import socket -import threading - -_TCP_PROXY_BUFFER_SIZE = 1024 -_TCP_PROXY_TIMEOUT = datetime.timedelta(milliseconds=500) - - -def _create_socket_ipv6(bind_address): - listen_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) - listen_socket.bind((bind_address, 0, 0, 0)) - return listen_socket - - -def _create_socket_ipv4(bind_address): - listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - listen_socket.bind((bind_address, 0)) - return listen_socket - - -def _init_listen_socket(bind_address): - listen_socket = None - if socket.has_ipv6: - try: - listen_socket = _create_socket_ipv6(bind_address) - except socket.error: - listen_socket = _create_socket_ipv4(bind_address) - else: - listen_socket = _create_socket_ipv4(bind_address) - listen_socket.listen(1) - return listen_socket, listen_socket.getsockname()[1] - - -def _init_proxy_socket(gateway_address, gateway_port): - proxy_socket = socket.create_connection((gateway_address, gateway_port)) - return proxy_socket - - -class TcpProxy(object): - """Proxies a TCP connection between one client and one server.""" - - def __init__(self, bind_address, gateway_address, gateway_port): - self._bind_address = bind_address - self._gateway_address = gateway_address - self._gateway_port = gateway_port - - self._byte_count_lock = threading.RLock() - self._sent_byte_count = 0 - self._received_byte_count = 0 - - self._stop_event = threading.Event() - - self._port = None - self._listen_socket = None - self._proxy_socket = None - - # The following three attributes are owned by the serving thread. - self._northbound_data = b"" - self._southbound_data = b"" - self._client_sockets = [] - - self._thread = threading.Thread(target=self._run_proxy) - - def start(self): - self._listen_socket, self._port = _init_listen_socket( - self._bind_address) - self._proxy_socket = _init_proxy_socket(self._gateway_address, - self._gateway_port) - self._thread.start() - - def get_port(self): - return self._port - - def _handle_reads(self, sockets_to_read): - for socket_to_read in sockets_to_read: - if socket_to_read is self._listen_socket: - client_socket, client_address = socket_to_read.accept() - self._client_sockets.append(client_socket) - elif socket_to_read is self._proxy_socket: - data = socket_to_read.recv(_TCP_PROXY_BUFFER_SIZE) - with self._byte_count_lock: - self._received_byte_count += len(data) - self._northbound_data += data - elif socket_to_read in self._client_sockets: - data = socket_to_read.recv(_TCP_PROXY_BUFFER_SIZE) - if data: - with self._byte_count_lock: - self._sent_byte_count += len(data) - self._southbound_data += data - else: - self._client_sockets.remove(socket_to_read) - else: - raise RuntimeError('Unidentified socket appeared in read set.') - - def _handle_writes(self, sockets_to_write): - for socket_to_write in sockets_to_write: - if socket_to_write is self._proxy_socket: - if self._southbound_data: - self._proxy_socket.sendall(self._southbound_data) - self._southbound_data = b"" - elif socket_to_write in self._client_sockets: - if self._northbound_data: - socket_to_write.sendall(self._northbound_data) - self._northbound_data = b"" - - def _run_proxy(self): - while not self._stop_event.is_set(): - expected_reads = (self._listen_socket, self._proxy_socket) + tuple( - self._client_sockets) - expected_writes = expected_reads - sockets_to_read, sockets_to_write, _ = select.select( - expected_reads, expected_writes, (), - _TCP_PROXY_TIMEOUT.total_seconds()) - self._handle_reads(sockets_to_read) - self._handle_writes(sockets_to_write) - for client_socket in self._client_sockets: - client_socket.close() - - def stop(self): - self._stop_event.set() - self._thread.join() - self._listen_socket.close() - self._proxy_socket.close() - - def get_byte_count(self): - with self._byte_count_lock: - return self._sent_byte_count, self._received_byte_count - - def reset_byte_count(self): - with self._byte_count_lock: - self._byte_count = 0 - self._received_byte_count = 0 - - def __enter__(self): - self.start() - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self.stop()