diff options
111 files changed, 1920 insertions, 659 deletions
@@ -198,6 +198,7 @@ cc_library( "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", "src/core/lib/channel/subchannel_call_holder.h", + "src/core/lib/client_config/client_channel_factory.h", "src/core/lib/client_config/client_config.h", "src/core/lib/client_config/connector.h", "src/core/lib/client_config/initial_connect_string.h", @@ -208,7 +209,6 @@ cc_library( "src/core/lib/client_config/resolver_factory.h", "src/core/lib/client_config/resolver_registry.h", "src/core/lib/client_config/subchannel.h", - "src/core/lib/client_config/subchannel_factory.h", "src/core/lib/client_config/subchannel_index.h", "src/core/lib/client_config/uri_parser.h", "src/core/lib/compression/algorithm_metadata.h", @@ -339,6 +339,7 @@ cc_library( "src/core/lib/channel/http_client_filter.c", "src/core/lib/channel/http_server_filter.c", "src/core/lib/channel/subchannel_call_holder.c", + "src/core/lib/client_config/client_channel_factory.c", "src/core/lib/client_config/client_config.c", "src/core/lib/client_config/connector.c", "src/core/lib/client_config/default_initial_connect_string.c", @@ -350,7 +351,6 @@ cc_library( "src/core/lib/client_config/resolver_factory.c", "src/core/lib/client_config/resolver_registry.c", "src/core/lib/client_config/subchannel.c", - "src/core/lib/client_config/subchannel_factory.c", "src/core/lib/client_config/subchannel_index.c", "src/core/lib/client_config/uri_parser.c", "src/core/lib/compression/compression_algorithm.c", @@ -561,6 +561,7 @@ cc_library( "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", "src/core/lib/channel/subchannel_call_holder.h", + "src/core/lib/client_config/client_channel_factory.h", "src/core/lib/client_config/client_config.h", "src/core/lib/client_config/connector.h", "src/core/lib/client_config/initial_connect_string.h", @@ -571,7 +572,6 @@ cc_library( "src/core/lib/client_config/resolver_factory.h", "src/core/lib/client_config/resolver_registry.h", "src/core/lib/client_config/subchannel.h", - "src/core/lib/client_config/subchannel_factory.h", "src/core/lib/client_config/subchannel_index.h", "src/core/lib/client_config/uri_parser.h", "src/core/lib/compression/algorithm_metadata.h", @@ -686,6 +686,7 @@ cc_library( "src/core/lib/channel/http_client_filter.c", "src/core/lib/channel/http_server_filter.c", "src/core/lib/channel/subchannel_call_holder.c", + "src/core/lib/client_config/client_channel_factory.c", "src/core/lib/client_config/client_config.c", "src/core/lib/client_config/connector.c", "src/core/lib/client_config/default_initial_connect_string.c", @@ -697,7 +698,6 @@ cc_library( "src/core/lib/client_config/resolver_factory.c", "src/core/lib/client_config/resolver_registry.c", "src/core/lib/client_config/subchannel.c", - "src/core/lib/client_config/subchannel_factory.c", "src/core/lib/client_config/subchannel_index.c", "src/core/lib/client_config/uri_parser.c", "src/core/lib/compression/compression_algorithm.c", @@ -1393,6 +1393,7 @@ objc_library( "src/core/lib/channel/http_client_filter.c", "src/core/lib/channel/http_server_filter.c", "src/core/lib/channel/subchannel_call_holder.c", + "src/core/lib/client_config/client_channel_factory.c", "src/core/lib/client_config/client_config.c", "src/core/lib/client_config/connector.c", "src/core/lib/client_config/default_initial_connect_string.c", @@ -1404,7 +1405,6 @@ objc_library( "src/core/lib/client_config/resolver_factory.c", "src/core/lib/client_config/resolver_registry.c", "src/core/lib/client_config/subchannel.c", - "src/core/lib/client_config/subchannel_factory.c", "src/core/lib/client_config/subchannel_index.c", "src/core/lib/client_config/uri_parser.c", "src/core/lib/compression/compression_algorithm.c", @@ -1557,6 +1557,7 @@ objc_library( "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", "src/core/lib/channel/subchannel_call_holder.h", + "src/core/lib/client_config/client_channel_factory.h", "src/core/lib/client_config/client_config.h", "src/core/lib/client_config/connector.h", "src/core/lib/client_config/initial_connect_string.h", @@ -1567,7 +1568,6 @@ objc_library( "src/core/lib/client_config/resolver_factory.h", "src/core/lib/client_config/resolver_registry.h", "src/core/lib/client_config/subchannel.h", - "src/core/lib/client_config/subchannel_factory.h", "src/core/lib/client_config/subchannel_index.h", "src/core/lib/client_config/uri_parser.h", "src/core/lib/compression/algorithm_metadata.h", @@ -2487,6 +2487,7 @@ LIBGRPC_SRC = \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ src/core/lib/channel/subchannel_call_holder.c \ + src/core/lib/client_config/client_channel_factory.c \ src/core/lib/client_config/client_config.c \ src/core/lib/client_config/connector.c \ src/core/lib/client_config/default_initial_connect_string.c \ @@ -2498,7 +2499,6 @@ LIBGRPC_SRC = \ src/core/lib/client_config/resolver_factory.c \ src/core/lib/client_config/resolver_registry.c \ src/core/lib/client_config/subchannel.c \ - src/core/lib/client_config/subchannel_factory.c \ src/core/lib/client_config/subchannel_index.c \ src/core/lib/client_config/uri_parser.c \ src/core/lib/compression/compression_algorithm.c \ @@ -2844,6 +2844,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ src/core/lib/channel/subchannel_call_holder.c \ + src/core/lib/client_config/client_channel_factory.c \ src/core/lib/client_config/client_config.c \ src/core/lib/client_config/connector.c \ src/core/lib/client_config/default_initial_connect_string.c \ @@ -2855,7 +2856,6 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/client_config/resolver_factory.c \ src/core/lib/client_config/resolver_registry.c \ src/core/lib/client_config/subchannel.c \ - src/core/lib/client_config/subchannel_factory.c \ src/core/lib/client_config/subchannel_index.c \ src/core/lib/client_config/uri_parser.c \ src/core/lib/compression/compression_algorithm.c \ @@ -5,7 +5,7 @@ [![Join the chat at https://gitter.im/grpc/grpc](https://badges.gitter.im/grpc/grpc.svg)](https://gitter.im/grpc/grpc?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -Copyright 2015-2016 Google Inc. +Copyright 2015 Google Inc. #Documentation diff --git a/binding.gyp b/binding.gyp index 8b987fefa8..8b53b43686 100644 --- a/binding.gyp +++ b/binding.gyp @@ -607,6 +607,7 @@ 'src/core/lib/channel/http_client_filter.c', 'src/core/lib/channel/http_server_filter.c', 'src/core/lib/channel/subchannel_call_holder.c', + 'src/core/lib/client_config/client_channel_factory.c', 'src/core/lib/client_config/client_config.c', 'src/core/lib/client_config/connector.c', 'src/core/lib/client_config/default_initial_connect_string.c', @@ -618,7 +619,6 @@ 'src/core/lib/client_config/resolver_factory.c', 'src/core/lib/client_config/resolver_registry.c', 'src/core/lib/client_config/subchannel.c', - 'src/core/lib/client_config/subchannel_factory.c', 'src/core/lib/client_config/subchannel_index.c', 'src/core/lib/client_config/uri_parser.c', 'src/core/lib/compression/compression_algorithm.c', diff --git a/build.yaml b/build.yaml index 0a71cf715d..459defd171 100644 --- a/build.yaml +++ b/build.yaml @@ -264,6 +264,7 @@ filegroups: - src/core/lib/channel/http_client_filter.h - src/core/lib/channel/http_server_filter.h - src/core/lib/channel/subchannel_call_holder.h + - src/core/lib/client_config/client_channel_factory.h - src/core/lib/client_config/client_config.h - src/core/lib/client_config/connector.h - src/core/lib/client_config/initial_connect_string.h @@ -274,7 +275,6 @@ filegroups: - src/core/lib/client_config/resolver_factory.h - src/core/lib/client_config/resolver_registry.h - src/core/lib/client_config/subchannel.h - - src/core/lib/client_config/subchannel_factory.h - src/core/lib/client_config/subchannel_index.h - src/core/lib/client_config/uri_parser.h - src/core/lib/compression/algorithm_metadata.h @@ -352,6 +352,7 @@ filegroups: - src/core/lib/channel/http_client_filter.c - src/core/lib/channel/http_server_filter.c - src/core/lib/channel/subchannel_call_holder.c + - src/core/lib/client_config/client_channel_factory.c - src/core/lib/client_config/client_config.c - src/core/lib/client_config/connector.c - src/core/lib/client_config/default_initial_connect_string.c @@ -363,7 +364,6 @@ filegroups: - src/core/lib/client_config/resolver_factory.c - src/core/lib/client_config/resolver_registry.c - src/core/lib/client_config/subchannel.c - - src/core/lib/client_config/subchannel_factory.c - src/core/lib/client_config/subchannel_index.c - src/core/lib/client_config/uri_parser.c - src/core/lib/compression/compression_algorithm.c @@ -129,6 +129,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ src/core/lib/channel/subchannel_call_holder.c \ + src/core/lib/client_config/client_channel_factory.c \ src/core/lib/client_config/client_config.c \ src/core/lib/client_config/connector.c \ src/core/lib/client_config/default_initial_connect_string.c \ @@ -140,7 +141,6 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/client_config/resolver_factory.c \ src/core/lib/client_config/resolver_registry.c \ src/core/lib/client_config/subchannel.c \ - src/core/lib/client_config/subchannel_factory.c \ src/core/lib/client_config/subchannel_index.c \ src/core/lib/client_config/uri_parser.c \ src/core/lib/compression/compression_algorithm.c \ diff --git a/gRPC.podspec b/gRPC.podspec index 7e0e44f3dd..06eee01a90 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -200,6 +200,7 @@ Pod::Spec.new do |s| 'src/core/lib/channel/http_client_filter.h', 'src/core/lib/channel/http_server_filter.h', 'src/core/lib/channel/subchannel_call_holder.h', + 'src/core/lib/client_config/client_channel_factory.h', 'src/core/lib/client_config/client_config.h', 'src/core/lib/client_config/connector.h', 'src/core/lib/client_config/initial_connect_string.h', @@ -210,7 +211,6 @@ Pod::Spec.new do |s| 'src/core/lib/client_config/resolver_factory.h', 'src/core/lib/client_config/resolver_registry.h', 'src/core/lib/client_config/subchannel.h', - 'src/core/lib/client_config/subchannel_factory.h', 'src/core/lib/client_config/subchannel_index.h', 'src/core/lib/client_config/uri_parser.h', 'src/core/lib/compression/algorithm_metadata.h', @@ -358,6 +358,7 @@ Pod::Spec.new do |s| 'src/core/lib/channel/http_client_filter.c', 'src/core/lib/channel/http_server_filter.c', 'src/core/lib/channel/subchannel_call_holder.c', + 'src/core/lib/client_config/client_channel_factory.c', 'src/core/lib/client_config/client_config.c', 'src/core/lib/client_config/connector.c', 'src/core/lib/client_config/default_initial_connect_string.c', @@ -369,7 +370,6 @@ Pod::Spec.new do |s| 'src/core/lib/client_config/resolver_factory.c', 'src/core/lib/client_config/resolver_registry.c', 'src/core/lib/client_config/subchannel.c', - 'src/core/lib/client_config/subchannel_factory.c', 'src/core/lib/client_config/subchannel_index.c', 'src/core/lib/client_config/uri_parser.c', 'src/core/lib/compression/compression_algorithm.c', @@ -523,6 +523,7 @@ Pod::Spec.new do |s| 'src/core/lib/channel/http_client_filter.h', 'src/core/lib/channel/http_server_filter.h', 'src/core/lib/channel/subchannel_call_holder.h', + 'src/core/lib/client_config/client_channel_factory.h', 'src/core/lib/client_config/client_config.h', 'src/core/lib/client_config/connector.h', 'src/core/lib/client_config/initial_connect_string.h', @@ -533,7 +534,6 @@ Pod::Spec.new do |s| 'src/core/lib/client_config/resolver_factory.h', 'src/core/lib/client_config/resolver_registry.h', 'src/core/lib/client_config/subchannel.h', - 'src/core/lib/client_config/subchannel_factory.h', 'src/core/lib/client_config/subchannel_index.h', 'src/core/lib/client_config/uri_parser.h', 'src/core/lib/compression/algorithm_metadata.h', diff --git a/grpc.gemspec b/grpc.gemspec index d1e7ad2b31..ade8023dea 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -196,6 +196,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/channel/http_client_filter.h ) s.files += %w( src/core/lib/channel/http_server_filter.h ) s.files += %w( src/core/lib/channel/subchannel_call_holder.h ) + s.files += %w( src/core/lib/client_config/client_channel_factory.h ) s.files += %w( src/core/lib/client_config/client_config.h ) s.files += %w( src/core/lib/client_config/connector.h ) s.files += %w( src/core/lib/client_config/initial_connect_string.h ) @@ -206,7 +207,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/client_config/resolver_factory.h ) s.files += %w( src/core/lib/client_config/resolver_registry.h ) s.files += %w( src/core/lib/client_config/subchannel.h ) - s.files += %w( src/core/lib/client_config/subchannel_factory.h ) s.files += %w( src/core/lib/client_config/subchannel_index.h ) s.files += %w( src/core/lib/client_config/uri_parser.h ) s.files += %w( src/core/lib/compression/algorithm_metadata.h ) @@ -341,6 +341,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/channel/http_client_filter.c ) s.files += %w( src/core/lib/channel/http_server_filter.c ) s.files += %w( src/core/lib/channel/subchannel_call_holder.c ) + s.files += %w( src/core/lib/client_config/client_channel_factory.c ) s.files += %w( src/core/lib/client_config/client_config.c ) s.files += %w( src/core/lib/client_config/connector.c ) s.files += %w( src/core/lib/client_config/default_initial_connect_string.c ) @@ -352,7 +353,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/client_config/resolver_factory.c ) s.files += %w( src/core/lib/client_config/resolver_registry.c ) s.files += %w( src/core/lib/client_config/subchannel.c ) - s.files += %w( src/core/lib/client_config/subchannel_factory.c ) s.files += %w( src/core/lib/client_config/subchannel_index.c ) s.files += %w( src/core/lib/client_config/uri_parser.c ) s.files += %w( src/core/lib/compression/compression_algorithm.c ) diff --git a/include/grpc++/impl/codegen/async_stream.h b/include/grpc++/impl/codegen/async_stream.h index 78fb7274e2..a607a47106 100644 --- a/include/grpc++/impl/codegen/async_stream.h +++ b/include/grpc++/impl/codegen/async_stream.h @@ -108,7 +108,8 @@ class ClientAsyncReader GRPC_FINAL : public ClientAsyncReaderInterface<R> { const W& request, void* tag) : context_(context), call_(channel->CreateCall(method, context, cq)) { init_ops_.set_output_tag(tag); - init_ops_.SendInitialMetadata(context->send_initial_metadata_); + init_ops_.SendInitialMetadata(context->send_initial_metadata_, + context->initial_metadata_flags()); // TODO(ctiller): don't assert GPR_CODEGEN_ASSERT(init_ops_.SendMessage(request).ok()); init_ops_.ClientSendClose(); @@ -173,7 +174,8 @@ class ClientAsyncWriter GRPC_FINAL : public ClientAsyncWriterInterface<W> { finish_ops_.RecvMessage(response); init_ops_.set_output_tag(tag); - init_ops_.SendInitialMetadata(context->send_initial_metadata_); + init_ops_.SendInitialMetadata(context->send_initial_metadata_, + context->initial_metadata_flags()); call_.PerformOps(&init_ops_); } @@ -240,7 +242,8 @@ class ClientAsyncReaderWriter GRPC_FINAL void* tag) : context_(context), call_(channel->CreateCall(method, context, cq)) { init_ops_.set_output_tag(tag); - init_ops_.SendInitialMetadata(context->send_initial_metadata_); + init_ops_.SendInitialMetadata(context->send_initial_metadata_, + context->initial_metadata_flags()); call_.PerformOps(&init_ops_); } @@ -305,7 +308,8 @@ class ServerAsyncReader GRPC_FINAL : public ServerAsyncStreamingInterface, GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); meta_ops_.set_output_tag(tag); - meta_ops_.SendInitialMetadata(ctx_->initial_metadata_); + meta_ops_.SendInitialMetadata(ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); ctx_->sent_initial_metadata_ = true; call_.PerformOps(&meta_ops_); } @@ -319,7 +323,8 @@ class ServerAsyncReader GRPC_FINAL : public ServerAsyncStreamingInterface, void Finish(const W& msg, const Status& status, void* tag) { finish_ops_.set_output_tag(tag); if (!ctx_->sent_initial_metadata_) { - finish_ops_.SendInitialMetadata(ctx_->initial_metadata_); + finish_ops_.SendInitialMetadata(ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); ctx_->sent_initial_metadata_ = true; } // The response is dropped if the status is not OK. @@ -336,7 +341,8 @@ class ServerAsyncReader GRPC_FINAL : public ServerAsyncStreamingInterface, GPR_CODEGEN_ASSERT(!status.ok()); finish_ops_.set_output_tag(tag); if (!ctx_->sent_initial_metadata_) { - finish_ops_.SendInitialMetadata(ctx_->initial_metadata_); + finish_ops_.SendInitialMetadata(ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); ctx_->sent_initial_metadata_ = true; } finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status); @@ -366,7 +372,8 @@ class ServerAsyncWriter GRPC_FINAL : public ServerAsyncStreamingInterface, GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); meta_ops_.set_output_tag(tag); - meta_ops_.SendInitialMetadata(ctx_->initial_metadata_); + meta_ops_.SendInitialMetadata(ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); ctx_->sent_initial_metadata_ = true; call_.PerformOps(&meta_ops_); } @@ -374,7 +381,8 @@ class ServerAsyncWriter GRPC_FINAL : public ServerAsyncStreamingInterface, void Write(const W& msg, void* tag) GRPC_OVERRIDE { write_ops_.set_output_tag(tag); if (!ctx_->sent_initial_metadata_) { - write_ops_.SendInitialMetadata(ctx_->initial_metadata_); + write_ops_.SendInitialMetadata(ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); ctx_->sent_initial_metadata_ = true; } // TODO(ctiller): don't assert @@ -385,7 +393,8 @@ class ServerAsyncWriter GRPC_FINAL : public ServerAsyncStreamingInterface, void Finish(const Status& status, void* tag) { finish_ops_.set_output_tag(tag); if (!ctx_->sent_initial_metadata_) { - finish_ops_.SendInitialMetadata(ctx_->initial_metadata_); + finish_ops_.SendInitialMetadata(ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); ctx_->sent_initial_metadata_ = true; } finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status); @@ -415,7 +424,8 @@ class ServerAsyncReaderWriter GRPC_FINAL : public ServerAsyncStreamingInterface, GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); meta_ops_.set_output_tag(tag); - meta_ops_.SendInitialMetadata(ctx_->initial_metadata_); + meta_ops_.SendInitialMetadata(ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); ctx_->sent_initial_metadata_ = true; call_.PerformOps(&meta_ops_); } @@ -429,7 +439,8 @@ class ServerAsyncReaderWriter GRPC_FINAL : public ServerAsyncStreamingInterface, void Write(const W& msg, void* tag) GRPC_OVERRIDE { write_ops_.set_output_tag(tag); if (!ctx_->sent_initial_metadata_) { - write_ops_.SendInitialMetadata(ctx_->initial_metadata_); + write_ops_.SendInitialMetadata(ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); ctx_->sent_initial_metadata_ = true; } // TODO(ctiller): don't assert @@ -440,7 +451,8 @@ class ServerAsyncReaderWriter GRPC_FINAL : public ServerAsyncStreamingInterface, void Finish(const Status& status, void* tag) { finish_ops_.set_output_tag(tag); if (!ctx_->sent_initial_metadata_) { - finish_ops_.SendInitialMetadata(ctx_->initial_metadata_); + finish_ops_.SendInitialMetadata(ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); ctx_->sent_initial_metadata_ = true; } finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status); diff --git a/include/grpc++/impl/codegen/async_unary_call.h b/include/grpc++/impl/codegen/async_unary_call.h index 52b34770a8..55c9788fbd 100644 --- a/include/grpc++/impl/codegen/async_unary_call.h +++ b/include/grpc++/impl/codegen/async_unary_call.h @@ -67,7 +67,8 @@ class ClientAsyncResponseReader GRPC_FINAL call_(channel->CreateCall(method, context, cq)), collection_(new CallOpSetCollection) { collection_->init_buf_.SetCollection(collection_); - collection_->init_buf_.SendInitialMetadata(context->send_initial_metadata_); + collection_->init_buf_.SendInitialMetadata( + context->send_initial_metadata_, context->initial_metadata_flags()); // TODO(ctiller): don't assert GPR_CODEGEN_ASSERT(collection_->init_buf_.SendMessage(request).ok()); collection_->init_buf_.ClientSendClose(); @@ -122,7 +123,8 @@ class ServerAsyncResponseWriter GRPC_FINAL GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); meta_buf_.set_output_tag(tag); - meta_buf_.SendInitialMetadata(ctx_->initial_metadata_); + meta_buf_.SendInitialMetadata(ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); ctx_->sent_initial_metadata_ = true; call_.PerformOps(&meta_buf_); } @@ -130,7 +132,8 @@ class ServerAsyncResponseWriter GRPC_FINAL void Finish(const W& msg, const Status& status, void* tag) { finish_buf_.set_output_tag(tag); if (!ctx_->sent_initial_metadata_) { - finish_buf_.SendInitialMetadata(ctx_->initial_metadata_); + finish_buf_.SendInitialMetadata(ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); ctx_->sent_initial_metadata_ = true; } // The response is dropped if the status is not OK. @@ -147,7 +150,8 @@ class ServerAsyncResponseWriter GRPC_FINAL GPR_CODEGEN_ASSERT(!status.ok()); finish_buf_.set_output_tag(tag); if (!ctx_->sent_initial_metadata_) { - finish_buf_.SendInitialMetadata(ctx_->initial_metadata_); + finish_buf_.SendInitialMetadata(ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); ctx_->sent_initial_metadata_ = true; } finish_buf_.ServerSendStatus(ctx_->trailing_metadata_, status); diff --git a/include/grpc++/impl/codegen/call.h b/include/grpc++/impl/codegen/call.h index f76d7c23ed..aea1a6acec 100644 --- a/include/grpc++/impl/codegen/call.h +++ b/include/grpc++/impl/codegen/call.h @@ -181,8 +181,10 @@ class CallOpSendInitialMetadata { CallOpSendInitialMetadata() : send_(false) {} void SendInitialMetadata( - const std::multimap<grpc::string, grpc::string>& metadata) { + const std::multimap<grpc::string, grpc::string>& metadata, + uint32_t flags) { send_ = true; + flags_ = flags; initial_metadata_count_ = metadata.size(); initial_metadata_ = FillMetadataArray(metadata); } @@ -192,7 +194,7 @@ class CallOpSendInitialMetadata { if (!send_) return; grpc_op* op = &ops[(*nops)++]; op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->flags = 0; + op->flags = flags_; op->reserved = NULL; op->data.send_initial_metadata.count = initial_metadata_count_; op->data.send_initial_metadata.metadata = initial_metadata_; @@ -204,6 +206,7 @@ class CallOpSendInitialMetadata { } bool send_; + uint32_t flags_; size_t initial_metadata_count_; grpc_metadata* initial_metadata_; }; diff --git a/include/grpc++/impl/codegen/client_context.h b/include/grpc++/impl/codegen/client_context.h index 5201808600..aed12767a7 100644 --- a/include/grpc++/impl/codegen/client_context.h +++ b/include/grpc++/impl/codegen/client_context.h @@ -221,6 +221,12 @@ class ClientContext { deadline_ = deadline_tp.raw_time(); } + /// EXPERIMENTAL: Set this request to be idempotent + void set_idempotent(bool idempotent) { idempotent_ = idempotent; } + + /// EXPERIMENTAL: Trigger fail-fast or not on this request + void set_fail_fast(bool fail_fast) { fail_fast_ = fail_fast; } + #ifndef GRPC_CXX0X_NO_CHRONO /// Return the deadline for the client call. std::chrono::system_clock::time_point deadline() { @@ -328,9 +334,16 @@ class ClientContext { grpc_call* call() { return call_; } void set_call(grpc_call* call, const std::shared_ptr<Channel>& channel); + uint32_t initial_metadata_flags() const { + return (idempotent_ ? GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST : 0) | + (fail_fast_ ? 0 : GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY); + } + grpc::string authority() { return authority_; } bool initial_metadata_received_; + bool fail_fast_; + bool idempotent_; std::shared_ptr<Channel> channel_; grpc::mutex mu_; grpc_call* call_; diff --git a/include/grpc++/impl/codegen/client_unary_call.h b/include/grpc++/impl/codegen/client_unary_call.h index 0ee5b198d2..70d65549c8 100644 --- a/include/grpc++/impl/codegen/client_unary_call.h +++ b/include/grpc++/impl/codegen/client_unary_call.h @@ -62,7 +62,8 @@ Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method, if (!status.ok()) { return status; } - ops.SendInitialMetadata(context->send_initial_metadata_); + ops.SendInitialMetadata(context->send_initial_metadata_, + context->initial_metadata_flags()); ops.RecvInitialMetadata(context); ops.RecvMessage(result); ops.ClientSendClose(); diff --git a/include/grpc++/impl/codegen/method_handler_impl.h b/include/grpc++/impl/codegen/method_handler_impl.h index 436b4d819b..ad74efabc4 100644 --- a/include/grpc++/impl/codegen/method_handler_impl.h +++ b/include/grpc++/impl/codegen/method_handler_impl.h @@ -63,7 +63,8 @@ class RpcMethodHandler : public MethodHandler { CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpServerSendStatus> ops; - ops.SendInitialMetadata(param.server_context->initial_metadata_); + ops.SendInitialMetadata(param.server_context->initial_metadata_, + param.server_context->initial_metadata_flags()); if (status.ok()) { status = ops.SendMessage(rsp); } @@ -100,7 +101,8 @@ class ClientStreamingHandler : public MethodHandler { CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpServerSendStatus> ops; - ops.SendInitialMetadata(param.server_context->initial_metadata_); + ops.SendInitialMetadata(param.server_context->initial_metadata_, + param.server_context->initial_metadata_flags()); if (status.ok()) { status = ops.SendMessage(rsp); } @@ -138,7 +140,8 @@ class ServerStreamingHandler : public MethodHandler { CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> ops; if (!param.server_context->sent_initial_metadata_) { - ops.SendInitialMetadata(param.server_context->initial_metadata_); + ops.SendInitialMetadata(param.server_context->initial_metadata_, + param.server_context->initial_metadata_flags()); } ops.ServerSendStatus(param.server_context->trailing_metadata_, status); param.call->PerformOps(&ops); @@ -170,7 +173,8 @@ class BidiStreamingHandler : public MethodHandler { CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> ops; if (!param.server_context->sent_initial_metadata_) { - ops.SendInitialMetadata(param.server_context->initial_metadata_); + ops.SendInitialMetadata(param.server_context->initial_metadata_, + param.server_context->initial_metadata_flags()); } ops.ServerSendStatus(param.server_context->trailing_metadata_, status); param.call->PerformOps(&ops); @@ -191,7 +195,8 @@ class UnknownMethodHandler : public MethodHandler { static void FillOps(ServerContext* context, T* ops) { Status status(StatusCode::UNIMPLEMENTED, ""); if (!context->sent_initial_metadata_) { - ops->SendInitialMetadata(context->initial_metadata_); + ops->SendInitialMetadata(context->initial_metadata_, + context->initial_metadata_flags()); context->sent_initial_metadata_ = true; } ops->ServerSendStatus(context->trailing_metadata_, status); diff --git a/include/grpc++/impl/codegen/server_context.h b/include/grpc++/impl/codegen/server_context.h index 44d340aa45..7fa0235ca9 100644 --- a/include/grpc++/impl/codegen/server_context.h +++ b/include/grpc++/impl/codegen/server_context.h @@ -195,6 +195,8 @@ class ServerContext { void set_call(grpc_call* call); + uint32_t initial_metadata_flags() const { return 0; } + CompletionOp* completion_op_; bool has_notify_when_done_tag_; void* async_notify_when_done_tag_; diff --git a/include/grpc++/impl/codegen/sync_stream.h b/include/grpc++/impl/codegen/sync_stream.h index d0ad05169f..9100ce09a2 100644 --- a/include/grpc++/impl/codegen/sync_stream.h +++ b/include/grpc++/impl/codegen/sync_stream.h @@ -125,7 +125,8 @@ class ClientReader GRPC_FINAL : public ClientReaderInterface<R> { CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose> ops; - ops.SendInitialMetadata(context->send_initial_metadata_); + ops.SendInitialMetadata(context->send_initial_metadata_, + context->initial_metadata_flags()); // TODO(ctiller): don't assert GPR_CODEGEN_ASSERT(ops.SendMessage(request).ok()); ops.ClientSendClose(); @@ -190,7 +191,8 @@ class ClientWriter : public ClientWriterInterface<W> { finish_ops_.RecvMessage(response); CallOpSet<CallOpSendInitialMetadata> ops; - ops.SendInitialMetadata(context->send_initial_metadata_); + ops.SendInitialMetadata(context->send_initial_metadata_, + context->initial_metadata_flags()); call_.PerformOps(&ops); cq_.Pluck(&ops); } @@ -268,7 +270,8 @@ class ClientReaderWriter GRPC_FINAL : public ClientReaderWriterInterface<W, R> { ClientContext* context) : context_(context), call_(channel->CreateCall(method, context, &cq_)) { CallOpSet<CallOpSendInitialMetadata> ops; - ops.SendInitialMetadata(context->send_initial_metadata_); + ops.SendInitialMetadata(context->send_initial_metadata_, + context->initial_metadata_flags()); call_.PerformOps(&ops); cq_.Pluck(&ops); } @@ -334,7 +337,8 @@ class ServerReader GRPC_FINAL : public ReaderInterface<R> { GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); CallOpSet<CallOpSendInitialMetadata> ops; - ops.SendInitialMetadata(ctx_->initial_metadata_); + ops.SendInitialMetadata(ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); ctx_->sent_initial_metadata_ = true; call_->PerformOps(&ops); call_->cq()->Pluck(&ops); @@ -361,7 +365,8 @@ class ServerWriter GRPC_FINAL : public WriterInterface<W> { GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); CallOpSet<CallOpSendInitialMetadata> ops; - ops.SendInitialMetadata(ctx_->initial_metadata_); + ops.SendInitialMetadata(ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); ctx_->sent_initial_metadata_ = true; call_->PerformOps(&ops); call_->cq()->Pluck(&ops); @@ -374,7 +379,8 @@ class ServerWriter GRPC_FINAL : public WriterInterface<W> { return false; } if (!ctx_->sent_initial_metadata_) { - ops.SendInitialMetadata(ctx_->initial_metadata_); + ops.SendInitialMetadata(ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); ctx_->sent_initial_metadata_ = true; } call_->PerformOps(&ops); @@ -397,7 +403,8 @@ class ServerReaderWriter GRPC_FINAL : public WriterInterface<W>, GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_); CallOpSet<CallOpSendInitialMetadata> ops; - ops.SendInitialMetadata(ctx_->initial_metadata_); + ops.SendInitialMetadata(ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); ctx_->sent_initial_metadata_ = true; call_->PerformOps(&ops); call_->cq()->Pluck(&ops); @@ -417,7 +424,8 @@ class ServerReaderWriter GRPC_FINAL : public WriterInterface<W>, return false; } if (!ctx_->sent_initial_metadata_) { - ops.SendInitialMetadata(ctx_->initial_metadata_); + ops.SendInitialMetadata(ctx_->initial_metadata_, + ctx_->initial_metadata_flags()); ctx_->sent_initial_metadata_ = true; } call_->PerformOps(&ops); diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index 65dae59bc7..aba4217d6a 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -204,8 +204,12 @@ typedef enum grpc_call_error { /* Initial metadata flags */ /** Signal that the call is idempotent */ #define GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST (0x00000010u) +/** Signal that the call should not return UNAVAILABLE before it has started */ +#define GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY (0x00000020u) /** Mask of all valid flags */ -#define GRPC_INITIAL_METADATA_USED_MASK GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST +#define GRPC_INITIAL_METADATA_USED_MASK \ + (GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST | \ + GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY) /** A single metadata element */ typedef struct grpc_metadata { diff --git a/package.json b/package.json index 24a5aa0cd5..339db464d1 100644 --- a/package.json +++ b/package.json @@ -139,6 +139,7 @@ "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", "src/core/lib/channel/subchannel_call_holder.h", + "src/core/lib/client_config/client_channel_factory.h", "src/core/lib/client_config/client_config.h", "src/core/lib/client_config/connector.h", "src/core/lib/client_config/initial_connect_string.h", @@ -149,7 +150,6 @@ "src/core/lib/client_config/resolver_factory.h", "src/core/lib/client_config/resolver_registry.h", "src/core/lib/client_config/subchannel.h", - "src/core/lib/client_config/subchannel_factory.h", "src/core/lib/client_config/subchannel_index.h", "src/core/lib/client_config/uri_parser.h", "src/core/lib/compression/algorithm_metadata.h", @@ -284,6 +284,7 @@ "src/core/lib/channel/http_client_filter.c", "src/core/lib/channel/http_server_filter.c", "src/core/lib/channel/subchannel_call_holder.c", + "src/core/lib/client_config/client_channel_factory.c", "src/core/lib/client_config/client_config.c", "src/core/lib/client_config/connector.c", "src/core/lib/client_config/default_initial_connect_string.c", @@ -295,7 +296,6 @@ "src/core/lib/client_config/resolver_factory.c", "src/core/lib/client_config/resolver_registry.c", "src/core/lib/client_config/subchannel.c", - "src/core/lib/client_config/subchannel_factory.c", "src/core/lib/client_config/subchannel_index.c", "src/core/lib/client_config/uri_parser.c", "src/core/lib/compression/compression_algorithm.c", diff --git a/package.xml b/package.xml index 0bb34d9487..af0e2e5bcd 100644 --- a/package.xml +++ b/package.xml @@ -200,6 +200,7 @@ <file baseinstalldir="/" name="src/core/lib/channel/http_client_filter.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/channel/http_server_filter.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/channel/subchannel_call_holder.h" role="src" /> + <file baseinstalldir="/" name="src/core/lib/client_config/client_channel_factory.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/client_config/client_config.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/client_config/connector.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/client_config/initial_connect_string.h" role="src" /> @@ -210,7 +211,6 @@ <file baseinstalldir="/" name="src/core/lib/client_config/resolver_factory.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/client_config/resolver_registry.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/client_config/subchannel.h" role="src" /> - <file baseinstalldir="/" name="src/core/lib/client_config/subchannel_factory.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/client_config/subchannel_index.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/client_config/uri_parser.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/compression/algorithm_metadata.h" role="src" /> @@ -345,6 +345,7 @@ <file baseinstalldir="/" name="src/core/lib/channel/http_client_filter.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/channel/http_server_filter.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/channel/subchannel_call_holder.c" role="src" /> + <file baseinstalldir="/" name="src/core/lib/client_config/client_channel_factory.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/client_config/client_config.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/client_config/connector.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/client_config/default_initial_connect_string.c" role="src" /> @@ -356,7 +357,6 @@ <file baseinstalldir="/" name="src/core/lib/client_config/resolver_factory.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/client_config/resolver_registry.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/client_config/subchannel.c" role="src" /> - <file baseinstalldir="/" name="src/core/lib/client_config/subchannel_factory.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/client_config/subchannel_index.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/client_config/uri_parser.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/compression/compression_algorithm.c" role="src" /> diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index 5a8746df8d..69e2738d53 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -81,6 +81,10 @@ std::string GetServerInterfaceName(const ServiceDescriptor* service) { return "I" + service->name(); } +std::string GetServerClassName(const ServiceDescriptor* service) { + return service->name() + "Base"; +} + std::string GetCSharpMethodType(MethodType method_type) { switch (method_type) { case METHODTYPE_NO_STREAMING: @@ -108,10 +112,14 @@ std::string GetMethodFieldName(const MethodDescriptor *method) { return "__Method_" + method->name(); } -std::string GetMethodRequestParamMaybe(const MethodDescriptor *method) { +std::string GetMethodRequestParamMaybe(const MethodDescriptor *method, + bool invocation_param=false) { if (method->client_streaming()) { return ""; } + if (invocation_param) { + return "request, "; + } return GetClassName(method->input_type()) + " request, "; } @@ -242,6 +250,8 @@ void GenerateServiceDescriptorProperty(Printer* out, const ServiceDescriptor *se void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) { out->Print("// client interface\n"); + out->Print("[System.Obsolete(\"Client side interfaced will be removed " + "in the next release. Use client class directly.\")]\n"); out->Print("public interface $name$\n", "name", GetClientInterfaceName(service)); out->Print("{\n"); @@ -290,6 +300,8 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) { void GenerateServerInterface(Printer* out, const ServiceDescriptor *service) { out->Print("// server-side interface\n"); + out->Print("[System.Obsolete(\"Service implementations should inherit" + " from the generated abstract base class instead.\")]\n"); out->Print("public interface $name$\n", "name", GetServerInterfaceName(service)); out->Print("{\n"); @@ -309,21 +321,64 @@ void GenerateServerInterface(Printer* out, const ServiceDescriptor *service) { out->Print("\n"); } +void GenerateServerClass(Printer* out, const ServiceDescriptor *service) { + out->Print("// server-side abstract class\n"); + out->Print("public abstract class $name$\n", "name", + GetServerClassName(service)); + out->Print("{\n"); + out->Indent(); + for (int i = 0; i < service->method_count(); i++) { + const MethodDescriptor *method = service->method(i); + out->Print( + "public virtual $returntype$ $methodname$($request$$response_stream_maybe$, " + "ServerCallContext context)\n", + "methodname", method->name(), "returntype", + GetMethodReturnTypeServer(method), "request", + GetMethodRequestParamServer(method), "response_stream_maybe", + GetMethodResponseStreamMaybe(method)); + out->Print("{\n"); + out->Indent(); + out->Print("throw new RpcException(" + "new Status(StatusCode.Unimplemented, \"\"));\n"); + out->Outdent(); + out->Print("}\n\n"); + } + out->Outdent(); + out->Print("}\n"); + out->Print("\n"); +} + void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { out->Print("// client stub\n"); out->Print( - "public class $name$ : ClientBase, $interface$\n", - "name", GetClientClassName(service), "interface", - GetClientInterfaceName(service)); + "public class $name$ : ClientBase<$name$>, $interface$\n", + "name", GetClientClassName(service), + "interface", GetClientInterfaceName(service)); out->Print("{\n"); out->Indent(); // constructors - out->Print( - "public $name$(Channel channel) : base(channel)\n", - "name", GetClientClassName(service)); + out->Print("public $name$(Channel channel) : base(channel)\n", + "name", GetClientClassName(service)); + out->Print("{\n"); + out->Print("}\n"); + out->Print("public $name$(CallInvoker callInvoker) : base(callInvoker)\n", + "name", GetClientClassName(service)); out->Print("{\n"); out->Print("}\n"); + out->Print("///<summary>Protected parameterless constructor to allow creation" + " of test doubles.</summary>\n"); + out->Print("protected $name$() : base()\n", + "name", GetClientClassName(service)); + out->Print("{\n"); + out->Print("}\n"); + out->Print("///<summary>Protected constructor to allow creation of configured" + " clients.</summary>\n"); + out->Print("protected $name$(ClientBaseConfiguration configuration)" + " : base(configuration)\n", + "name", GetClientClassName(service)); + out->Print("{\n"); + out->Print("}\n\n"); for (int i = 0; i < service->method_count(); i++) { const MethodDescriptor *method = service->method(i); @@ -331,30 +386,26 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { if (method_type == METHODTYPE_NO_STREAMING) { // unary calls have an extra synchronous stub method - out->Print( - "public $response$ $methodname$($request$ request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n", + out->Print("public virtual $response$ $methodname$($request$ request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n", "methodname", method->name(), "request", GetClassName(method->input_type()), "response", GetClassName(method->output_type())); out->Print("{\n"); out->Indent(); - out->Print("var call = CreateCall($methodfield$, new CallOptions(headers, deadline, cancellationToken));\n", - "methodfield", GetMethodFieldName(method)); - out->Print("return Calls.BlockingUnaryCall(call, request);\n"); + out->Print("return $methodname$(request, new CallOptions(headers, deadline, cancellationToken));\n", + "methodname", method->name()); out->Outdent(); out->Print("}\n"); // overload taking CallOptions as a param - out->Print( - "public $response$ $methodname$($request$ request, CallOptions options)\n", - "methodname", method->name(), "request", - GetClassName(method->input_type()), "response", - GetClassName(method->output_type())); + out->Print("public virtual $response$ $methodname$($request$ request, CallOptions options)\n", + "methodname", method->name(), "request", + GetClassName(method->input_type()), "response", + GetClassName(method->output_type())); out->Print("{\n"); out->Indent(); - out->Print("var call = CreateCall($methodfield$, options);\n", + out->Print("return CallInvoker.BlockingUnaryCall($methodfield$, null, options, request);\n", "methodfield", GetMethodFieldName(method)); - out->Print("return Calls.BlockingUnaryCall(call, request);\n"); out->Outdent(); out->Print("}\n"); } @@ -364,57 +415,44 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { method_name += "Async"; // prevent name clash with synchronous method. } out->Print( - "public $returntype$ $methodname$($request_maybe$Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n", - "methodname", method_name, "request_maybe", - GetMethodRequestParamMaybe(method), "returntype", - GetMethodReturnTypeClient(method)); + "public virtual $returntype$ $methodname$($request_maybe$Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n", + "methodname", method_name, "request_maybe", + GetMethodRequestParamMaybe(method), "returntype", + GetMethodReturnTypeClient(method)); out->Print("{\n"); out->Indent(); - out->Print("var call = CreateCall($methodfield$, new CallOptions(headers, deadline, cancellationToken));\n", - "methodfield", GetMethodFieldName(method)); - switch (GetMethodType(method)) { - case METHODTYPE_NO_STREAMING: - out->Print("return Calls.AsyncUnaryCall(call, request);\n"); - break; - case METHODTYPE_CLIENT_STREAMING: - out->Print("return Calls.AsyncClientStreamingCall(call);\n"); - break; - case METHODTYPE_SERVER_STREAMING: - out->Print( - "return Calls.AsyncServerStreamingCall(call, request);\n"); - break; - case METHODTYPE_BIDI_STREAMING: - out->Print("return Calls.AsyncDuplexStreamingCall(call);\n"); - break; - default: - GOOGLE_LOG(FATAL)<< "Can't get here."; - } + + out->Print("return $methodname$($request_maybe$new CallOptions(headers, deadline, cancellationToken));\n", + "methodname", method_name, + "request_maybe", GetMethodRequestParamMaybe(method, true)); out->Outdent(); out->Print("}\n"); // overload taking CallOptions as a param out->Print( - "public $returntype$ $methodname$($request_maybe$CallOptions options)\n", + "public virtual $returntype$ $methodname$($request_maybe$CallOptions options)\n", "methodname", method_name, "request_maybe", GetMethodRequestParamMaybe(method), "returntype", GetMethodReturnTypeClient(method)); out->Print("{\n"); out->Indent(); - out->Print("var call = CreateCall($methodfield$, options);\n", - "methodfield", GetMethodFieldName(method)); switch (GetMethodType(method)) { case METHODTYPE_NO_STREAMING: - out->Print("return Calls.AsyncUnaryCall(call, request);\n"); + out->Print("return CallInvoker.AsyncUnaryCall($methodfield$, null, options, request);\n", + "methodfield", GetMethodFieldName(method)); break; case METHODTYPE_CLIENT_STREAMING: - out->Print("return Calls.AsyncClientStreamingCall(call);\n"); + out->Print("return CallInvoker.AsyncClientStreamingCall($methodfield$, null, options);\n", + "methodfield", GetMethodFieldName(method)); break; case METHODTYPE_SERVER_STREAMING: out->Print( - "return Calls.AsyncServerStreamingCall(call, request);\n"); + "return CallInvoker.AsyncServerStreamingCall($methodfield$, null, options, request);\n", + "methodfield", GetMethodFieldName(method)); break; case METHODTYPE_BIDI_STREAMING: - out->Print("return Calls.AsyncDuplexStreamingCall(call);\n"); + out->Print("return CallInvoker.AsyncDuplexStreamingCall($methodfield$, null, options);\n", + "methodfield", GetMethodFieldName(method)); break; default: GOOGLE_LOG(FATAL)<< "Can't get here."; @@ -422,17 +460,30 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { out->Outdent(); out->Print("}\n"); } + + // override NewInstance method + out->Print("protected override $name$ NewInstance(ClientBaseConfiguration configuration)\n", + "name", GetClientClassName(service)); + out->Print("{\n"); + out->Indent(); + out->Print("return new $name$(configuration);\n", + "name", GetClientClassName(service)); + out->Outdent(); + out->Print("}\n"); + out->Outdent(); out->Print("}\n"); out->Print("\n"); } -void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service) { +void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service, + bool use_server_class) { out->Print( "// creates service definition that can be registered with a server\n"); out->Print( "public static ServerServiceDefinition BindService($interface$ serviceImpl)\n", - "interface", GetServerInterfaceName(service)); + "interface", use_server_class ? GetServerClassName(service) : + GetServerInterfaceName(service)); out->Print("{\n"); out->Indent(); @@ -489,8 +540,10 @@ void GenerateService(Printer* out, const ServiceDescriptor *service) { GenerateServiceDescriptorProperty(out, service); GenerateClientInterface(out, service); GenerateServerInterface(out, service); + GenerateServerClass(out, service); GenerateClientStub(out, service); - GenerateBindServiceMethod(out, service); + GenerateBindServiceMethod(out, service, false); + GenerateBindServiceMethod(out, service, true); GenerateNewStubMethods(out, service); out->Outdent(); diff --git a/src/core/ext/lb_policy/pick_first/pick_first.c b/src/core/ext/lb_policy/pick_first/pick_first.c index cb5c40501e..43197c1191 100644 --- a/src/core/ext/lb_policy/pick_first/pick_first.c +++ b/src/core/ext/lb_policy/pick_first/pick_first.c @@ -40,6 +40,7 @@ typedef struct pending_pick { struct pending_pick *next; grpc_pollset *pollset; + uint32_t initial_metadata_flags; grpc_connected_subchannel **target; grpc_closure *on_complete; } pending_pick; @@ -149,6 +150,31 @@ static void pf_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, gpr_mu_unlock(&p->mu); } +static void pf_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, + uint32_t initial_metadata_flags_mask, + uint32_t initial_metadata_flags_eq) { + pick_first_lb_policy *p = (pick_first_lb_policy *)pol; + pending_pick *pp; + gpr_mu_lock(&p->mu); + pp = p->pending_picks; + p->pending_picks = NULL; + while (pp != NULL) { + pending_pick *next = pp->next; + if ((pp->initial_metadata_flags & initial_metadata_flags_mask) == + initial_metadata_flags_eq) { + grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties, + pp->pollset); + grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL); + gpr_free(pp); + } else { + pp->next = p->pending_picks; + p->pending_picks = pp; + } + pp = next; + } + gpr_mu_unlock(&p->mu); +} + static void start_picking(grpc_exec_ctx *exec_ctx, pick_first_lb_policy *p) { p->started_picking = 1; p->checking_subchannel = 0; @@ -171,6 +197,7 @@ static void pf_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { static int pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_pollset *pollset, grpc_metadata_batch *initial_metadata, + uint32_t initial_metadata_flags, grpc_connected_subchannel **target, grpc_closure *on_complete) { pick_first_lb_policy *p = (pick_first_lb_policy *)pol; @@ -199,6 +226,7 @@ static int pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, pp->next = p->pending_picks; pp->pollset = pollset; pp->target = target; + pp->initial_metadata_flags = initial_metadata_flags; pp->on_complete = on_complete; p->pending_picks = pp; gpr_mu_unlock(&p->mu); @@ -286,11 +314,14 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg, &p->checking_connectivity, &p->connectivity_changed); break; case GRPC_CHANNEL_TRANSIENT_FAILURE: - grpc_connectivity_state_set(exec_ctx, &p->state_tracker, - GRPC_CHANNEL_TRANSIENT_FAILURE, - "connecting_transient_failure"); p->checking_subchannel = (p->checking_subchannel + 1) % p->num_subchannels; + if (p->checking_subchannel == 0) { + /* only trigger transient failure when we've tried all alternatives */ + grpc_connectivity_state_set(exec_ctx, &p->state_tracker, + GRPC_CHANNEL_TRANSIENT_FAILURE, + "connecting_transient_failure"); + } p->checking_connectivity = grpc_subchannel_check_connectivity( p->subchannels[p->checking_subchannel]); if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) { @@ -378,14 +409,9 @@ static void pf_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, } static const grpc_lb_policy_vtable pick_first_lb_policy_vtable = { - pf_destroy, - pf_shutdown, - pf_pick, - pf_cancel_pick, - pf_ping_one, - pf_exit_idle, - pf_check_connectivity, - pf_notify_on_state_change}; + pf_destroy, pf_shutdown, pf_pick, + pf_cancel_pick, pf_cancel_picks, pf_ping_one, + pf_exit_idle, pf_check_connectivity, pf_notify_on_state_change}; static void pick_first_factory_ref(grpc_lb_policy_factory *factory) {} @@ -395,7 +421,7 @@ static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx, grpc_lb_policy_factory *factory, grpc_lb_policy_args *args) { GPR_ASSERT(args->addresses != NULL); - GPR_ASSERT(args->subchannel_factory != NULL); + GPR_ASSERT(args->client_channel_factory != NULL); if (args->addresses->naddrs == 0) return NULL; @@ -412,8 +438,8 @@ static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx, sc_args.addr = (struct sockaddr *)(args->addresses->addrs[i].addr); sc_args.addr_len = (size_t)args->addresses->addrs[i].len; - grpc_subchannel *subchannel = grpc_subchannel_factory_create_subchannel( - exec_ctx, args->subchannel_factory, &sc_args); + grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel( + exec_ctx, args->client_channel_factory, &sc_args); if (subchannel != NULL) { p->subchannels[subchannel_idx++] = subchannel; diff --git a/src/core/ext/lb_policy/round_robin/round_robin.c b/src/core/ext/lb_policy/round_robin/round_robin.c index d94c081494..eac6971099 100644 --- a/src/core/ext/lb_policy/round_robin/round_robin.c +++ b/src/core/ext/lb_policy/round_robin/round_robin.c @@ -49,6 +49,7 @@ int grpc_lb_round_robin_trace = 0; typedef struct pending_pick { struct pending_pick *next; grpc_pollset *pollset; + uint32_t initial_metadata_flags; grpc_connected_subchannel **target; grpc_closure *on_complete; } pending_pick; @@ -275,6 +276,32 @@ static void rr_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, gpr_mu_unlock(&p->mu); } +static void rr_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, + uint32_t initial_metadata_flags_mask, + uint32_t initial_metadata_flags_eq) { + round_robin_lb_policy *p = (round_robin_lb_policy *)pol; + pending_pick *pp; + gpr_mu_lock(&p->mu); + pp = p->pending_picks; + p->pending_picks = NULL; + while (pp != NULL) { + pending_pick *next = pp->next; + if ((pp->initial_metadata_flags & initial_metadata_flags_mask) == + initial_metadata_flags_eq) { + grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties, + pp->pollset); + *pp->target = NULL; + grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL); + gpr_free(pp); + } else { + pp->next = p->pending_picks; + p->pending_picks = pp; + } + pp = next; + } + gpr_mu_unlock(&p->mu); +} + static void start_picking(grpc_exec_ctx *exec_ctx, round_robin_lb_policy *p) { size_t i; p->started_picking = 1; @@ -303,6 +330,7 @@ static void rr_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { static int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_pollset *pollset, grpc_metadata_batch *initial_metadata, + uint32_t initial_metadata_flags, grpc_connected_subchannel **target, grpc_closure *on_complete) { round_robin_lb_policy *p = (round_robin_lb_policy *)pol; @@ -330,6 +358,7 @@ static int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, pp->pollset = pollset; pp->target = target; pp->on_complete = on_complete; + pp->initial_metadata_flags = initial_metadata_flags; p->pending_picks = pp; gpr_mu_unlock(&p->mu); return 0; @@ -485,14 +514,9 @@ static void rr_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, } static const grpc_lb_policy_vtable round_robin_lb_policy_vtable = { - rr_destroy, - rr_shutdown, - rr_pick, - rr_cancel_pick, - rr_ping_one, - rr_exit_idle, - rr_check_connectivity, - rr_notify_on_state_change}; + rr_destroy, rr_shutdown, rr_pick, + rr_cancel_pick, rr_cancel_picks, rr_ping_one, + rr_exit_idle, rr_check_connectivity, rr_notify_on_state_change}; static void round_robin_factory_ref(grpc_lb_policy_factory *factory) {} @@ -502,7 +526,7 @@ static grpc_lb_policy *create_round_robin(grpc_exec_ctx *exec_ctx, grpc_lb_policy_factory *factory, grpc_lb_policy_args *args) { GPR_ASSERT(args->addresses != NULL); - GPR_ASSERT(args->subchannel_factory != NULL); + GPR_ASSERT(args->client_channel_factory != NULL); round_robin_lb_policy *p = gpr_malloc(sizeof(*p)); memset(p, 0, sizeof(*p)); @@ -518,8 +542,8 @@ static grpc_lb_policy *create_round_robin(grpc_exec_ctx *exec_ctx, sc_args.addr = (struct sockaddr *)(args->addresses->addrs[i].addr); sc_args.addr_len = (size_t)args->addresses->addrs[i].len; - grpc_subchannel *subchannel = grpc_subchannel_factory_create_subchannel( - exec_ctx, args->subchannel_factory, &sc_args); + grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel( + exec_ctx, args->client_channel_factory, &sc_args); if (subchannel != NULL) { subchannel_data *sd = gpr_malloc(sizeof(*sd)); diff --git a/src/core/ext/resolver/dns/native/dns_resolver.c b/src/core/ext/resolver/dns/native/dns_resolver.c index 70d8a3fe2d..1a0bf305d6 100644 --- a/src/core/ext/resolver/dns/native/dns_resolver.c +++ b/src/core/ext/resolver/dns/native/dns_resolver.c @@ -59,7 +59,7 @@ typedef struct { /** default port to use */ char *default_port; /** subchannel factory */ - grpc_subchannel_factory *subchannel_factory; + grpc_client_channel_factory *client_channel_factory; /** load balancing policy name */ char *lb_policy_name; @@ -170,7 +170,7 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg, config = grpc_client_config_create(); memset(&lb_policy_args, 0, sizeof(lb_policy_args)); lb_policy_args.addresses = addresses; - lb_policy_args.subchannel_factory = r->subchannel_factory; + lb_policy_args.client_channel_factory = r->client_channel_factory; lb_policy = grpc_lb_policy_create(exec_ctx, r->lb_policy_name, &lb_policy_args); if (lb_policy != NULL) { @@ -228,7 +228,7 @@ static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) { if (r->resolved_config) { grpc_client_config_unref(exec_ctx, r->resolved_config); } - grpc_subchannel_factory_unref(exec_ctx, r->subchannel_factory); + grpc_client_channel_factory_unref(exec_ctx, r->client_channel_factory); gpr_free(r->name); gpr_free(r->default_port); gpr_free(r->lb_policy_name); @@ -255,10 +255,10 @@ static grpc_resolver *dns_create(grpc_resolver_args *args, grpc_resolver_init(&r->base, &dns_resolver_vtable); r->name = gpr_strdup(path); r->default_port = gpr_strdup(default_port); - r->subchannel_factory = args->subchannel_factory; + r->client_channel_factory = args->client_channel_factory; gpr_backoff_init(&r->backoff_state, BACKOFF_MULTIPLIER, BACKOFF_JITTER, BACKOFF_MIN_SECONDS * 1000, BACKOFF_MAX_SECONDS * 1000); - grpc_subchannel_factory_ref(r->subchannel_factory); + grpc_client_channel_factory_ref(r->client_channel_factory); r->lb_policy_name = gpr_strdup(lb_policy_name); return &r->base; } diff --git a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c index 69595ca3db..b50b4ee480 100644 --- a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c +++ b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c @@ -52,7 +52,7 @@ typedef struct { /** refcount */ gpr_refcount refs; /** subchannel factory */ - grpc_subchannel_factory *subchannel_factory; + grpc_client_channel_factory *client_channel_factory; /** load balancing policy name */ char *lb_policy_name; @@ -125,7 +125,7 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy_args lb_policy_args; memset(&lb_policy_args, 0, sizeof(lb_policy_args)); lb_policy_args.addresses = r->addresses; - lb_policy_args.subchannel_factory = r->subchannel_factory; + lb_policy_args.client_channel_factory = r->client_channel_factory; grpc_lb_policy *lb_policy = grpc_lb_policy_create(exec_ctx, r->lb_policy_name, &lb_policy_args); grpc_client_config_set_lb_policy(cfg, lb_policy); @@ -140,7 +140,7 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx, static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) { sockaddr_resolver *r = (sockaddr_resolver *)gr; gpr_mu_destroy(&r->mu); - grpc_subchannel_factory_unref(exec_ctx, r->subchannel_factory); + grpc_client_channel_factory_unref(exec_ctx, r->client_channel_factory); grpc_resolved_addresses_destroy(r->addresses); gpr_free(r->lb_policy_name); gpr_free(r); @@ -318,8 +318,8 @@ static grpc_resolver *sockaddr_create( gpr_ref_init(&r->refs, 1); gpr_mu_init(&r->mu); grpc_resolver_init(&r->base, &sockaddr_resolver_vtable); - r->subchannel_factory = args->subchannel_factory; - grpc_subchannel_factory_ref(r->subchannel_factory); + r->client_channel_factory = args->client_channel_factory; + grpc_client_channel_factory_ref(r->client_channel_factory); return &r->base; } diff --git a/src/core/ext/resolver/zookeeper/zookeeper_resolver.c b/src/core/ext/resolver/zookeeper/zookeeper_resolver.c index 5acb0940c6..91153f14b5 100644 --- a/src/core/ext/resolver/zookeeper/zookeeper_resolver.c +++ b/src/core/ext/resolver/zookeeper/zookeeper_resolver.c @@ -57,7 +57,7 @@ typedef struct { /** name to resolve */ char *name; /** subchannel factory */ - grpc_subchannel_factory *subchannel_factory; + grpc_client_channel_factory *client_channel_factory; /** load balancing policy name */ char *lb_policy_name; @@ -187,9 +187,8 @@ static void zookeeper_on_resolved(grpc_exec_ctx *exec_ctx, void *arg, if (addresses != NULL) { grpc_lb_policy_args lb_policy_args; config = grpc_client_config_create(); - lb_policy_args.addresses = addresses; - lb_policy_args.subchannel_factory = r->subchannel_factory; + lb_policy_args.client_channel_factory = r->client_channel_factory; lb_policy = grpc_lb_policy_create(exec_ctx, r->lb_policy_name, &lb_policy_args); @@ -424,7 +423,7 @@ static void zookeeper_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) { if (r->resolved_config != NULL) { grpc_client_config_unref(exec_ctx, r->resolved_config); } - grpc_subchannel_factory_unref(exec_ctx, r->subchannel_factory); + grpc_client_channel_factory_unref(exec_ctx, r->client_channel_factory); gpr_free(r->name); gpr_free(r->lb_policy_name); gpr_free(r); @@ -454,8 +453,8 @@ static grpc_resolver *zookeeper_create(grpc_resolver_args *args, grpc_resolver_init(&r->base, &zookeeper_resolver_vtable); r->name = gpr_strdup(path); - r->subchannel_factory = args->subchannel_factory; - grpc_subchannel_factory_ref(r->subchannel_factory); + r->client_channel_factory = args->client_channel_factory; + grpc_client_channel_factory_ref(r->client_channel_factory); r->lb_policy_name = gpr_strdup(lb_policy_name); diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.c b/src/core/ext/transport/chttp2/client/insecure/channel_create.c index 606fff5fb4..ee2ac44978 100644 --- a/src/core/ext/transport/chttp2/client/insecure/channel_create.c +++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.c @@ -136,31 +136,35 @@ static const grpc_connector_vtable connector_vtable = { connector_ref, connector_unref, connector_shutdown, connector_connect}; typedef struct { - grpc_subchannel_factory base; + grpc_client_channel_factory base; gpr_refcount refs; grpc_channel_args *merge_args; grpc_channel *master; -} subchannel_factory; +} client_channel_factory; -static void subchannel_factory_ref(grpc_subchannel_factory *scf) { - subchannel_factory *f = (subchannel_factory *)scf; +static void client_channel_factory_ref( + grpc_client_channel_factory *cc_factory) { + client_channel_factory *f = (client_channel_factory *)cc_factory; gpr_ref(&f->refs); } -static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx, - grpc_subchannel_factory *scf) { - subchannel_factory *f = (subchannel_factory *)scf; +static void client_channel_factory_unref( + grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) { + client_channel_factory *f = (client_channel_factory *)cc_factory; if (gpr_unref(&f->refs)) { - GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, "subchannel_factory"); + if (f->master != NULL) { + GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, + "client_channel_factory"); + } grpc_channel_args_destroy(f->merge_args); gpr_free(f); } } -static grpc_subchannel *subchannel_factory_create_subchannel( - grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *scf, +static grpc_subchannel *client_channel_factory_create_subchannel( + grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, grpc_subchannel_args *args) { - subchannel_factory *f = (subchannel_factory *)scf; + client_channel_factory *f = (client_channel_factory *)cc_factory; connector *c = gpr_malloc(sizeof(*c)); grpc_channel_args *final_args = grpc_channel_args_merge(args->args, f->merge_args); @@ -175,9 +179,33 @@ static grpc_subchannel *subchannel_factory_create_subchannel( return s; } -static const grpc_subchannel_factory_vtable subchannel_factory_vtable = { - subchannel_factory_ref, subchannel_factory_unref, - subchannel_factory_create_subchannel}; +static grpc_channel *client_channel_factory_create_channel( + grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, + const char *target, grpc_client_channel_type type, + grpc_channel_args *args) { + client_channel_factory *f = (client_channel_factory *)cc_factory; + grpc_channel_args *final_args = grpc_channel_args_merge(args, f->merge_args); + grpc_channel *channel = grpc_channel_create(exec_ctx, target, final_args, + GRPC_CLIENT_CHANNEL, NULL); + grpc_channel_args_destroy(final_args); + grpc_resolver *resolver = grpc_resolver_create(target, &f->base); + if (!resolver) { + GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, + "client_channel_factory_create_channel"); + return NULL; + } + + grpc_client_channel_set_resolver( + exec_ctx, grpc_channel_get_channel_stack(channel), resolver); + GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create_channel"); + + return channel; +} + +static const grpc_client_channel_factory_vtable client_channel_factory_vtable = + {client_channel_factory_ref, client_channel_factory_unref, + client_channel_factory_create_subchannel, + client_channel_factory_create_channel}; /* Create a client channel: Asynchronously: - resolve target @@ -186,38 +214,27 @@ static const grpc_subchannel_factory_vtable subchannel_factory_vtable = { grpc_channel *grpc_insecure_channel_create(const char *target, const grpc_channel_args *args, void *reserved) { - grpc_channel *channel = NULL; - grpc_resolver *resolver; - subchannel_factory *f; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE( "grpc_insecure_channel_create(target=%p, args=%p, reserved=%p)", 3, (target, args, reserved)); GPR_ASSERT(!reserved); - channel = - grpc_channel_create(&exec_ctx, target, args, GRPC_CLIENT_CHANNEL, NULL); - - f = gpr_malloc(sizeof(*f)); - f->base.vtable = &subchannel_factory_vtable; + client_channel_factory *f = gpr_malloc(sizeof(*f)); + memset(f, 0, sizeof(*f)); + f->base.vtable = &client_channel_factory_vtable; gpr_ref_init(&f->refs, 1); f->merge_args = grpc_channel_args_copy(args); - f->master = channel; - GRPC_CHANNEL_INTERNAL_REF(f->master, "subchannel_factory"); - resolver = grpc_resolver_create(target, &f->base); - if (!resolver) { - GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, f->master, "subchannel_factory"); - grpc_subchannel_factory_unref(&exec_ctx, &f->base); - grpc_exec_ctx_finish(&exec_ctx); - return NULL; - } - grpc_client_channel_set_resolver( - &exec_ctx, grpc_channel_get_channel_stack(channel), resolver); - GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "create"); - grpc_subchannel_factory_unref(&exec_ctx, &f->base); + grpc_channel *channel = client_channel_factory_create_channel( + &exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, NULL); + if (channel != NULL) { + f->master = channel; + GRPC_CHANNEL_INTERNAL_REF(f->master, "grpc_insecure_channel_create"); + } + grpc_client_channel_factory_unref(&exec_ctx, &f->base); grpc_exec_ctx_finish(&exec_ctx); - return channel; + return channel; /* may be NULL */ } diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c index 3465d2b6c4..5d30805639 100644 --- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c @@ -192,34 +192,38 @@ static const grpc_connector_vtable connector_vtable = { connector_ref, connector_unref, connector_shutdown, connector_connect}; typedef struct { - grpc_subchannel_factory base; + grpc_client_channel_factory base; gpr_refcount refs; grpc_channel_args *merge_args; grpc_channel_security_connector *security_connector; grpc_channel *master; -} subchannel_factory; +} client_channel_factory; -static void subchannel_factory_ref(grpc_subchannel_factory *scf) { - subchannel_factory *f = (subchannel_factory *)scf; +static void client_channel_factory_ref( + grpc_client_channel_factory *cc_factory) { + client_channel_factory *f = (client_channel_factory *)cc_factory; gpr_ref(&f->refs); } -static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx, - grpc_subchannel_factory *scf) { - subchannel_factory *f = (subchannel_factory *)scf; +static void client_channel_factory_unref( + grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) { + client_channel_factory *f = (client_channel_factory *)cc_factory; if (gpr_unref(&f->refs)) { GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base, - "subchannel_factory"); - GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, "subchannel_factory"); + "client_channel_factory"); + if (f->master != NULL) { + GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, + "client_channel_factory"); + } grpc_channel_args_destroy(f->merge_args); gpr_free(f); } } -static grpc_subchannel *subchannel_factory_create_subchannel( - grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *scf, +static grpc_subchannel *client_channel_factory_create_subchannel( + grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, grpc_subchannel_args *args) { - subchannel_factory *f = (subchannel_factory *)scf; + client_channel_factory *f = (client_channel_factory *)cc_factory; connector *c = gpr_malloc(sizeof(*c)); grpc_channel_args *final_args = grpc_channel_args_merge(args->args, f->merge_args); @@ -236,9 +240,37 @@ static grpc_subchannel *subchannel_factory_create_subchannel( return s; } -static const grpc_subchannel_factory_vtable subchannel_factory_vtable = { - subchannel_factory_ref, subchannel_factory_unref, - subchannel_factory_create_subchannel}; +static grpc_channel *client_channel_factory_create_channel( + grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, + const char *target, grpc_client_channel_type type, + grpc_channel_args *args) { + client_channel_factory *f = (client_channel_factory *)cc_factory; + + grpc_channel_args *final_args = grpc_channel_args_merge(args, f->merge_args); + grpc_channel *channel = grpc_channel_create(exec_ctx, target, final_args, + GRPC_CLIENT_CHANNEL, NULL); + grpc_channel_args_destroy(final_args); + + grpc_resolver *resolver = grpc_resolver_create(target, &f->base); + if (resolver != NULL) { + grpc_client_channel_set_resolver( + exec_ctx, grpc_channel_get_channel_stack(channel), resolver); + GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create"); + } else { + GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, + "client_channel_factory_create_channel"); + channel = NULL; + } + + GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base, + "client_channel_factory_create_channel"); + return channel; +} + +static const grpc_client_channel_factory_vtable client_channel_factory_vtable = + {client_channel_factory_ref, client_channel_factory_unref, + client_channel_factory_create_subchannel, + client_channel_factory_create_channel}; /* Create a secure client channel: Asynchronously: - resolve target @@ -248,13 +280,11 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds, const char *target, const grpc_channel_args *args, void *reserved) { - grpc_channel *channel; grpc_arg connector_arg; grpc_channel_args *args_copy; grpc_channel_args *new_args_from_connector; grpc_channel_security_connector *security_connector; - grpc_resolver *resolver; - subchannel_factory *f; + client_channel_factory *f; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE( @@ -284,35 +314,30 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds, new_args_from_connector != NULL ? new_args_from_connector : args, &connector_arg, 1); - channel = grpc_channel_create(&exec_ctx, target, args_copy, - GRPC_CLIENT_CHANNEL, NULL); - f = gpr_malloc(sizeof(*f)); - f->base.vtable = &subchannel_factory_vtable; + memset(f, 0, sizeof(*f)); + f->base.vtable = &client_channel_factory_vtable; gpr_ref_init(&f->refs, 1); - GRPC_SECURITY_CONNECTOR_REF(&security_connector->base, "subchannel_factory"); - f->security_connector = security_connector; + f->merge_args = grpc_channel_args_copy(args_copy); - f->master = channel; - GRPC_CHANNEL_INTERNAL_REF(channel, "subchannel_factory"); - resolver = grpc_resolver_create(target, &f->base); - if (resolver) { - grpc_client_channel_set_resolver( - &exec_ctx, grpc_channel_get_channel_stack(channel), resolver); - GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "create"); - } - grpc_subchannel_factory_unref(&exec_ctx, &f->base); - GRPC_SECURITY_CONNECTOR_UNREF(&security_connector->base, "channel_create"); grpc_channel_args_destroy(args_copy); if (new_args_from_connector != NULL) { grpc_channel_args_destroy(new_args_from_connector); } - if (!resolver) { - GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, channel, "subchannel_factory"); - channel = NULL; + GRPC_SECURITY_CONNECTOR_REF(&security_connector->base, + "grpc_secure_channel_create"); + f->security_connector = security_connector; + + grpc_channel *channel = client_channel_factory_create_channel( + &exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, NULL); + if (channel != NULL) { + f->master = channel; + GRPC_CHANNEL_INTERNAL_REF(f->master, "grpc_secure_channel_create"); } + + grpc_client_channel_factory_unref(&exec_ctx, &f->base); grpc_exec_ctx_finish(&exec_ctx); - return channel; + return channel; /* may be NULL */ } diff --git a/src/core/lib/channel/client_channel.c b/src/core/lib/channel/client_channel.c index 3f7cf1cf97..55867ba80c 100644 --- a/src/core/lib/channel/client_channel.c +++ b/src/core/lib/channel/client_channel.c @@ -114,6 +114,22 @@ static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand, grpc_lb_policy *lb_policy, grpc_connectivity_state current_state); +static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx, + channel_data *chand, + grpc_connectivity_state state, + const char *reason) { + if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE || + state == GRPC_CHANNEL_FATAL_FAILURE) && + chand->lb_policy != NULL) { + /* cancel fail-fast picks */ + grpc_lb_policy_cancel_picks( + exec_ctx, chand->lb_policy, + /* mask= */ GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY, + /* check= */ 0); + } + grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, reason); +} + static void on_lb_policy_state_changed_locked( grpc_exec_ctx *exec_ctx, lb_policy_connectivity_watcher *w) { grpc_connectivity_state publish_state = w->state; @@ -127,8 +143,8 @@ static void on_lb_policy_state_changed_locked( GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel"); w->chand->lb_policy = NULL; } - grpc_connectivity_state_set(exec_ctx, &w->chand->state_tracker, publish_state, - "lb_changed"); + set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state, + "lb_changed"); if (w->state != GRPC_CHANNEL_FATAL_FAILURE) { watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state); } @@ -200,8 +216,8 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg, } if (iomgr_success && chand->resolver) { - grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, - "new_lb+resolver"); + set_channel_connectivity_state_locked(exec_ctx, chand, state, + "new_lb+resolver"); if (lb_policy != NULL) { watch_lb_policy(exec_ctx, chand, lb_policy, state); } @@ -216,8 +232,8 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg, GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel"); chand->resolver = NULL; } - grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, - GRPC_CHANNEL_FATAL_FAILURE, "resolver_gone"); + set_channel_connectivity_state_locked( + exec_ctx, chand, GRPC_CHANNEL_FATAL_FAILURE, "resolver_gone"); gpr_mu_unlock(&chand->mu_config); } @@ -272,8 +288,8 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx, } if (op->disconnect && chand->resolver != NULL) { - grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, - GRPC_CHANNEL_FATAL_FAILURE, "disconnect"); + set_channel_connectivity_state_locked( + exec_ctx, chand, GRPC_CHANNEL_FATAL_FAILURE, "disconnect"); grpc_resolver_shutdown(exec_ctx, chand->resolver); GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel"); chand->resolver = NULL; @@ -290,6 +306,7 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx, typedef struct { grpc_metadata_batch *initial_metadata; + uint32_t initial_metadata_flags; grpc_connected_subchannel **connected_subchannel; grpc_closure *on_ready; grpc_call_element *elem; @@ -298,6 +315,7 @@ typedef struct { static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *arg, grpc_metadata_batch *initial_metadata, + uint32_t initial_metadata_flags, grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready); @@ -308,6 +326,7 @@ static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg, bool success) { } else if (cpa->connected_subchannel == NULL) { /* cancelled, do nothing */ } else if (cc_pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata, + cpa->initial_metadata_flags, cpa->connected_subchannel, cpa->on_ready)) { grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, true, NULL); } @@ -316,6 +335,7 @@ static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg, bool success) { static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp, grpc_metadata_batch *initial_metadata, + uint32_t initial_metadata_flags, grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready) { grpc_call_element *elem = elemp; @@ -349,7 +369,8 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp, GRPC_LB_POLICY_REF(lb_policy, "cc_pick_subchannel"); gpr_mu_unlock(&chand->mu_config); r = grpc_lb_policy_pick(exec_ctx, lb_policy, calld->pollset, - initial_metadata, connected_subchannel, on_ready); + initial_metadata, initial_metadata_flags, + connected_subchannel, on_ready); GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "cc_pick_subchannel"); return r; } @@ -362,6 +383,7 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp, } cpa = gpr_malloc(sizeof(*cpa)); cpa->initial_metadata = initial_metadata; + cpa->initial_metadata_flags = initial_metadata_flags; cpa->connected_subchannel = connected_subchannel; cpa->on_ready = on_ready; cpa->elem = elem; diff --git a/src/core/lib/channel/http_client_filter.c b/src/core/lib/channel/http_client_filter.c index deba23e21f..211f537c69 100644 --- a/src/core/lib/channel/http_client_filter.c +++ b/src/core/lib/channel/http_client_filter.c @@ -111,10 +111,12 @@ static void hc_mutate_op(grpc_call_element *elem, elem); /* Send : prefixed headers, which have to be before any application layer headers. */ - grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->method, - op->send_idempotent_request - ? GRPC_MDELEM_METHOD_PUT - : GRPC_MDELEM_METHOD_POST); + grpc_metadata_batch_add_head( + op->send_initial_metadata, &calld->method, + op->send_initial_metadata_flags & + GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST + ? GRPC_MDELEM_METHOD_PUT + : GRPC_MDELEM_METHOD_POST); grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->scheme, channeld->static_scheme); grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->te_trailers, diff --git a/src/core/lib/channel/subchannel_call_holder.c b/src/core/lib/channel/subchannel_call_holder.c index 22f3679bf5..a2686a380a 100644 --- a/src/core/lib/channel/subchannel_call_holder.c +++ b/src/core/lib/channel/subchannel_call_holder.c @@ -127,7 +127,7 @@ retry: break; case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL: holder->pick_subchannel(exec_ctx, holder->pick_subchannel_arg, NULL, - &holder->connected_subchannel, NULL); + 0, &holder->connected_subchannel, NULL); break; } gpr_mu_unlock(&holder->mu); @@ -145,7 +145,8 @@ retry: GRPC_CALL_STACK_REF(holder->owning_call, "pick_subchannel"); if (holder->pick_subchannel( exec_ctx, holder->pick_subchannel_arg, op->send_initial_metadata, - &holder->connected_subchannel, &holder->next_step)) { + op->send_initial_metadata_flags, &holder->connected_subchannel, + &holder->next_step)) { holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING; GRPC_CALL_STACK_UNREF(exec_ctx, holder->owning_call, "pick_subchannel"); } diff --git a/src/core/lib/channel/subchannel_call_holder.h b/src/core/lib/channel/subchannel_call_holder.h index 5cf291a266..769e22b061 100644 --- a/src/core/lib/channel/subchannel_call_holder.h +++ b/src/core/lib/channel/subchannel_call_holder.h @@ -42,6 +42,7 @@ called when the subchannel is available) */ typedef int (*grpc_subchannel_call_holder_pick_subchannel)( grpc_exec_ctx *exec_ctx, void *arg, grpc_metadata_batch *initial_metadata, + uint32_t initial_metadata_flags, grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready); typedef enum { diff --git a/src/core/lib/client_config/README.md b/src/core/lib/client_config/README.md index fff7a5af5b..7024fd540d 100644 --- a/src/core/lib/client_config/README.md +++ b/src/core/lib/client_config/README.md @@ -40,7 +40,7 @@ decisions (for example, by avoiding disconnected backends). Configured sub-channels are fully setup to participate in the grpc data plane. Their behavior is specified by a set of grpc channel filters defined at their construction. To customize this behavior, resolvers build -grpc_subchannel_factory objects, which use the decorator pattern to customize +grpc_client_channel_factory objects, which use the decorator pattern to customize construction arguments for concrete grpc_subchannel instances. diff --git a/src/core/lib/client_config/subchannel_factory.c b/src/core/lib/client_config/client_channel_factory.c index 541368ec96..d27b38d9f2 100644 --- a/src/core/lib/client_config/subchannel_factory.c +++ b/src/core/lib/client_config/client_channel_factory.c @@ -31,19 +31,27 @@ * */ -#include "src/core/lib/client_config/subchannel_factory.h" +#include "src/core/lib/client_config/client_channel_factory.h" -void grpc_subchannel_factory_ref(grpc_subchannel_factory* factory) { +void grpc_client_channel_factory_ref(grpc_client_channel_factory* factory) { factory->vtable->ref(factory); } -void grpc_subchannel_factory_unref(grpc_exec_ctx* exec_ctx, - grpc_subchannel_factory* factory) { +void grpc_client_channel_factory_unref(grpc_exec_ctx* exec_ctx, + grpc_client_channel_factory* factory) { factory->vtable->unref(exec_ctx, factory); } -grpc_subchannel* grpc_subchannel_factory_create_subchannel( - grpc_exec_ctx* exec_ctx, grpc_subchannel_factory* factory, +grpc_subchannel* grpc_client_channel_factory_create_subchannel( + grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory, grpc_subchannel_args* args) { return factory->vtable->create_subchannel(exec_ctx, factory, args); } + +grpc_channel* grpc_client_channel_factory_create_channel( + grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory, + const char* target, grpc_client_channel_type type, + grpc_channel_args* args) { + return factory->vtable->create_client_channel(exec_ctx, factory, target, type, + args); +} diff --git a/src/core/lib/client_config/subchannel_factory.h b/src/core/lib/client_config/client_channel_factory.h index 96d68a2079..0b71cd9bdb 100644 --- a/src/core/lib/client_config/subchannel_factory.h +++ b/src/core/lib/client_config/client_channel_factory.h @@ -31,36 +31,55 @@ * */ -#ifndef GRPC_CORE_LIB_CLIENT_CONFIG_SUBCHANNEL_FACTORY_H -#define GRPC_CORE_LIB_CLIENT_CONFIG_SUBCHANNEL_FACTORY_H +#ifndef GRPC_CORE_LIB_CLIENT_CONFIG_CLIENT_CHANNEL_FACTORY_H +#define GRPC_CORE_LIB_CLIENT_CONFIG_CLIENT_CHANNEL_FACTORY_H + +#include <grpc/impl/codegen/grpc_types.h> #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/client_config/subchannel.h" -typedef struct grpc_subchannel_factory grpc_subchannel_factory; -typedef struct grpc_subchannel_factory_vtable grpc_subchannel_factory_vtable; +typedef struct grpc_client_channel_factory grpc_client_channel_factory; +typedef struct grpc_client_channel_factory_vtable + grpc_client_channel_factory_vtable; + +typedef enum { + GRPC_CLIENT_CHANNEL_TYPE_REGULAR, /** for the user-level regular calls */ + GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, /** for communication with a load + balancing service */ +} grpc_client_channel_type; /** Constructor for new configured channels. Creating decorators around this type is encouraged to adapt behavior. */ -struct grpc_subchannel_factory { - const grpc_subchannel_factory_vtable *vtable; +struct grpc_client_channel_factory { + const grpc_client_channel_factory_vtable *vtable; }; -struct grpc_subchannel_factory_vtable { - void (*ref)(grpc_subchannel_factory *factory); - void (*unref)(grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory); +struct grpc_client_channel_factory_vtable { + void (*ref)(grpc_client_channel_factory *factory); + void (*unref)(grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory); grpc_subchannel *(*create_subchannel)(grpc_exec_ctx *exec_ctx, - grpc_subchannel_factory *factory, + grpc_client_channel_factory *factory, grpc_subchannel_args *args); + grpc_channel *(*create_client_channel)(grpc_exec_ctx *exec_ctx, + grpc_client_channel_factory *factory, + const char *target, + grpc_client_channel_type type, + grpc_channel_args *args); }; -void grpc_subchannel_factory_ref(grpc_subchannel_factory *factory); -void grpc_subchannel_factory_unref(grpc_exec_ctx *exec_ctx, - grpc_subchannel_factory *factory); +void grpc_client_channel_factory_ref(grpc_client_channel_factory *factory); +void grpc_client_channel_factory_unref(grpc_exec_ctx *exec_ctx, + grpc_client_channel_factory *factory); /** Create a new grpc_subchannel */ -grpc_subchannel *grpc_subchannel_factory_create_subchannel( - grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory, +grpc_subchannel *grpc_client_channel_factory_create_subchannel( + grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory, grpc_subchannel_args *args); -#endif /* GRPC_CORE_LIB_CLIENT_CONFIG_SUBCHANNEL_FACTORY_H */ +/** Create a new grpc_channel */ +grpc_channel *grpc_client_channel_factory_create_channel( + grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory, + const char *target, grpc_client_channel_type type, grpc_channel_args *args); + +#endif /* GRPC_CORE_LIB_CLIENT_CONFIG_CLIENT_CHANNEL_FACTORY_H */ diff --git a/src/core/lib/client_config/lb_policy.c b/src/core/lib/client_config/lb_policy.c index 3d23669ec2..6174162d49 100644 --- a/src/core/lib/client_config/lb_policy.c +++ b/src/core/lib/client_config/lb_policy.c @@ -101,10 +101,11 @@ void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx, int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_pollset *pollset, grpc_metadata_batch *initial_metadata, + uint32_t initial_metadata_flags, grpc_connected_subchannel **target, grpc_closure *on_complete) { return policy->vtable->pick(exec_ctx, policy, pollset, initial_metadata, - target, on_complete); + initial_metadata_flags, target, on_complete); } void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, @@ -112,6 +113,14 @@ void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, policy->vtable->cancel_pick(exec_ctx, policy, target); } +void grpc_lb_policy_cancel_picks(grpc_exec_ctx *exec_ctx, + grpc_lb_policy *policy, + uint32_t initial_metadata_flags_mask, + uint32_t initial_metadata_flags_eq) { + policy->vtable->cancel_picks(exec_ctx, policy, initial_metadata_flags_mask, + initial_metadata_flags_eq); +} + void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) { policy->vtable->exit_idle(exec_ctx, policy); } diff --git a/src/core/lib/client_config/lb_policy.h b/src/core/lib/client_config/lb_policy.h index a63e8e68df..60729ef8f9 100644 --- a/src/core/lib/client_config/lb_policy.h +++ b/src/core/lib/client_config/lb_policy.h @@ -60,9 +60,13 @@ struct grpc_lb_policy_vtable { /** implement grpc_lb_policy_pick */ int (*pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_pollset *pollset, grpc_metadata_batch *initial_metadata, + uint32_t initial_metadata_flags, grpc_connected_subchannel **target, grpc_closure *on_complete); void (*cancel_pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_connected_subchannel **target); + void (*cancel_picks)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, + uint32_t initial_metadata_flags_mask, + uint32_t initial_metadata_flags_eq); void (*ping_one)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_closure *closure); @@ -122,6 +126,7 @@ void grpc_lb_policy_init(grpc_lb_policy *policy, int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_pollset *pollset, grpc_metadata_batch *initial_metadata, + uint32_t initial_metadata_flags, grpc_connected_subchannel **target, grpc_closure *on_complete); @@ -131,6 +136,14 @@ void grpc_lb_policy_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_connected_subchannel **target); +/** Cancel all pending picks which have: + (initial_metadata_flags & initial_metadata_flags_mask) == + initial_metadata_flags_eq */ +void grpc_lb_policy_cancel_picks(grpc_exec_ctx *exec_ctx, + grpc_lb_policy *policy, + uint32_t initial_metadata_flags_mask, + uint32_t initial_metadata_flags_eq); + void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy); void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx, diff --git a/src/core/lib/client_config/lb_policy_factory.h b/src/core/lib/client_config/lb_policy_factory.h index 6f21912821..4931d4df58 100644 --- a/src/core/lib/client_config/lb_policy_factory.h +++ b/src/core/lib/client_config/lb_policy_factory.h @@ -34,8 +34,8 @@ #ifndef GRPC_CORE_LIB_CLIENT_CONFIG_LB_POLICY_FACTORY_H #define GRPC_CORE_LIB_CLIENT_CONFIG_LB_POLICY_FACTORY_H +#include "src/core/lib/client_config/client_channel_factory.h" #include "src/core/lib/client_config/lb_policy.h" -#include "src/core/lib/client_config/subchannel_factory.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/exec_ctx.h" @@ -51,7 +51,7 @@ struct grpc_lb_policy_factory { typedef struct grpc_lb_policy_args { grpc_resolved_addresses *addresses; - grpc_subchannel_factory *subchannel_factory; + grpc_client_channel_factory *client_channel_factory; } grpc_lb_policy_args; struct grpc_lb_policy_factory_vtable { diff --git a/src/core/lib/client_config/resolver_factory.h b/src/core/lib/client_config/resolver_factory.h index a5bca06475..18c7fd7d62 100644 --- a/src/core/lib/client_config/resolver_factory.h +++ b/src/core/lib/client_config/resolver_factory.h @@ -34,8 +34,8 @@ #ifndef GRPC_CORE_LIB_CLIENT_CONFIG_RESOLVER_FACTORY_H #define GRPC_CORE_LIB_CLIENT_CONFIG_RESOLVER_FACTORY_H +#include "src/core/lib/client_config/client_channel_factory.h" #include "src/core/lib/client_config/resolver.h" -#include "src/core/lib/client_config/subchannel_factory.h" #include "src/core/lib/client_config/uri_parser.h" typedef struct grpc_resolver_factory grpc_resolver_factory; @@ -49,7 +49,7 @@ struct grpc_resolver_factory { typedef struct grpc_resolver_args { grpc_uri *uri; - grpc_subchannel_factory *subchannel_factory; + grpc_client_channel_factory *client_channel_factory; } grpc_resolver_args; struct grpc_resolver_factory_vtable { diff --git a/src/core/lib/client_config/resolver_registry.c b/src/core/lib/client_config/resolver_registry.c index 5f3db273b5..5584f6692e 100644 --- a/src/core/lib/client_config/resolver_registry.c +++ b/src/core/lib/client_config/resolver_registry.c @@ -123,14 +123,14 @@ static grpc_resolver_factory *resolve_factory(const char *target, } grpc_resolver *grpc_resolver_create( - const char *target, grpc_subchannel_factory *subchannel_factory) { + const char *target, grpc_client_channel_factory *client_channel_factory) { grpc_uri *uri = NULL; grpc_resolver_factory *factory = resolve_factory(target, &uri); grpc_resolver *resolver; grpc_resolver_args args; memset(&args, 0, sizeof(args)); args.uri = uri; - args.subchannel_factory = subchannel_factory; + args.client_channel_factory = client_channel_factory; resolver = grpc_resolver_factory_create_resolver(factory, &args); grpc_uri_destroy(uri); return resolver; diff --git a/src/core/lib/client_config/resolver_registry.h b/src/core/lib/client_config/resolver_registry.h index 36c4f2fe03..b207313084 100644 --- a/src/core/lib/client_config/resolver_registry.h +++ b/src/core/lib/client_config/resolver_registry.h @@ -56,7 +56,7 @@ void grpc_register_resolver_type(grpc_resolver_factory *factory); return it. If a resolver factory was not found, return NULL. */ grpc_resolver *grpc_resolver_create( - const char *target, grpc_subchannel_factory *subchannel_factory); + const char *target, grpc_client_channel_factory *client_channel_factory); /** Find a resolver factory given a name and return an (owned-by-the-caller) * reference to it */ diff --git a/src/core/lib/client_config/subchannel.c b/src/core/lib/client_config/subchannel.c index 2889260ea4..f44e2f7404 100644 --- a/src/core/lib/client_config/subchannel.c +++ b/src/core/lib/client_config/subchannel.c @@ -54,7 +54,7 @@ #define STRONG_REF_MASK (~(gpr_atm)((1 << INTERNAL_REF_BITS) - 1)) #define GRPC_SUBCHANNEL_MIN_CONNECT_TIMEOUT_SECONDS 20 -#define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 1 +#define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 2 #define GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER 1.6 #define GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS 120 #define GRPC_SUBCHANNEL_RECONNECT_JITTER 0.2 diff --git a/src/core/lib/iomgr/ev_poll_and_epoll_posix.c b/src/core/lib/iomgr/ev_poll_and_epoll_posix.c index dba335490b..3c8127e1a8 100644 --- a/src/core/lib/iomgr/ev_poll_and_epoll_posix.c +++ b/src/core/lib/iomgr/ev_poll_and_epoll_posix.c @@ -1,6 +1,6 @@ /* * - * Copyright 2015-2016, Google Inc. + * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/core/lib/iomgr/ev_posix.c b/src/core/lib/iomgr/ev_posix.c index 235a7df08d..0eb95a2e09 100644 --- a/src/core/lib/iomgr/ev_posix.c +++ b/src/core/lib/iomgr/ev_posix.c @@ -1,6 +1,6 @@ /* * - * Copyright 2015-2016, Google Inc. + * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/core/lib/iomgr/ev_posix.h b/src/core/lib/iomgr/ev_posix.h index 9d27b2bcda..1fa9f5ef2d 100644 --- a/src/core/lib/iomgr/ev_posix.h +++ b/src/core/lib/iomgr/ev_posix.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015-2016, Google Inc. + * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 37cc724b53..ba94852f9a 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -81,11 +81,11 @@ typedef enum { /* Status came from the application layer overriding whatever the wire says */ STATUS_FROM_API_OVERRIDE = 0, - /* Status was created by some internal channel stack operation */ - STATUS_FROM_CORE, /* Status came from 'the wire' - or somewhere below the surface layer */ STATUS_FROM_WIRE, + /* Status was created by some internal channel stack operation */ + STATUS_FROM_CORE, /* Status came from the server sending status */ STATUS_FROM_SERVER_STATUS, STATUS_SOURCE_COUNT @@ -1110,6 +1110,9 @@ static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp, bool success) { gpr_mu_lock(&call->mu); if (bctl->send_initial_metadata) { + if (!success) { + set_status_code(call, STATUS_FROM_CORE, GRPC_STATUS_UNAVAILABLE); + } grpc_metadata_batch_destroy( &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]); } @@ -1232,8 +1235,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, call->metadata_batch[0][0].deadline = call->send_deadline; stream_op.send_initial_metadata = &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]; - stream_op.send_idempotent_request = - (op->flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) != 0; + stream_op.send_initial_metadata_flags = op->flags; break; case GRPC_OP_SEND_MESSAGE: if (!are_write_flags_valid(op->flags)) { diff --git a/src/core/lib/surface/channel.h b/src/core/lib/surface/channel.h index 640fd7e137..68afac6fac 100644 --- a/src/core/lib/surface/channel.h +++ b/src/core/lib/surface/channel.h @@ -35,7 +35,7 @@ #define GRPC_CORE_LIB_SURFACE_CHANNEL_H #include "src/core/lib/channel/channel_stack.h" -#include "src/core/lib/client_config/subchannel_factory.h" +#include "src/core/lib/client_config/client_channel_factory.h" #include "src/core/lib/surface/channel_stack_type.h" grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target, diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index 460e4dcedc..bb1120ee3a 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -101,9 +101,9 @@ typedef struct grpc_transport_stream_op { /** Send initial metadata to the peer, from the provided metadata batch. idempotent_request MUST be set if this is non-null */ grpc_metadata_batch *send_initial_metadata; - /** Iff send_initial_metadata != NULL, flags if this is an idempotent request - or not */ - bool send_idempotent_request; + /** Iff send_initial_metadata != NULL, flags associated with + send_initial_metadata: a bitfield of GRPC_INITIAL_METADATA_xxx */ + uint32_t send_initial_metadata_flags; /** Send trailing metadata to the peer, from the provided metadata batch. */ grpc_metadata_batch *send_trailing_metadata; diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc index bf6423128a..c277d7ebe8 100644 --- a/src/cpp/client/client_context.cc +++ b/src/cpp/client/client_context.cc @@ -60,6 +60,8 @@ static ClientContext::GlobalCallbacks* g_client_callbacks = ClientContext::ClientContext() : initial_metadata_received_(false), + fail_fast_(true), + idempotent_(false), call_(nullptr), call_canceled_(false), deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)), diff --git a/src/csharp/Grpc.Core/CallInvoker.cs b/src/csharp/Grpc.Core/CallInvoker.cs new file mode 100644 index 0000000000..39199b1fd5 --- /dev/null +++ b/src/csharp/Grpc.Core/CallInvoker.cs @@ -0,0 +1,84 @@ +#region Copyright notice and license + +// Copyright 2015-2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System.Threading.Tasks; +using Grpc.Core.Internal; + +namespace Grpc.Core +{ + /// <summary> + /// Abstraction of client-side RPC invocation. + /// </summary> + /// <seealso cref="Calls"/> + public abstract class CallInvoker + { + /// <summary> + /// Invokes a simple remote call in a blocking fashion. + /// </summary> + public abstract TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request) + where TRequest : class + where TResponse : class; + + /// <summary> + /// Invokes a simple remote call asynchronously. + /// </summary> + public abstract AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request) + where TRequest : class + where TResponse : class; + + /// <summary> + /// Invokes a server streaming call asynchronously. + /// In server streaming scenario, client sends on request and server responds with a stream of responses. + /// </summary> + public abstract AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request) + where TRequest : class + where TResponse : class; + + /// <summary> + /// Invokes a client streaming call asynchronously. + /// In client streaming scenario, client sends a stream of requests and server responds with a single response. + /// </summary> + public abstract AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options) + where TRequest : class + where TResponse : class; + + /// <summary> + /// Invokes a duplex streaming call asynchronously. + /// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses. + /// The response stream is completely independent and both side can be sending messages at the same time. + /// </summary> + public abstract AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options) + where TRequest : class + where TResponse : class; + } +} diff --git a/src/csharp/Grpc.Core/ClientBase.cs b/src/csharp/Grpc.Core/ClientBase.cs index e5b398062b..5517233e3c 100644 --- a/src/csharp/Grpc.Core/ClientBase.cs +++ b/src/csharp/Grpc.Core/ClientBase.cs @@ -1,6 +1,6 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -31,93 +31,156 @@ #endregion -using System; -using System.Text.RegularExpressions; -using System.Threading.Tasks; +using Grpc.Core.Internal; +using Grpc.Core.Utils; namespace Grpc.Core { /// <summary> - /// Interceptor for call headers. + /// Generic base class for client-side stubs. /// </summary> - /// <remarks>Header interceptor is no longer to recommented way to perform authentication. - /// For header (initial metadata) based auth such as OAuth2 or JWT access token, use <see cref="MetadataCredentials"/>. - /// </remarks> - public delegate void HeaderInterceptor(IMethod method, Metadata metadata); + public abstract class ClientBase<T> : ClientBase + where T : ClientBase<T> + { + /// <summary> + /// Initializes a new instance of <c>ClientBase</c> class that + /// throws <c>NotImplementedException</c> upon invocation of any RPC. + /// This constructor is only provided to allow creation of test doubles + /// for client classes (e.g. mocking requires a parameterless constructor). + /// </summary> + protected ClientBase() : base() + { + } + + /// <summary> + /// Initializes a new instance of <c>ClientBase</c> class. + /// </summary> + /// <param name="configuration">The configuration.</param> + protected ClientBase(ClientBaseConfiguration configuration) : base(configuration) + { + } + + /// <summary> + /// Initializes a new instance of <c>ClientBase</c> class. + /// </summary> + /// <param name="channel">The channel to use for remote call invocation.</param> + public ClientBase(Channel channel) : base(channel) + { + } + + /// <summary> + /// Initializes a new instance of <c>ClientBase</c> class. + /// </summary> + /// <param name="callInvoker">The <c>CallInvoker</c> for remote call invocation.</param> + public ClientBase(CallInvoker callInvoker) : base(callInvoker) + { + } + + /// <summary> + /// Creates a new client that sets host field for calls explicitly. + /// gRPC supports multiple "hosts" being served by a single server. + /// By default (if a client was not created by calling this method), + /// host <c>null</c> with the meaning "use default host" is used. + /// </summary> + public T WithHost(string host) + { + var newConfiguration = this.Configuration.WithHost(host); + return NewInstance(newConfiguration); + } + + /// <summary> + /// Creates a new instance of client from given <c>ClientBaseConfiguration</c>. + /// </summary> + protected abstract T NewInstance(ClientBaseConfiguration configuration); + } /// <summary> /// Base class for client-side stubs. /// </summary> public abstract class ClientBase { - readonly Channel channel; + readonly ClientBaseConfiguration configuration; + readonly CallInvoker callInvoker; + + /// <summary> + /// Initializes a new instance of <c>ClientBase</c> class that + /// throws <c>NotImplementedException</c> upon invocation of any RPC. + /// This constructor is only provided to allow creation of test doubles + /// for client classes (e.g. mocking requires a parameterless constructor). + /// </summary> + protected ClientBase() : this(new UnimplementedCallInvoker()) + { + } + + /// <summary> + /// Initializes a new instance of <c>ClientBase</c> class. + /// </summary> + /// <param name="configuration">The configuration.</param> + protected ClientBase(ClientBaseConfiguration configuration) + { + this.configuration = GrpcPreconditions.CheckNotNull(configuration, "configuration"); + this.callInvoker = configuration.CreateDecoratedCallInvoker(); + } /// <summary> /// Initializes a new instance of <c>ClientBase</c> class. /// </summary> /// <param name="channel">The channel to use for remote call invocation.</param> - public ClientBase(Channel channel) + public ClientBase(Channel channel) : this(new DefaultCallInvoker(channel)) { - this.channel = channel; } /// <summary> - /// Can be used to register a custom header interceptor. - /// The interceptor is invoked each time a new call on this client is started. - /// It is not recommented to use header interceptor to add auth headers to RPC calls. + /// Initializes a new instance of <c>ClientBase</c> class. /// </summary> - /// <seealso cref="HeaderInterceptor"/> - public HeaderInterceptor HeaderInterceptor + /// <param name="callInvoker">The <c>CallInvoker</c> for remote call invocation.</param> + public ClientBase(CallInvoker callInvoker) : this(new ClientBaseConfiguration(callInvoker, null)) { - get; - set; } /// <summary> - /// gRPC supports multiple "hosts" being served by a single server. - /// This property can be used to set the target host explicitly. - /// By default, this will be set to <c>null</c> with the meaning - /// "use default host". + /// Gets the call invoker. /// </summary> - public string Host + protected CallInvoker CallInvoker { - get; - set; + get { return this.callInvoker; } } /// <summary> - /// Channel associated with this client. + /// Gets the configuration. /// </summary> - public Channel Channel + internal ClientBaseConfiguration Configuration { - get - { - return this.channel; - } + get { return this.configuration; } } /// <summary> - /// Creates a new call to given method. + /// Represents configuration of ClientBase. The class itself is visible to + /// subclasses, but contents are marked as internal to make the instances opaque. + /// The verbose name of this class was chosen to make name clash in generated code + /// less likely. /// </summary> - /// <param name="method">The method to invoke.</param> - /// <param name="options">The call options.</param> - /// <typeparam name="TRequest">Request message type.</typeparam> - /// <typeparam name="TResponse">Response message type.</typeparam> - /// <returns>The call invocation details.</returns> - protected CallInvocationDetails<TRequest, TResponse> CreateCall<TRequest, TResponse>(Method<TRequest, TResponse> method, CallOptions options) - where TRequest : class - where TResponse : class + protected internal class ClientBaseConfiguration { - var interceptor = HeaderInterceptor; - if (interceptor != null) + readonly CallInvoker undecoratedCallInvoker; + readonly string host; + + internal ClientBaseConfiguration(CallInvoker undecoratedCallInvoker, string host) + { + this.undecoratedCallInvoker = GrpcPreconditions.CheckNotNull(undecoratedCallInvoker); + this.host = host; + } + + internal CallInvoker CreateDecoratedCallInvoker() + { + return new InterceptingCallInvoker(undecoratedCallInvoker, hostInterceptor: (h) => host); + } + + internal ClientBaseConfiguration WithHost(string host) { - if (options.Headers == null) - { - options = options.WithHeaders(new Metadata()); - } - interceptor(method, options.Headers); + GrpcPreconditions.CheckNotNull(host, "host"); + return new ClientBaseConfiguration(this.undecoratedCallInvoker, host); } - return new CallInvocationDetails<TRequest, TResponse>(channel, method, Host, options); } } } diff --git a/src/csharp/Grpc.Core/DefaultCallInvoker.cs b/src/csharp/Grpc.Core/DefaultCallInvoker.cs new file mode 100644 index 0000000000..1a99e41153 --- /dev/null +++ b/src/csharp/Grpc.Core/DefaultCallInvoker.cs @@ -0,0 +1,112 @@ +#region Copyright notice and license + +// Copyright 2015-2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System.Threading.Tasks; +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// <summary> + /// Invokes client RPCs using <see cref="Calls"/>. + /// </summary> + public class DefaultCallInvoker : CallInvoker + { + readonly Channel channel; + + /// <summary> + /// Initializes a new instance of the <see cref="Grpc.Core.DefaultCallInvoker"/> class. + /// </summary> + /// <param name="channel">Channel to use.</param> + public DefaultCallInvoker(Channel channel) + { + this.channel = GrpcPreconditions.CheckNotNull(channel); + } + + /// <summary> + /// Invokes a simple remote call in a blocking fashion. + /// </summary> + public override TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request) + { + var call = CreateCall(method, host, options); + return Calls.BlockingUnaryCall(call, request); + } + + /// <summary> + /// Invokes a simple remote call asynchronously. + /// </summary> + public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request) + { + var call = CreateCall(method, host, options); + return Calls.AsyncUnaryCall(call, request); + } + + /// <summary> + /// Invokes a server streaming call asynchronously. + /// In server streaming scenario, client sends on request and server responds with a stream of responses. + /// </summary> + public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request) + { + var call = CreateCall(method, host, options); + return Calls.AsyncServerStreamingCall(call, request); + } + + /// <summary> + /// Invokes a client streaming call asynchronously. + /// In client streaming scenario, client sends a stream of requests and server responds with a single response. + /// </summary> + public override AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options) + { + var call = CreateCall(method, host, options); + return Calls.AsyncClientStreamingCall(call); + } + + /// <summary> + /// Invokes a duplex streaming call asynchronously. + /// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses. + /// The response stream is completely independent and both side can be sending messages at the same time. + /// </summary> + public override AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options) + { + var call = CreateCall(method, host, options); + return Calls.AsyncDuplexStreamingCall(call); + } + + protected virtual CallInvocationDetails<TRequest, TResponse> CreateCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options) + where TRequest : class + where TResponse : class + { + return new CallInvocationDetails<TRequest, TResponse>(channel, method, host, options); + } + } +} diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index 3189835ccd..251a688946 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -129,6 +129,10 @@ <Compile Include="Profiling\Profilers.cs" /> <Compile Include="Internal\DefaultSslRootsOverride.cs" /> <Compile Include="Utils\GrpcPreconditions.cs" /> + <Compile Include="CallInvoker.cs" /> + <Compile Include="DefaultCallInvoker.cs" /> + <Compile Include="Internal\UnimplementedCallInvoker.cs" /> + <Compile Include="Internal\InterceptingCallInvoker.cs" /> </ItemGroup> <ItemGroup> <None Include="Grpc.Core.nuspec" /> diff --git a/src/csharp/Grpc.Core/Internal/InterceptingCallInvoker.cs b/src/csharp/Grpc.Core/Internal/InterceptingCallInvoker.cs new file mode 100644 index 0000000000..ef48dc7121 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/InterceptingCallInvoker.cs @@ -0,0 +1,134 @@ +#region Copyright notice and license + +// Copyright 2015-2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// <summary> + /// Decorates an underlying <c>CallInvoker</c> to intercept call invocations. + /// </summary> + internal class InterceptingCallInvoker : CallInvoker + { + readonly CallInvoker callInvoker; + readonly Func<string, string> hostInterceptor; + readonly Func<CallOptions, CallOptions> callOptionsInterceptor; + + /// <summary> + /// Initializes a new instance of the <see cref="Grpc.Core.InterceptingCallInvoker"/> class. + /// </summary> + public InterceptingCallInvoker(CallInvoker callInvoker, + Func<string, string> hostInterceptor = null, + Func<CallOptions, CallOptions> callOptionsInterceptor = null) + { + this.callInvoker = GrpcPreconditions.CheckNotNull(callInvoker); + this.hostInterceptor = hostInterceptor; + this.callOptionsInterceptor = callOptionsInterceptor; + } + + /// <summary> + /// Intercepts a unary call. + /// </summary> + public override TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request) + { + host = InterceptHost(host); + options = InterceptCallOptions(options); + return callInvoker.BlockingUnaryCall(method, host, options, request); + } + + /// <summary> + /// Invokes a simple remote call asynchronously. + /// </summary> + public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request) + { + host = InterceptHost(host); + options = InterceptCallOptions(options); + return callInvoker.AsyncUnaryCall(method, host, options, request); + } + + /// <summary> + /// Invokes a server streaming call asynchronously. + /// In server streaming scenario, client sends on request and server responds with a stream of responses. + /// </summary> + public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request) + { + host = InterceptHost(host); + options = InterceptCallOptions(options); + return callInvoker.AsyncServerStreamingCall(method, host, options, request); + } + + /// <summary> + /// Invokes a client streaming call asynchronously. + /// In client streaming scenario, client sends a stream of requests and server responds with a single response. + /// </summary> + public override AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options) + { + host = InterceptHost(host); + options = InterceptCallOptions(options); + return callInvoker.AsyncClientStreamingCall(method, host, options); + } + + /// <summary> + /// Invokes a duplex streaming call asynchronously. + /// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses. + /// The response stream is completely independent and both side can be sending messages at the same time. + /// </summary> + public override AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options) + { + host = InterceptHost(host); + options = InterceptCallOptions(options); + return callInvoker.AsyncDuplexStreamingCall(method, host, options); + } + + private string InterceptHost(string host) + { + if (hostInterceptor == null) + { + return host; + } + return hostInterceptor(host); + } + + private CallOptions InterceptCallOptions(CallOptions options) + { + if (callOptionsInterceptor == null) + { + return options; + } + return callOptionsInterceptor(options); + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/UnimplementedCallInvoker.cs b/src/csharp/Grpc.Core/Internal/UnimplementedCallInvoker.cs new file mode 100644 index 0000000000..0c7340873b --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/UnimplementedCallInvoker.cs @@ -0,0 +1,75 @@ +#region Copyright notice and license + +// Copyright 2015-2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// <summary> + /// Call invoker that throws <c>NotImplementedException</c> for all requests. + /// </summary> + internal class UnimplementedCallInvoker : CallInvoker + { + public UnimplementedCallInvoker() + { + } + + public override TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request) + { + throw new NotImplementedException(); + } + + public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request) + { + throw new NotImplementedException(); + } + + public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request) + { + throw new NotImplementedException(); + } + + public override AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options) + { + throw new NotImplementedException(); + } + + public override AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/csharp/Grpc.Examples.MathClient/MathClient.cs b/src/csharp/Grpc.Examples.MathClient/MathClient.cs index 64e429ed5a..aadef6833d 100644 --- a/src/csharp/Grpc.Examples.MathClient/MathClient.cs +++ b/src/csharp/Grpc.Examples.MathClient/MathClient.cs @@ -1,5 +1,5 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -40,7 +40,7 @@ namespace Math public static void Main(string[] args) { var channel = new Channel("127.0.0.1", 23456, ChannelCredentials.Insecure); - Math.IMathClient client = new Math.MathClient(channel); + Math.MathClient client = new Math.MathClient(channel); MathExamples.DivExample(client); MathExamples.DivAsyncExample(client).Wait(); diff --git a/src/csharp/Grpc.Examples/MathExamples.cs b/src/csharp/Grpc.Examples/MathExamples.cs index 8009ccbbfa..6075420974 100644 --- a/src/csharp/Grpc.Examples/MathExamples.cs +++ b/src/csharp/Grpc.Examples/MathExamples.cs @@ -1,5 +1,5 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -38,19 +38,19 @@ namespace Math { public static class MathExamples { - public static void DivExample(Math.IMathClient client) + public static void DivExample(Math.MathClient client) { DivReply result = client.Div(new DivArgs { Dividend = 10, Divisor = 3 }); Console.WriteLine("Div Result: " + result); } - public static async Task DivAsyncExample(Math.IMathClient client) + public static async Task DivAsyncExample(Math.MathClient client) { DivReply result = await client.DivAsync(new DivArgs { Dividend = 4, Divisor = 5 }); Console.WriteLine("DivAsync Result: " + result); } - public static async Task FibExample(Math.IMathClient client) + public static async Task FibExample(Math.MathClient client) { using (var call = client.Fib(new FibArgs { Limit = 5 })) { @@ -59,7 +59,7 @@ namespace Math } } - public static async Task SumExample(Math.IMathClient client) + public static async Task SumExample(Math.MathClient client) { var numbers = new List<Num> { @@ -75,7 +75,7 @@ namespace Math } } - public static async Task DivManyExample(Math.IMathClient client) + public static async Task DivManyExample(Math.MathClient client) { var divArgsList = new List<DivArgs> { @@ -90,7 +90,7 @@ namespace Math } } - public static async Task DependendRequestsExample(Math.IMathClient client) + public static async Task DependendRequestsExample(Math.MathClient client) { var numbers = new List<Num> { diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index a6e878d0f4..f3bb0d1cdc 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -52,6 +52,7 @@ namespace Math { } // client interface + [System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")] public interface IMathClient { global::Math.DivReply Div(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); @@ -67,6 +68,7 @@ namespace Math { } // server-side interface + [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")] public interface IMath { Task<global::Math.DivReply> Div(global::Math.DivArgs request, ServerCallContext context); @@ -75,61 +77,92 @@ namespace Math { Task<global::Math.Num> Sum(IAsyncStreamReader<global::Math.Num> requestStream, ServerCallContext context); } + // server-side abstract class + public abstract class MathBase + { + public virtual Task<global::Math.DivReply> Div(global::Math.DivArgs request, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + public virtual Task DivMany(IAsyncStreamReader<global::Math.DivArgs> requestStream, IServerStreamWriter<global::Math.DivReply> responseStream, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + public virtual Task Fib(global::Math.FibArgs request, IServerStreamWriter<global::Math.Num> responseStream, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + public virtual Task<global::Math.Num> Sum(IAsyncStreamReader<global::Math.Num> requestStream, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + } + // client stub - public class MathClient : ClientBase, IMathClient + public class MathClient : ClientBase<MathClient>, IMathClient { public MathClient(Channel channel) : base(channel) { } - public global::Math.DivReply Div(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public MathClient(CallInvoker callInvoker) : base(callInvoker) { - var call = CreateCall(__Method_Div, new CallOptions(headers, deadline, cancellationToken)); - return Calls.BlockingUnaryCall(call, request); } - public global::Math.DivReply Div(global::Math.DivArgs request, CallOptions options) + ///<summary>Protected parameterless constructor to allow creation of test doubles.</summary> + protected MathClient() : base() { - var call = CreateCall(__Method_Div, options); - return Calls.BlockingUnaryCall(call, request); } - public AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + ///<summary>Protected constructor to allow creation of configured clients.</summary> + protected MathClient(ClientBaseConfiguration configuration) : base(configuration) { - var call = CreateCall(__Method_Div, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncUnaryCall(call, request); } - public AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, CallOptions options) + + public virtual global::Math.DivReply Div(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_Div, options); - return Calls.AsyncUnaryCall(call, request); + return Div(request, new CallOptions(headers, deadline, cancellationToken)); } - public AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual global::Math.DivReply Div(global::Math.DivArgs request, CallOptions options) { - var call = CreateCall(__Method_DivMany, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncDuplexStreamingCall(call); + return CallInvoker.BlockingUnaryCall(__Method_Div, null, options, request); } - public AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(CallOptions options) + public virtual AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_DivMany, options); - return Calls.AsyncDuplexStreamingCall(call); + return DivAsync(request, new CallOptions(headers, deadline, cancellationToken)); } - public AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, CallOptions options) { - var call = CreateCall(__Method_Fib, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncServerStreamingCall(call, request); + return CallInvoker.AsyncUnaryCall(__Method_Div, null, options, request); } - public AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, CallOptions options) + public virtual AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_Fib, options); - return Calls.AsyncServerStreamingCall(call, request); + return DivMany(new CallOptions(headers, deadline, cancellationToken)); } - public AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(CallOptions options) { - var call = CreateCall(__Method_Sum, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncClientStreamingCall(call); + return CallInvoker.AsyncDuplexStreamingCall(__Method_DivMany, null, options); } - public AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(CallOptions options) + public virtual AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_Sum, options); - return Calls.AsyncClientStreamingCall(call); + return Fib(request, new CallOptions(headers, deadline, cancellationToken)); + } + public virtual AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, CallOptions options) + { + return CallInvoker.AsyncServerStreamingCall(__Method_Fib, null, options, request); + } + public virtual AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + { + return Sum(new CallOptions(headers, deadline, cancellationToken)); + } + public virtual AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(CallOptions options) + { + return CallInvoker.AsyncClientStreamingCall(__Method_Sum, null, options); + } + protected override MathClient NewInstance(ClientBaseConfiguration configuration) + { + return new MathClient(configuration); } } @@ -143,6 +176,16 @@ namespace Math { .AddMethod(__Method_Sum, serviceImpl.Sum).Build(); } + // creates service definition that can be registered with a server + public static ServerServiceDefinition BindService(MathBase serviceImpl) + { + return ServerServiceDefinition.CreateBuilder(__ServiceName) + .AddMethod(__Method_Div, serviceImpl.Div) + .AddMethod(__Method_DivMany, serviceImpl.DivMany) + .AddMethod(__Method_Fib, serviceImpl.Fib) + .AddMethod(__Method_Sum, serviceImpl.Sum).Build(); + } + // creates a new client public static MathClient NewClient(Channel channel) { diff --git a/src/csharp/Grpc.Examples/MathServiceImpl.cs b/src/csharp/Grpc.Examples/MathServiceImpl.cs index 71dc655e46..79c56e57a8 100644 --- a/src/csharp/Grpc.Examples/MathServiceImpl.cs +++ b/src/csharp/Grpc.Examples/MathServiceImpl.cs @@ -1,6 +1,6 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -43,14 +43,14 @@ namespace Math /// <summary> /// Implementation of MathService server /// </summary> - public class MathServiceImpl : Math.IMath + public class MathServiceImpl : Math.MathBase { - public Task<DivReply> Div(DivArgs request, ServerCallContext context) + public override Task<DivReply> Div(DivArgs request, ServerCallContext context) { return Task.FromResult(DivInternal(request)); } - public async Task Fib(FibArgs request, IServerStreamWriter<Num> responseStream, ServerCallContext context) + public override async Task Fib(FibArgs request, IServerStreamWriter<Num> responseStream, ServerCallContext context) { if (request.Limit <= 0) { @@ -72,7 +72,7 @@ namespace Math } } - public async Task<Num> Sum(IAsyncStreamReader<Num> requestStream, ServerCallContext context) + public override async Task<Num> Sum(IAsyncStreamReader<Num> requestStream, ServerCallContext context) { long sum = 0; await requestStream.ForEachAsync(async num => @@ -82,7 +82,7 @@ namespace Math return new Num { Num_ = sum }; } - public async Task DivMany(IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream, ServerCallContext context) + public override async Task DivMany(IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream, ServerCallContext context) { await requestStream.ForEachAsync(async divArgs => await responseStream.WriteAsync(DivInternal(divArgs))); } diff --git a/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs index 8318e84277..fb292945a6 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs +++ b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs @@ -49,7 +49,7 @@ namespace Grpc.HealthCheck.Tests const string Host = "localhost"; Server server; Channel channel; - Grpc.Health.V1.Health.IHealthClient client; + Grpc.Health.V1.Health.HealthClient client; Grpc.HealthCheck.HealthServiceImpl serviceImpl; [TestFixtureSetUp] diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs index 68320eb5c2..72e11cca3a 100644 --- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs +++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs @@ -29,6 +29,7 @@ namespace Grpc.Health.V1 { } // client interface + [System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")] public interface IHealthClient { global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); @@ -38,36 +39,59 @@ namespace Grpc.Health.V1 { } // server-side interface + [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")] public interface IHealth { Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context); } + // server-side abstract class + public abstract class HealthBase + { + public virtual Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + } + // client stub - public class HealthClient : ClientBase, IHealthClient + public class HealthClient : ClientBase<HealthClient>, IHealthClient { public HealthClient(Channel channel) : base(channel) { } - public global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public HealthClient(CallInvoker callInvoker) : base(callInvoker) { - var call = CreateCall(__Method_Check, new CallOptions(headers, deadline, cancellationToken)); - return Calls.BlockingUnaryCall(call, request); } - public global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options) + ///<summary>Protected parameterless constructor to allow creation of test doubles.</summary> + protected HealthClient() : base() + { + } + ///<summary>Protected constructor to allow creation of configured clients.</summary> + protected HealthClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + public virtual global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_Check, options); - return Calls.BlockingUnaryCall(call, request); + return Check(request, new CallOptions(headers, deadline, cancellationToken)); } - public AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options) { - var call = CreateCall(__Method_Check, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncUnaryCall(call, request); + return CallInvoker.BlockingUnaryCall(__Method_Check, null, options, request); } - public AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options) + public virtual AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_Check, options); - return Calls.AsyncUnaryCall(call, request); + return CheckAsync(request, new CallOptions(headers, deadline, cancellationToken)); + } + public virtual AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_Check, null, options, request); + } + protected override HealthClient NewInstance(ClientBaseConfiguration configuration) + { + return new HealthClient(configuration); } } @@ -78,6 +102,13 @@ namespace Grpc.Health.V1 { .AddMethod(__Method_Check, serviceImpl.Check).Build(); } + // creates service definition that can be registered with a server + public static ServerServiceDefinition BindService(HealthBase serviceImpl) + { + return ServerServiceDefinition.CreateBuilder(__ServiceName) + .AddMethod(__Method_Check, serviceImpl.Check).Build(); + } + // creates a new client public static HealthClient NewClient(Channel channel) { diff --git a/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs b/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs index a6e82aa0d4..d0406ece00 100644 --- a/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs +++ b/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs @@ -51,7 +51,7 @@ namespace Grpc.HealthCheck /// server.AddServiceDefinition(Grpc.Health.V1.Health.BindService(serviceImpl)); /// </code> /// </summary> - public class HealthServiceImpl : Grpc.Health.V1.Health.IHealth + public class HealthServiceImpl : Grpc.Health.V1.Health.HealthBase { private readonly object myLock = new object(); private readonly Dictionary<string, HealthCheckResponse.Types.ServingStatus> statusMap = @@ -99,7 +99,7 @@ namespace Grpc.HealthCheck /// <param name="request">The check request.</param> /// <param name="context">The call context.</param> /// <returns>The asynchronous response.</returns> - public Task<HealthCheckResponse> Check(HealthCheckRequest request, ServerCallContext context) + public override Task<HealthCheckResponse> Check(HealthCheckRequest request, ServerCallContext context) { lock (myLock) { diff --git a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs index 7e7bc713a0..07f2703d4a 100644 --- a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs +++ b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs @@ -1,6 +1,6 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -44,19 +44,19 @@ namespace Grpc.Testing /// <summary> /// Implementation of BenchmarkService server /// </summary> - public class BenchmarkServiceImpl : BenchmarkService.IBenchmarkService + public class BenchmarkServiceImpl : BenchmarkService.BenchmarkServiceBase { public BenchmarkServiceImpl() { } - public Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context) + public override Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context) { var response = new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) }; return Task.FromResult(response); } - public async Task StreamingCall(IAsyncStreamReader<SimpleRequest> requestStream, IServerStreamWriter<SimpleResponse> responseStream, ServerCallContext context) + public override async Task StreamingCall(IAsyncStreamReader<SimpleRequest> requestStream, IServerStreamWriter<SimpleResponse> responseStream, ServerCallContext context) { await requestStream.ForEachAsync(async request => { diff --git a/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs b/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs index 5bfc89d591..0bcacf76e5 100644 --- a/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs +++ b/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs @@ -112,7 +112,7 @@ namespace Grpc.IntegrationTesting readonly PayloadConfig payloadConfig; readonly Histogram histogram; - readonly BenchmarkService.IBenchmarkServiceClient client; + readonly BenchmarkService.BenchmarkServiceClient client; readonly Task runnerTask; readonly CancellationTokenSource stoppedCts; readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch(); diff --git a/src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs b/src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs new file mode 100644 index 0000000000..37786b6c30 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs @@ -0,0 +1,106 @@ +#region Copyright notice and license + +// Copyright 2015-2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Utils; +using Grpc.Testing; +using Moq; +using NUnit.Framework; + +namespace Grpc.IntegrationTesting +{ + public class GeneratedClientTest + { + TestService.TestServiceClient unimplementedClient = new UnimplementedTestServiceClient(); + + [Test] + public void ExpandedParamOverloadCanBeMocked() + { + var expected = new SimpleResponse(); + + var mockClient = new Mock<TestService.TestServiceClient>(); + // mocking is relatively clumsy because one needs to specify value for all the optional params. + mockClient.Setup(m => m.UnaryCall(It.IsAny<SimpleRequest>(), null, null, CancellationToken.None)).Returns(expected); + + Assert.AreSame(expected, mockClient.Object.UnaryCall(new SimpleRequest())); + } + + [Test] + public void CallOptionsOverloadCanBeMocked() + { + var expected = new SimpleResponse(); + + var mockClient = new Mock<TestService.TestServiceClient>(); + mockClient.Setup(m => m.UnaryCall(It.IsAny<SimpleRequest>(), It.IsAny<CallOptions>())).Returns(expected); + + Assert.AreSame(expected, mockClient.Object.UnaryCall(new SimpleRequest(), new CallOptions())); + } + + [Test] + public void DefaultMethodStubThrows_UnaryCall() + { + Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.UnaryCall(new SimpleRequest())); + } + + [Test] + public void DefaultMethodStubThrows_ClientStreaming() + { + Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.StreamingInputCall()); + } + + [Test] + public void DefaultMethodStubThrows_ServerStreaming() + { + Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.StreamingOutputCall(new StreamingOutputCallRequest())); + } + + [Test] + public void DefaultMethodStubThrows_DuplexStreaming() + { + Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.FullDuplexCall()); + } + + /// <summary> + /// Subclass of the generated client that doesn't override any method stubs. + /// </summary> + private class UnimplementedTestServiceClient : TestService.TestServiceClient + { + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/GeneratedServiceBaseTest.cs b/src/csharp/Grpc.IntegrationTesting/GeneratedServiceBaseTest.cs new file mode 100644 index 0000000000..99aa729030 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/GeneratedServiceBaseTest.cs @@ -0,0 +1,116 @@ +#region Copyright notice and license + +// Copyright 2015-2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Utils; +using Grpc.Testing; +using Moq; +using NUnit.Framework; + +namespace Grpc.IntegrationTesting +{ + public class GeneratedServiceBaseTest + { + const string Host = "localhost"; + Server server; + Channel channel; + TestService.TestServiceClient client; + + [SetUp] + public void Init() + { + server = new Server + { + Services = { TestService.BindService(new UnimplementedTestServiceImpl()) }, + Ports = { { Host, ServerPort.PickUnused, SslServerCredentials.Insecure } } + }; + server.Start(); + channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure); + client = TestService.NewClient(channel); + } + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public void UnimplementedByDefault_Unary() + { + var ex = Assert.Throws<RpcException>(() => client.UnaryCall(new SimpleRequest { })); + Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode); + } + + [Test] + public async Task UnimplementedByDefault_ClientStreaming() + { + var call = client.StreamingInputCall(); + + var ex = Assert.Throws<RpcException>(async () => await call); + Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode); + } + + [Test] + public async Task UnimplementedByDefault_ServerStreamingCall() + { + var call = client.StreamingOutputCall(new StreamingOutputCallRequest()); + + var ex = Assert.Throws<RpcException>(async () => await call.ResponseStream.MoveNext()); + Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode); + } + + [Test] + public async Task UnimplementedByDefault_DuplexStreamingCall() + { + var call = client.FullDuplexCall(); + + var ex = Assert.Throws<RpcException>(async () => await call.ResponseStream.MoveNext()); + Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode); + } + + /// <summary> + /// Implementation of TestService that doesn't override any methods. + /// </summary> + private class UnimplementedTestServiceImpl : TestService.TestServiceBase + { + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj index d3c572fe27..64d14b0df5 100644 --- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj +++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj @@ -84,7 +84,6 @@ <Compile Include="..\Grpc.Core\Version.cs"> <Link>Version.cs</Link> </Compile> - <Compile Include="HeaderInterceptorTest.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Empty.cs" /> <Compile Include="Messages.cs" /> @@ -114,6 +113,8 @@ <Compile Include="QpsWorker.cs" /> <Compile Include="WallClockStopwatch.cs" /> <Compile Include="GenericService.cs" /> + <Compile Include="GeneratedServiceBaseTest.cs" /> + <Compile Include="GeneratedClientTest.cs" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <ItemGroup> diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs index b0e33e49f7..7ca5221936 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs @@ -1,6 +1,6 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -217,7 +217,7 @@ namespace Grpc.IntegrationTesting } } - public static void RunEmptyUnary(TestService.ITestServiceClient client) + public static void RunEmptyUnary(TestService.TestServiceClient client) { Console.WriteLine("running empty_unary"); var response = client.EmptyCall(new Empty()); @@ -225,7 +225,7 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } - public static void RunLargeUnary(TestService.ITestServiceClient client) + public static void RunLargeUnary(TestService.TestServiceClient client) { Console.WriteLine("running large_unary"); var request = new SimpleRequest @@ -241,7 +241,7 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } - public static async Task RunClientStreamingAsync(TestService.ITestServiceClient client) + public static async Task RunClientStreamingAsync(TestService.TestServiceClient client) { Console.WriteLine("running client_streaming"); @@ -257,7 +257,7 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } - public static async Task RunServerStreamingAsync(TestService.ITestServiceClient client) + public static async Task RunServerStreamingAsync(TestService.TestServiceClient client) { Console.WriteLine("running server_streaming"); @@ -281,7 +281,7 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } - public static async Task RunPingPongAsync(TestService.ITestServiceClient client) + public static async Task RunPingPongAsync(TestService.TestServiceClient client) { Console.WriteLine("running ping_pong"); @@ -338,7 +338,7 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } - public static async Task RunEmptyStreamAsync(TestService.ITestServiceClient client) + public static async Task RunEmptyStreamAsync(TestService.TestServiceClient client) { Console.WriteLine("running empty_stream"); using (var call = client.FullDuplexCall()) @@ -434,7 +434,7 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } - public static async Task RunCancelAfterBeginAsync(TestService.ITestServiceClient client) + public static async Task RunCancelAfterBeginAsync(TestService.TestServiceClient client) { Console.WriteLine("running cancel_after_begin"); @@ -451,7 +451,7 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } - public static async Task RunCancelAfterFirstResponseAsync(TestService.ITestServiceClient client) + public static async Task RunCancelAfterFirstResponseAsync(TestService.TestServiceClient client) { Console.WriteLine("running cancel_after_first_response"); @@ -477,7 +477,7 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } - public static async Task RunTimeoutOnSleepingServerAsync(TestService.ITestServiceClient client) + public static async Task RunTimeoutOnSleepingServerAsync(TestService.TestServiceClient client) { Console.WriteLine("running timeout_on_sleeping_server"); @@ -499,7 +499,7 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } - public static async Task RunCustomMetadataAsync(TestService.ITestServiceClient client) + public static async Task RunCustomMetadataAsync(TestService.TestServiceClient client) { Console.WriteLine("running custom_metadata"); { @@ -546,7 +546,7 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } - public static async Task RunStatusCodeAndMessageAsync(TestService.ITestServiceClient client) + public static async Task RunStatusCodeAndMessageAsync(TestService.TestServiceClient client) { Console.WriteLine("running status_code_and_message"); var echoStatus = new EchoStatus @@ -580,7 +580,7 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } - public static void RunUnimplementedMethod(UnimplementedService.IUnimplementedServiceClient client) + public static void RunUnimplementedMethod(UnimplementedService.UnimplementedServiceClient client) { Console.WriteLine("running unimplemented_method"); var e = Assert.Throws<RpcException>(() => client.UnimplementedCall(new Empty())); diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs index 5facb87971..4ee1ff5ec8 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs @@ -51,7 +51,7 @@ namespace Grpc.IntegrationTesting const string Host = "localhost"; Server server; Channel channel; - TestService.ITestServiceClient client; + TestService.TestServiceClient client; [TestFixtureSetUp] public void Init() diff --git a/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs b/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs index 1c8bfed1f6..f95af5008f 100644 --- a/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs +++ b/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs @@ -1,6 +1,6 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -50,15 +50,15 @@ namespace Grpc.IntegrationTesting const string Host = "localhost"; Server server; Channel channel; - TestService.ITestServiceClient client; + TestService.TestServiceClient client; List<ChannelOption> options; - Mock<TestService.ITestService> serviceMock; + Mock<TestService.TestServiceBase> serviceMock; AsyncAuthInterceptor asyncAuthInterceptor; [SetUp] public void Init() { - serviceMock = new Mock<TestService.ITestService>(); + serviceMock = new Mock<TestService.TestServiceBase>(); serviceMock.Setup(m => m.UnaryCall(It.IsAny<SimpleRequest>(), It.IsAny<ServerCallContext>())) .Returns(new Func<SimpleRequest, ServerCallContext, Task<SimpleResponse>>(UnaryCallHandler)); diff --git a/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs index 996439afbf..46b16cf202 100644 --- a/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs @@ -36,6 +36,7 @@ namespace Grpc.Testing { } // client interface + [System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")] public interface IBenchmarkServiceClient { global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); @@ -47,47 +48,73 @@ namespace Grpc.Testing { } // server-side interface + [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")] public interface IBenchmarkService { Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context); Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context); } + // server-side abstract class + public abstract class BenchmarkServiceBase + { + public virtual Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + public virtual Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + } + // client stub - public class BenchmarkServiceClient : ClientBase, IBenchmarkServiceClient + public class BenchmarkServiceClient : ClientBase<BenchmarkServiceClient>, IBenchmarkServiceClient { public BenchmarkServiceClient(Channel channel) : base(channel) { } - public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public BenchmarkServiceClient(CallInvoker callInvoker) : base(callInvoker) + { + } + ///<summary>Protected parameterless constructor to allow creation of test doubles.</summary> + protected BenchmarkServiceClient() : base() { - var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken)); - return Calls.BlockingUnaryCall(call, request); } - public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options) + ///<summary>Protected constructor to allow creation of configured clients.</summary> + protected BenchmarkServiceClient(ClientBaseConfiguration configuration) : base(configuration) { - var call = CreateCall(__Method_UnaryCall, options); - return Calls.BlockingUnaryCall(call, request); } - public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + + public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncUnaryCall(call, request); + return UnaryCall(request, new CallOptions(headers, deadline, cancellationToken)); } - public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options) + public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options) { - var call = CreateCall(__Method_UnaryCall, options); - return Calls.AsyncUnaryCall(call, request); + return CallInvoker.BlockingUnaryCall(__Method_UnaryCall, null, options, request); } - public AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_StreamingCall, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncDuplexStreamingCall(call); + return UnaryCallAsync(request, new CallOptions(headers, deadline, cancellationToken)); } - public AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options) + public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options) { - var call = CreateCall(__Method_StreamingCall, options); - return Calls.AsyncDuplexStreamingCall(call); + return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request); + } + public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + { + return StreamingCall(new CallOptions(headers, deadline, cancellationToken)); + } + public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options) + { + return CallInvoker.AsyncDuplexStreamingCall(__Method_StreamingCall, null, options); + } + protected override BenchmarkServiceClient NewInstance(ClientBaseConfiguration configuration) + { + return new BenchmarkServiceClient(configuration); } } @@ -99,6 +126,14 @@ namespace Grpc.Testing { .AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall).Build(); } + // creates service definition that can be registered with a server + public static ServerServiceDefinition BindService(BenchmarkServiceBase serviceImpl) + { + return ServerServiceDefinition.CreateBuilder(__ServiceName) + .AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall) + .AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall).Build(); + } + // creates a new client public static BenchmarkServiceClient NewClient(Channel channel) { @@ -153,6 +188,7 @@ namespace Grpc.Testing { } // client interface + [System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")] public interface IWorkerServiceClient { AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); @@ -170,6 +206,7 @@ namespace Grpc.Testing { } // server-side interface + [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")] public interface IWorkerService { Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context); @@ -178,71 +215,100 @@ namespace Grpc.Testing { Task<global::Grpc.Testing.Void> QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context); } + // server-side abstract class + public abstract class WorkerServiceBase + { + public virtual Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + public virtual Task RunClient(IAsyncStreamReader<global::Grpc.Testing.ClientArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ClientStatus> responseStream, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + public virtual Task<global::Grpc.Testing.CoreResponse> CoreCount(global::Grpc.Testing.CoreRequest request, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + public virtual Task<global::Grpc.Testing.Void> QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + } + // client stub - public class WorkerServiceClient : ClientBase, IWorkerServiceClient + public class WorkerServiceClient : ClientBase<WorkerServiceClient>, IWorkerServiceClient { public WorkerServiceClient(Channel channel) : base(channel) { } - public AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public WorkerServiceClient(CallInvoker callInvoker) : base(callInvoker) { - var call = CreateCall(__Method_RunServer, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncDuplexStreamingCall(call); } - public AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options) + ///<summary>Protected parameterless constructor to allow creation of test doubles.</summary> + protected WorkerServiceClient() : base() { - var call = CreateCall(__Method_RunServer, options); - return Calls.AsyncDuplexStreamingCall(call); } - public AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + ///<summary>Protected constructor to allow creation of configured clients.</summary> + protected WorkerServiceClient(ClientBaseConfiguration configuration) : base(configuration) { - var call = CreateCall(__Method_RunClient, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncDuplexStreamingCall(call); } - public AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options) + + public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_RunClient, options); - return Calls.AsyncDuplexStreamingCall(call); + return RunServer(new CallOptions(headers, deadline, cancellationToken)); } - public global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options) { - var call = CreateCall(__Method_CoreCount, new CallOptions(headers, deadline, cancellationToken)); - return Calls.BlockingUnaryCall(call, request); + return CallInvoker.AsyncDuplexStreamingCall(__Method_RunServer, null, options); } - public global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, CallOptions options) + public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_CoreCount, options); - return Calls.BlockingUnaryCall(call, request); + return RunClient(new CallOptions(headers, deadline, cancellationToken)); } - public AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options) { - var call = CreateCall(__Method_CoreCount, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncUnaryCall(call, request); + return CallInvoker.AsyncDuplexStreamingCall(__Method_RunClient, null, options); } - public AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, CallOptions options) + public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_CoreCount, options); - return Calls.AsyncUnaryCall(call, request); + return CoreCount(request, new CallOptions(headers, deadline, cancellationToken)); } - public global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, CallOptions options) { - var call = CreateCall(__Method_QuitWorker, new CallOptions(headers, deadline, cancellationToken)); - return Calls.BlockingUnaryCall(call, request); + return CallInvoker.BlockingUnaryCall(__Method_CoreCount, null, options, request); } - public global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, CallOptions options) + public virtual AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_QuitWorker, options); - return Calls.BlockingUnaryCall(call, request); + return CoreCountAsync(request, new CallOptions(headers, deadline, cancellationToken)); } - public AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, CallOptions options) { - var call = CreateCall(__Method_QuitWorker, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncUnaryCall(call, request); + return CallInvoker.AsyncUnaryCall(__Method_CoreCount, null, options, request); } - public AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, CallOptions options) + public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_QuitWorker, options); - return Calls.AsyncUnaryCall(call, request); + return QuitWorker(request, new CallOptions(headers, deadline, cancellationToken)); + } + public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_QuitWorker, null, options, request); + } + public virtual AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + { + return QuitWorkerAsync(request, new CallOptions(headers, deadline, cancellationToken)); + } + public virtual AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_QuitWorker, null, options, request); + } + protected override WorkerServiceClient NewInstance(ClientBaseConfiguration configuration) + { + return new WorkerServiceClient(configuration); } } @@ -256,6 +322,16 @@ namespace Grpc.Testing { .AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build(); } + // creates service definition that can be registered with a server + public static ServerServiceDefinition BindService(WorkerServiceBase serviceImpl) + { + return ServerServiceDefinition.CreateBuilder(__ServiceName) + .AddMethod(__Method_RunServer, serviceImpl.RunServer) + .AddMethod(__Method_RunClient, serviceImpl.RunClient) + .AddMethod(__Method_CoreCount, serviceImpl.CoreCount) + .AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build(); + } + // creates a new client public static WorkerServiceClient NewClient(Channel channel) { diff --git a/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs index 37b2518c21..3df45b5f70 100644 --- a/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs +++ b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs @@ -1,6 +1,6 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -53,7 +53,7 @@ namespace Grpc.IntegrationTesting const string Host = "localhost"; Server server; Channel channel; - TestService.ITestServiceClient client; + TestService.TestServiceClient client; [TestFixtureSetUp] public void Init() diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs index 2c469080d9..b84ec2d984 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs @@ -69,6 +69,7 @@ namespace Grpc.Testing { } // client interface + [System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")] public interface ITestServiceClient { global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); @@ -90,6 +91,7 @@ namespace Grpc.Testing { } // server-side interface + [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")] public interface ITestService { Task<global::Grpc.Testing.Empty> EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context); @@ -100,91 +102,126 @@ namespace Grpc.Testing { Task HalfDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context); } + // server-side abstract class + public abstract class TestServiceBase + { + public virtual Task<global::Grpc.Testing.Empty> EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + public virtual Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + public virtual Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + public virtual Task<global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<global::Grpc.Testing.StreamingInputCallRequest> requestStream, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + public virtual Task FullDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + public virtual Task HalfDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + } + // client stub - public class TestServiceClient : ClientBase, ITestServiceClient + public class TestServiceClient : ClientBase<TestServiceClient>, ITestServiceClient { public TestServiceClient(Channel channel) : base(channel) { } - public global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public TestServiceClient(CallInvoker callInvoker) : base(callInvoker) + { + } + ///<summary>Protected parameterless constructor to allow creation of test doubles.</summary> + protected TestServiceClient() : base() + { + } + ///<summary>Protected constructor to allow creation of configured clients.</summary> + protected TestServiceClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + public virtual global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_EmptyCall, new CallOptions(headers, deadline, cancellationToken)); - return Calls.BlockingUnaryCall(call, request); + return EmptyCall(request, new CallOptions(headers, deadline, cancellationToken)); } - public global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, CallOptions options) + public virtual global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, CallOptions options) { - var call = CreateCall(__Method_EmptyCall, options); - return Calls.BlockingUnaryCall(call, request); + return CallInvoker.BlockingUnaryCall(__Method_EmptyCall, null, options, request); } - public AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_EmptyCall, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncUnaryCall(call, request); + return EmptyCallAsync(request, new CallOptions(headers, deadline, cancellationToken)); } - public AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, CallOptions options) + public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, CallOptions options) { - var call = CreateCall(__Method_EmptyCall, options); - return Calls.AsyncUnaryCall(call, request); + return CallInvoker.AsyncUnaryCall(__Method_EmptyCall, null, options, request); } - public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken)); - return Calls.BlockingUnaryCall(call, request); + return UnaryCall(request, new CallOptions(headers, deadline, cancellationToken)); } - public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options) + public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options) { - var call = CreateCall(__Method_UnaryCall, options); - return Calls.BlockingUnaryCall(call, request); + return CallInvoker.BlockingUnaryCall(__Method_UnaryCall, null, options, request); } - public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncUnaryCall(call, request); + return UnaryCallAsync(request, new CallOptions(headers, deadline, cancellationToken)); } - public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options) + public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options) { - var call = CreateCall(__Method_UnaryCall, options); - return Calls.AsyncUnaryCall(call, request); + return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request); } - public AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_StreamingOutputCall, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncServerStreamingCall(call, request); + return StreamingOutputCall(request, new CallOptions(headers, deadline, cancellationToken)); } - public AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, CallOptions options) + public virtual AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, CallOptions options) { - var call = CreateCall(__Method_StreamingOutputCall, options); - return Calls.AsyncServerStreamingCall(call, request); + return CallInvoker.AsyncServerStreamingCall(__Method_StreamingOutputCall, null, options, request); } - public AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_StreamingInputCall, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncClientStreamingCall(call); + return StreamingInputCall(new CallOptions(headers, deadline, cancellationToken)); } - public AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options) + public virtual AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options) { - var call = CreateCall(__Method_StreamingInputCall, options); - return Calls.AsyncClientStreamingCall(call); + return CallInvoker.AsyncClientStreamingCall(__Method_StreamingInputCall, null, options); } - public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_FullDuplexCall, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncDuplexStreamingCall(call); + return FullDuplexCall(new CallOptions(headers, deadline, cancellationToken)); } - public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options) + public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options) { - var call = CreateCall(__Method_FullDuplexCall, options); - return Calls.AsyncDuplexStreamingCall(call); + return CallInvoker.AsyncDuplexStreamingCall(__Method_FullDuplexCall, null, options); } - public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_HalfDuplexCall, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncDuplexStreamingCall(call); + return HalfDuplexCall(new CallOptions(headers, deadline, cancellationToken)); } - public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options) + public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options) { - var call = CreateCall(__Method_HalfDuplexCall, options); - return Calls.AsyncDuplexStreamingCall(call); + return CallInvoker.AsyncDuplexStreamingCall(__Method_HalfDuplexCall, null, options); + } + protected override TestServiceClient NewInstance(ClientBaseConfiguration configuration) + { + return new TestServiceClient(configuration); } } @@ -200,6 +237,18 @@ namespace Grpc.Testing { .AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall).Build(); } + // creates service definition that can be registered with a server + public static ServerServiceDefinition BindService(TestServiceBase serviceImpl) + { + return ServerServiceDefinition.CreateBuilder(__ServiceName) + .AddMethod(__Method_EmptyCall, serviceImpl.EmptyCall) + .AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall) + .AddMethod(__Method_StreamingOutputCall, serviceImpl.StreamingOutputCall) + .AddMethod(__Method_StreamingInputCall, serviceImpl.StreamingInputCall) + .AddMethod(__Method_FullDuplexCall, serviceImpl.FullDuplexCall) + .AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall).Build(); + } + // creates a new client public static TestServiceClient NewClient(Channel channel) { @@ -227,6 +276,7 @@ namespace Grpc.Testing { } // client interface + [System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")] public interface IUnimplementedServiceClient { global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); @@ -236,36 +286,59 @@ namespace Grpc.Testing { } // server-side interface + [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")] public interface IUnimplementedService { Task<global::Grpc.Testing.Empty> UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context); } + // server-side abstract class + public abstract class UnimplementedServiceBase + { + public virtual Task<global::Grpc.Testing.Empty> UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + } + // client stub - public class UnimplementedServiceClient : ClientBase, IUnimplementedServiceClient + public class UnimplementedServiceClient : ClientBase<UnimplementedServiceClient>, IUnimplementedServiceClient { public UnimplementedServiceClient(Channel channel) : base(channel) { } - public global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public UnimplementedServiceClient(CallInvoker callInvoker) : base(callInvoker) + { + } + ///<summary>Protected parameterless constructor to allow creation of test doubles.</summary> + protected UnimplementedServiceClient() : base() + { + } + ///<summary>Protected constructor to allow creation of configured clients.</summary> + protected UnimplementedServiceClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + { + return UnimplementedCall(request, new CallOptions(headers, deadline, cancellationToken)); + } + public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, CallOptions options) { - var call = CreateCall(__Method_UnimplementedCall, new CallOptions(headers, deadline, cancellationToken)); - return Calls.BlockingUnaryCall(call, request); + return CallInvoker.BlockingUnaryCall(__Method_UnimplementedCall, null, options, request); } - public global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, CallOptions options) + public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_UnimplementedCall, options); - return Calls.BlockingUnaryCall(call, request); + return UnimplementedCallAsync(request, new CallOptions(headers, deadline, cancellationToken)); } - public AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, CallOptions options) { - var call = CreateCall(__Method_UnimplementedCall, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncUnaryCall(call, request); + return CallInvoker.AsyncUnaryCall(__Method_UnimplementedCall, null, options, request); } - public AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, CallOptions options) + protected override UnimplementedServiceClient NewInstance(ClientBaseConfiguration configuration) { - var call = CreateCall(__Method_UnimplementedCall, options); - return Calls.AsyncUnaryCall(call, request); + return new UnimplementedServiceClient(configuration); } } @@ -276,6 +349,13 @@ namespace Grpc.Testing { .AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build(); } + // creates service definition that can be registered with a server + public static ServerServiceDefinition BindService(UnimplementedServiceBase serviceImpl) + { + return ServerServiceDefinition.CreateBuilder(__ServiceName) + .AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build(); + } + // creates a new client public static UnimplementedServiceClient NewClient(Channel channel) { @@ -311,6 +391,7 @@ namespace Grpc.Testing { } // client interface + [System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")] public interface IReconnectServiceClient { global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); @@ -324,57 +405,81 @@ namespace Grpc.Testing { } // server-side interface + [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")] public interface IReconnectService { Task<global::Grpc.Testing.Empty> Start(global::Grpc.Testing.Empty request, ServerCallContext context); Task<global::Grpc.Testing.ReconnectInfo> Stop(global::Grpc.Testing.Empty request, ServerCallContext context); } + // server-side abstract class + public abstract class ReconnectServiceBase + { + public virtual Task<global::Grpc.Testing.Empty> Start(global::Grpc.Testing.Empty request, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + public virtual Task<global::Grpc.Testing.ReconnectInfo> Stop(global::Grpc.Testing.Empty request, ServerCallContext context) + { + throw new RpcException(new Status(StatusCode.Unimplemented, "")); + } + + } + // client stub - public class ReconnectServiceClient : ClientBase, IReconnectServiceClient + public class ReconnectServiceClient : ClientBase<ReconnectServiceClient>, IReconnectServiceClient { public ReconnectServiceClient(Channel channel) : base(channel) { } - public global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public ReconnectServiceClient(CallInvoker callInvoker) : base(callInvoker) { - var call = CreateCall(__Method_Start, new CallOptions(headers, deadline, cancellationToken)); - return Calls.BlockingUnaryCall(call, request); } - public global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, CallOptions options) + ///<summary>Protected parameterless constructor to allow creation of test doubles.</summary> + protected ReconnectServiceClient() : base() { - var call = CreateCall(__Method_Start, options); - return Calls.BlockingUnaryCall(call, request); } - public AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + ///<summary>Protected constructor to allow creation of configured clients.</summary> + protected ReconnectServiceClient(ClientBaseConfiguration configuration) : base(configuration) { - var call = CreateCall(__Method_Start, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncUnaryCall(call, request); } - public AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.Empty request, CallOptions options) + + public virtual global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_Start, options); - return Calls.AsyncUnaryCall(call, request); + return Start(request, new CallOptions(headers, deadline, cancellationToken)); } - public global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, CallOptions options) { - var call = CreateCall(__Method_Stop, new CallOptions(headers, deadline, cancellationToken)); - return Calls.BlockingUnaryCall(call, request); + return CallInvoker.BlockingUnaryCall(__Method_Start, null, options, request); } - public global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, CallOptions options) + public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_Stop, options); - return Calls.BlockingUnaryCall(call, request); + return StartAsync(request, new CallOptions(headers, deadline, cancellationToken)); } - public AsyncUnaryCall<global::Grpc.Testing.ReconnectInfo> StopAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.Empty request, CallOptions options) { - var call = CreateCall(__Method_Stop, new CallOptions(headers, deadline, cancellationToken)); - return Calls.AsyncUnaryCall(call, request); + return CallInvoker.AsyncUnaryCall(__Method_Start, null, options, request); } - public AsyncUnaryCall<global::Grpc.Testing.ReconnectInfo> StopAsync(global::Grpc.Testing.Empty request, CallOptions options) + public virtual global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { - var call = CreateCall(__Method_Stop, options); - return Calls.AsyncUnaryCall(call, request); + return Stop(request, new CallOptions(headers, deadline, cancellationToken)); + } + public virtual global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_Stop, null, options, request); + } + public virtual AsyncUnaryCall<global::Grpc.Testing.ReconnectInfo> StopAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + { + return StopAsync(request, new CallOptions(headers, deadline, cancellationToken)); + } + public virtual AsyncUnaryCall<global::Grpc.Testing.ReconnectInfo> StopAsync(global::Grpc.Testing.Empty request, CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_Stop, null, options, request); + } + protected override ReconnectServiceClient NewInstance(ClientBaseConfiguration configuration) + { + return new ReconnectServiceClient(configuration); } } @@ -386,6 +491,14 @@ namespace Grpc.Testing { .AddMethod(__Method_Stop, serviceImpl.Stop).Build(); } + // creates service definition that can be registered with a server + public static ServerServiceDefinition BindService(ReconnectServiceBase serviceImpl) + { + return ServerServiceDefinition.CreateBuilder(__ServiceName) + .AddMethod(__Method_Start, serviceImpl.Start) + .AddMethod(__Method_Stop, serviceImpl.Stop).Build(); + } + // creates a new client public static ReconnectServiceClient NewClient(Channel channel) { diff --git a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs index 5a1b4cf319..354318e80e 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs @@ -1,6 +1,6 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -45,14 +45,14 @@ namespace Grpc.Testing /// <summary> /// Implementation of TestService server /// </summary> - public class TestServiceImpl : TestService.ITestService + public class TestServiceImpl : TestService.TestServiceBase { - public Task<Empty> EmptyCall(Empty request, ServerCallContext context) + public override Task<Empty> EmptyCall(Empty request, ServerCallContext context) { return Task.FromResult(new Empty()); } - public async Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context) + public override async Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context) { await EnsureEchoMetadataAsync(context); EnsureEchoStatus(request.ResponseStatus, context); @@ -61,7 +61,7 @@ namespace Grpc.Testing return response; } - public async Task StreamingOutputCall(StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context) + public override async Task StreamingOutputCall(StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context) { await EnsureEchoMetadataAsync(context); EnsureEchoStatus(request.ResponseStatus, context); @@ -73,7 +73,7 @@ namespace Grpc.Testing } } - public async Task<StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<StreamingInputCallRequest> requestStream, ServerCallContext context) + public override async Task<StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<StreamingInputCallRequest> requestStream, ServerCallContext context) { await EnsureEchoMetadataAsync(context); @@ -85,7 +85,7 @@ namespace Grpc.Testing return new StreamingInputCallResponse { AggregatedPayloadSize = sum }; } - public async Task FullDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context) + public override async Task FullDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context) { await EnsureEchoMetadataAsync(context); @@ -100,7 +100,7 @@ namespace Grpc.Testing }); } - public async Task HalfDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context) + public override async Task HalfDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context) { throw new NotImplementedException(); } diff --git a/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs index e5ad0caa03..80dad9fdd9 100644 --- a/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs +++ b/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs @@ -45,7 +45,7 @@ namespace Grpc.Testing /// <summary> /// Implementation of WorkerService server /// </summary> - public class WorkerServiceImpl : WorkerService.IWorkerService + public class WorkerServiceImpl : WorkerService.WorkerServiceBase { readonly Action stopRequestHandler; @@ -54,7 +54,7 @@ namespace Grpc.Testing this.stopRequestHandler = GrpcPreconditions.CheckNotNull(stopRequestHandler); } - public async Task RunServer(IAsyncStreamReader<ServerArgs> requestStream, IServerStreamWriter<ServerStatus> responseStream, ServerCallContext context) + public override async Task RunServer(IAsyncStreamReader<ServerArgs> requestStream, IServerStreamWriter<ServerStatus> responseStream, ServerCallContext context) { GrpcPreconditions.CheckState(await requestStream.MoveNext()); var serverConfig = requestStream.Current.Setup; @@ -78,7 +78,7 @@ namespace Grpc.Testing await runner.StopAsync(); } - public async Task RunClient(IAsyncStreamReader<ClientArgs> requestStream, IServerStreamWriter<ClientStatus> responseStream, ServerCallContext context) + public override async Task RunClient(IAsyncStreamReader<ClientArgs> requestStream, IServerStreamWriter<ClientStatus> responseStream, ServerCallContext context) { GrpcPreconditions.CheckState(await requestStream.MoveNext()); var clientConfig = requestStream.Current.Setup; @@ -100,12 +100,12 @@ namespace Grpc.Testing await runner.StopAsync(); } - public Task<CoreResponse> CoreCount(CoreRequest request, ServerCallContext context) + public override Task<CoreResponse> CoreCount(CoreRequest request, ServerCallContext context) { return Task.FromResult(new CoreResponse { Cores = Environment.ProcessorCount }); } - public Task<Void> QuitWorker(Void request, ServerCallContext context) + public override Task<Void> QuitWorker(Void request, ServerCallContext context) { stopRequestHandler(); return Task.FromResult(new Void()); diff --git a/src/csharp/grpc.native.csharp/grpc.native.csharp.nuspec b/src/csharp/grpc.native.csharp/grpc.native.csharp.nuspec index 6a1795b709..cc688e2bc7 100644 --- a/src/csharp/grpc.native.csharp/grpc.native.csharp.nuspec +++ b/src/csharp/grpc.native.csharp/grpc.native.csharp.nuspec @@ -10,7 +10,7 @@ <requireLicenseAcceptance>false</requireLicenseAcceptance> <description>Native extension needed by gRPC C# library. This is not the package you are looking for, it is only meant to be used as a dependency.</description> <releaseNotes>Release of gRPC C core $version$ libraries.</releaseNotes> - <copyright>Copyright 2015-2016</copyright> + <copyright>Copyright 2015</copyright> <title>gRPC C# Native Extension</title> <summary>Native library required by gRPC C#</summary> <tags>gRPC native</tags> diff --git a/src/csharp/tests.json b/src/csharp/tests.json index d66cb1b100..718bfa3287 100644 --- a/src/csharp/tests.json +++ b/src/csharp/tests.json @@ -36,8 +36,9 @@ "Math.Tests.MathClientServerTest", "Grpc.HealthCheck.Tests.HealthClientServerTest", "Grpc.HealthCheck.Tests.HealthServiceImplTest", - "Grpc.IntegrationTesting.HeaderInterceptorTest", "Grpc.IntegrationTesting.HistogramTest", + "Grpc.IntegrationTesting.GeneratedClientTest", + "Grpc.IntegrationTesting.GeneratedServiceBaseTest", "Grpc.IntegrationTesting.InteropClientServerTest", "Grpc.IntegrationTesting.MetadataCredentialsTest", "Grpc.IntegrationTesting.RunnerClientServerTest", diff --git a/src/python/grpcio/grpc/beta/implementations.py b/src/python/grpcio/grpc/beta/implementations.py index 06ee7aa26e..742e94dc65 100644 --- a/src/python/grpcio/grpc/beta/implementations.py +++ b/src/python/grpcio/grpc/beta/implementations.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016, Google Inc. +# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 875ff49d30..3452e3a0f5 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -123,6 +123,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/channel/http_client_filter.c', 'src/core/lib/channel/http_server_filter.c', 'src/core/lib/channel/subchannel_call_holder.c', + 'src/core/lib/client_config/client_channel_factory.c', 'src/core/lib/client_config/client_config.c', 'src/core/lib/client_config/connector.c', 'src/core/lib/client_config/default_initial_connect_string.c', @@ -134,7 +135,6 @@ CORE_SOURCE_FILES = [ 'src/core/lib/client_config/resolver_factory.c', 'src/core/lib/client_config/resolver_registry.c', 'src/core/lib/client_config/subchannel.c', - 'src/core/lib/client_config/subchannel_factory.c', 'src/core/lib/client_config/subchannel_index.c', 'src/core/lib/client_config/uri_parser.c', 'src/core/lib/compression/compression_algorithm.c', diff --git a/src/python/grpcio/tests/interop/_secure_interop_test.py b/src/python/grpcio/tests/interop/_secure_interop_test.py index 1a1a063a6f..86d7e43351 100644 --- a/src/python/grpcio/tests/interop/_secure_interop_test.py +++ b/src/python/grpcio/tests/interop/_secure_interop_test.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016, Google Inc. +# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/src/python/grpcio/tests/interop/client.py b/src/python/grpcio/tests/interop/client.py index 02a37cc6bc..1d10d7e45d 100644 --- a/src/python/grpcio/tests/interop/client.py +++ b/src/python/grpcio/tests/interop/client.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016, Google Inc. +# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/src/python/grpcio/tests/unit/beta/_beta_features_test.py b/src/python/grpcio/tests/unit/beta/_beta_features_test.py index b8b77a96c1..bb2893a21b 100644 --- a/src/python/grpcio/tests/unit/beta/_beta_features_test.py +++ b/src/python/grpcio/tests/unit/beta/_beta_features_test.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016, Google Inc. +# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/src/python/grpcio/tests/unit/beta/_face_interface_test.py b/src/python/grpcio/tests/unit/beta/_face_interface_test.py index ea19ee47ae..3a67516906 100644 --- a/src/python/grpcio/tests/unit/beta/_face_interface_test.py +++ b/src/python/grpcio/tests/unit/beta/_face_interface_test.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016, Google Inc. +# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb index 4b5578b018..5ba77db173 100644 --- a/src/ruby/lib/grpc/generic/rpc_server.rb +++ b/src/ruby/lib/grpc/generic/rpc_server.rb @@ -403,7 +403,7 @@ module GRPC loop_handle_server_calls end - # Sends UNAVAILABLE if there are too many unprocessed jobs + # Sends RESOURCE_EXHAUSTED if there are too many unprocessed jobs def available?(an_rpc) jobs_count, max = @pool.jobs_waiting, @max_waiting_requests GRPC.logger.info("waiting: #{jobs_count}, max: #{max}") @@ -411,7 +411,7 @@ module GRPC GRPC.logger.warn("NOT AVAILABLE: too many jobs_waiting: #{an_rpc}") noop = proc { |x| x } c = ActiveCall.new(an_rpc.call, @cq, noop, noop, an_rpc.deadline) - c.send_status(StatusCodes::UNAVAILABLE, '') + c.send_status(StatusCodes::RESOURCE_EXHAUSTED, '') nil end diff --git a/src/ruby/spec/generic/rpc_server_spec.rb b/src/ruby/spec/generic/rpc_server_spec.rb index e16ba60387..e688057cb1 100644 --- a/src/ruby/spec/generic/rpc_server_spec.rb +++ b/src/ruby/spec/generic/rpc_server_spec.rb @@ -426,7 +426,7 @@ describe GRPC::RpcServer do threads.each(&:join) end - it 'should return UNAVAILABLE on too many jobs', server: true do + it 'should return RESOURCE_EXHAUSTED on too many jobs', server: true do opts = { a_channel_arg: 'an_arg', server_override: @server, @@ -449,7 +449,8 @@ describe GRPC::RpcServer do begin stub.an_rpc(req) rescue GRPC::BadStatus => e - one_failed_as_unavailable = e.code == StatusCodes::UNAVAILABLE + one_failed_as_unavailable = + e.code == StatusCodes::RESOURCE_EXHAUSTED end end end diff --git a/test/core/bad_ssl/bad_ssl_test.c b/test/core/bad_ssl/bad_ssl_test.c index 12c7710af6..c4ae212ec2 100644 --- a/test/core/bad_ssl/bad_ssl_test.c +++ b/test/core/bad_ssl/bad_ssl_test.c @@ -87,7 +87,7 @@ static void run_test(const char *target, size_t nops) { op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; - op->flags = 0; + op->flags = GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; diff --git a/test/core/client_config/resolvers/dns_resolver_connectivity_test.c b/test/core/client_config/resolvers/dns_resolver_connectivity_test.c index b7c3b78fe1..bcd9fca9c7 100644 --- a/test/core/client_config/resolvers/dns_resolver_connectivity_test.c +++ b/test/core/client_config/resolvers/dns_resolver_connectivity_test.c @@ -41,20 +41,28 @@ #include "src/core/lib/iomgr/timer.h" #include "test/core/util/test_config.h" -static void subchannel_factory_ref(grpc_subchannel_factory *scv) {} -static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx, - grpc_subchannel_factory *scv) {} -static grpc_subchannel *subchannel_factory_create_subchannel( - grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory, +static void client_channel_factory_ref(grpc_client_channel_factory *scv) {} +static void client_channel_factory_unref(grpc_exec_ctx *exec_ctx, + grpc_client_channel_factory *scv) {} +static grpc_subchannel *client_channel_factory_create_subchannel( + grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory, grpc_subchannel_args *args) { return NULL; } -static const grpc_subchannel_factory_vtable sc_vtable = { - subchannel_factory_ref, subchannel_factory_unref, - subchannel_factory_create_subchannel}; +static grpc_channel *client_channel_factory_create_channel( + grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, + const char *target, grpc_client_channel_type type, + grpc_channel_args *args) { + GPR_UNREACHABLE_CODE(return NULL); +} + +static const grpc_client_channel_factory_vtable sc_vtable = { + client_channel_factory_ref, client_channel_factory_unref, + client_channel_factory_create_subchannel, + client_channel_factory_create_channel}; -static grpc_subchannel_factory sc_factory = {&sc_vtable}; +static grpc_client_channel_factory cc_factory = {&sc_vtable}; static gpr_mu g_mu; static bool g_fail_resolution = true; @@ -84,7 +92,7 @@ static grpc_resolver *create_resolver(const char *name) { grpc_resolver_args args; memset(&args, 0, sizeof(args)); args.uri = uri; - args.subchannel_factory = &sc_factory; + args.client_channel_factory = &cc_factory; grpc_resolver *resolver = grpc_resolver_factory_create_resolver(factory, &args); grpc_resolver_factory_unref(factory); diff --git a/test/core/client_config/resolvers/dns_resolver_test.c b/test/core/client_config/resolvers/dns_resolver_test.c index 0e8a3b13dd..6a9c06e48c 100644 --- a/test/core/client_config/resolvers/dns_resolver_test.c +++ b/test/core/client_config/resolvers/dns_resolver_test.c @@ -38,20 +38,28 @@ #include "src/core/lib/client_config/resolver_registry.h" #include "test/core/util/test_config.h" -static void subchannel_factory_ref(grpc_subchannel_factory *scv) {} -static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx, - grpc_subchannel_factory *scv) {} -static grpc_subchannel *subchannel_factory_create_subchannel( - grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory, +static void client_channel_factory_ref(grpc_client_channel_factory *scv) {} +static void client_channel_factory_unref(grpc_exec_ctx *exec_ctx, + grpc_client_channel_factory *scv) {} +static grpc_subchannel *client_channel_factory_create_subchannel( + grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory, grpc_subchannel_args *args) { GPR_UNREACHABLE_CODE(return NULL); } -static const grpc_subchannel_factory_vtable sc_vtable = { - subchannel_factory_ref, subchannel_factory_unref, - subchannel_factory_create_subchannel}; +static grpc_channel *client_channel_factory_create_channel( + grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, + const char *target, grpc_client_channel_type type, + grpc_channel_args *args) { + GPR_UNREACHABLE_CODE(return NULL); +} + +static const grpc_client_channel_factory_vtable sc_vtable = { + client_channel_factory_ref, client_channel_factory_unref, + client_channel_factory_create_subchannel, + client_channel_factory_create_channel}; -static grpc_subchannel_factory sc_factory = {&sc_vtable}; +static grpc_client_channel_factory cc_factory = {&sc_vtable}; static void test_succeeds(grpc_resolver_factory *factory, const char *string) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; @@ -63,7 +71,7 @@ static void test_succeeds(grpc_resolver_factory *factory, const char *string) { GPR_ASSERT(uri); memset(&args, 0, sizeof(args)); args.uri = uri; - args.subchannel_factory = &sc_factory; + args.client_channel_factory = &cc_factory; resolver = grpc_resolver_factory_create_resolver(factory, &args); GPR_ASSERT(resolver != NULL); GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds"); diff --git a/test/core/client_config/resolvers/sockaddr_resolver_test.c b/test/core/client_config/resolvers/sockaddr_resolver_test.c index b2c4c63b79..99b3ca0dc8 100644 --- a/test/core/client_config/resolvers/sockaddr_resolver_test.c +++ b/test/core/client_config/resolvers/sockaddr_resolver_test.c @@ -38,20 +38,28 @@ #include "src/core/lib/client_config/resolver_registry.h" #include "test/core/util/test_config.h" -static void subchannel_factory_ref(grpc_subchannel_factory *scv) {} -static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx, - grpc_subchannel_factory *scv) {} -static grpc_subchannel *subchannel_factory_create_subchannel( - grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory, +static void client_channel_factory_ref(grpc_client_channel_factory *scv) {} +static void client_channel_factory_unref(grpc_exec_ctx *exec_ctx, + grpc_client_channel_factory *scv) {} +static grpc_subchannel *client_channel_factory_create_subchannel( + grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory, grpc_subchannel_args *args) { GPR_UNREACHABLE_CODE(return NULL); } -static const grpc_subchannel_factory_vtable sc_vtable = { - subchannel_factory_ref, subchannel_factory_unref, - subchannel_factory_create_subchannel}; +static grpc_channel *client_channel_factory_create_channel( + grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, + const char *target, grpc_client_channel_type type, + grpc_channel_args *args) { + GPR_UNREACHABLE_CODE(return NULL); +} + +static const grpc_client_channel_factory_vtable sc_vtable = { + client_channel_factory_ref, client_channel_factory_unref, + client_channel_factory_create_subchannel, + client_channel_factory_create_channel}; -static grpc_subchannel_factory sc_factory = {&sc_vtable}; +static grpc_client_channel_factory cc_factory = {&sc_vtable}; static void test_succeeds(grpc_resolver_factory *factory, const char *string) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; @@ -63,7 +71,7 @@ static void test_succeeds(grpc_resolver_factory *factory, const char *string) { GPR_ASSERT(uri); memset(&args, 0, sizeof(args)); args.uri = uri; - args.subchannel_factory = &sc_factory; + args.client_channel_factory = &cc_factory; resolver = grpc_resolver_factory_create_resolver(factory, &args); GPR_ASSERT(resolver != NULL); GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds"); diff --git a/test/core/end2end/dualstack_socket_test.c b/test/core/end2end/dualstack_socket_test.c index 8568bb1a86..81f76ea79c 100644 --- a/test/core/end2end/dualstack_socket_test.c +++ b/test/core/end2end/dualstack_socket_test.c @@ -168,7 +168,7 @@ void test_connect(const char *server_host, const char *client_host, int port, op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; - op->flags = 0; + op->flags = expect_ok ? GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY : 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; @@ -237,7 +237,7 @@ void test_connect(const char *server_host, const char *client_host, int port, cq_expect_completion(cqv, tag(1), 1); cq_verify(cqv); - GPR_ASSERT(status == GRPC_STATUS_DEADLINE_EXCEEDED); + GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); } grpc_call_destroy(c); diff --git a/test/core/end2end/fixtures/proxy.c b/test/core/end2end/fixtures/proxy.c index 1ca53cdad9..a6487a17ac 100644 --- a/test/core/end2end/fixtures/proxy.c +++ b/test/core/end2end/fixtures/proxy.c @@ -1,6 +1,6 @@ /* * - * Copyright 2015-2016, Google Inc. + * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/test/core/end2end/tests/idempotent_request.c b/test/core/end2end/tests/idempotent_request.c index 485a854441..1bc6450414 100644 --- a/test/core/end2end/tests/idempotent_request.c +++ b/test/core/end2end/tests/idempotent_request.c @@ -1,6 +1,6 @@ /* * - * Copyright 2015-2016, Google Inc. + * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/test/core/end2end/tests/simple_delayed_request.c b/test/core/end2end/tests/simple_delayed_request.c index bb9d462cef..122dcd0a5b 100644 --- a/test/core/end2end/tests/simple_delayed_request.c +++ b/test/core/end2end/tests/simple_delayed_request.c @@ -120,7 +120,7 @@ static void simple_delayed_request_body(grpc_end2end_test_config config, op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; - op->flags = 0; + op->flags = GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; diff --git a/test/core/internal_api_canaries/iomgr.c b/test/core/internal_api_canaries/iomgr.c index 04d66994cd..f87a80cd90 100644 --- a/test/core/internal_api_canaries/iomgr.c +++ b/test/core/internal_api_canaries/iomgr.c @@ -1,6 +1,6 @@ /* * - * Copyright 2015-2016, Google Inc. + * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/test/core/internal_api_canaries/support.c b/test/core/internal_api_canaries/support.c index 7e00e0d2ff..c51cbf2522 100644 --- a/test/core/internal_api_canaries/support.c +++ b/test/core/internal_api_canaries/support.c @@ -1,6 +1,6 @@ /* * - * Copyright 2015-2016, Google Inc. + * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/test/core/internal_api_canaries/transport.c b/test/core/internal_api_canaries/transport.c index 01daabaa56..0617865412 100644 --- a/test/core/internal_api_canaries/transport.c +++ b/test/core/internal_api_canaries/transport.c @@ -1,6 +1,6 @@ /* * - * Copyright 2015-2016, Google Inc. + * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/test/core/surface/server_test.c b/test/core/surface/server_test.c index 4c62d8caad..beb685b338 100644 --- a/test/core/surface/server_test.c +++ b/test/core/surface/server_test.c @@ -1,6 +1,6 @@ /* * - * Copyright 2015-2016, Google Inc. + * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/test/cpp/end2end/client_crash_test.cc b/test/cpp/end2end/client_crash_test.cc index c01f40dbc2..30b04fb9b9 100644 --- a/test/cpp/end2end/client_crash_test.cc +++ b/test/cpp/end2end/client_crash_test.cc @@ -88,6 +88,7 @@ TEST_F(CrashTest, KillBeforeWrite) { EchoRequest request; EchoResponse response; ClientContext context; + context.set_fail_fast(false); auto stream = stub->BidiStream(&context); @@ -113,6 +114,7 @@ TEST_F(CrashTest, KillAfterWrite) { EchoRequest request; EchoResponse response; ClientContext context; + context.set_fail_fast(false); auto stream = stub->BidiStream(&context); diff --git a/test/cpp/end2end/server_crash_test_client.cc b/test/cpp/end2end/server_crash_test_client.cc index 1964840fa5..ece948d5a7 100644 --- a/test/cpp/end2end/server_crash_test_client.cc +++ b/test/cpp/end2end/server_crash_test_client.cc @@ -63,6 +63,7 @@ int main(int argc, char** argv) { EchoRequest request; EchoResponse response; grpc::ClientContext context; + context.set_fail_fast(false); if (FLAGS_mode == "bidi") { auto stream = stub->BidiStream(&context); diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index c07048578a..fc841e8887 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -812,6 +812,7 @@ src/core/lib/channel/context.h \ src/core/lib/channel/http_client_filter.h \ src/core/lib/channel/http_server_filter.h \ src/core/lib/channel/subchannel_call_holder.h \ +src/core/lib/client_config/client_channel_factory.h \ src/core/lib/client_config/client_config.h \ src/core/lib/client_config/connector.h \ src/core/lib/client_config/initial_connect_string.h \ @@ -822,7 +823,6 @@ src/core/lib/client_config/resolver.h \ src/core/lib/client_config/resolver_factory.h \ src/core/lib/client_config/resolver_registry.h \ src/core/lib/client_config/subchannel.h \ -src/core/lib/client_config/subchannel_factory.h \ src/core/lib/client_config/subchannel_index.h \ src/core/lib/client_config/uri_parser.h \ src/core/lib/compression/algorithm_metadata.h \ @@ -957,6 +957,7 @@ src/core/lib/channel/connected_channel.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ src/core/lib/channel/subchannel_call_holder.c \ +src/core/lib/client_config/client_channel_factory.c \ src/core/lib/client_config/client_config.c \ src/core/lib/client_config/connector.c \ src/core/lib/client_config/default_initial_connect_string.c \ @@ -968,7 +969,6 @@ src/core/lib/client_config/resolver.c \ src/core/lib/client_config/resolver_factory.c \ src/core/lib/client_config/resolver_registry.c \ src/core/lib/client_config/subchannel.c \ -src/core/lib/client_config/subchannel_factory.c \ src/core/lib/client_config/subchannel_index.c \ src/core/lib/client_config/uri_parser.c \ src/core/lib/compression/compression_algorithm.c \ diff --git a/tools/gce/create_interop_worker.sh b/tools/gce/create_interop_worker.sh index 3c49c6102a..9170d82144 100755 --- a/tools/gce/create_interop_worker.sh +++ b/tools/gce/create_interop_worker.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2015-2016, Google Inc. +# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tools/run_tests/performance/build_performance.sh b/tools/run_tests/performance/build_performance.sh index 829c2e3040..e5c0f86369 100755 --- a/tools/run_tests/performance/build_performance.sh +++ b/tools/run_tests/performance/build_performance.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2015-2016, Google Inc. +# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tools/run_tests/performance/remote_host_build.sh b/tools/run_tests/performance/remote_host_build.sh index fee4167d33..b8886080a5 100755 --- a/tools/run_tests/performance/remote_host_build.sh +++ b/tools/run_tests/performance/remote_host_build.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2015-2016, Google Inc. +# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tools/run_tests/performance/remote_host_prepare.sh b/tools/run_tests/performance/remote_host_prepare.sh index c70e1d3963..18633d1420 100755 --- a/tools/run_tests/performance/remote_host_prepare.sh +++ b/tools/run_tests/performance/remote_host_prepare.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2015-2016, Google Inc. +# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tools/run_tests/performance/run_worker_csharp.sh b/tools/run_tests/performance/run_worker_csharp.sh index ce34b203c3..b91df09b42 100755 --- a/tools/run_tests/performance/run_worker_csharp.sh +++ b/tools/run_tests/performance/run_worker_csharp.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2015-2016, Google Inc. +# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tools/run_tests/performance/run_worker_node.sh b/tools/run_tests/performance/run_worker_node.sh index 36bf1b20a0..46b6ff0177 100755 --- a/tools/run_tests/performance/run_worker_node.sh +++ b/tools/run_tests/performance/run_worker_node.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2015-2016, Google Inc. +# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tools/run_tests/run_node.sh b/tools/run_tests/run_node.sh index 30f2c93588..44f75645f5 100755 --- a/tools/run_tests/run_node.sh +++ b/tools/run_tests/run_node.sh @@ -48,6 +48,7 @@ if [ "$CONFIG" = "gcov" ] then ./node_modules/.bin/istanbul cover --dir reports/node_coverage \ -x **/interop/* ./node_modules/.bin/_mocha -- --timeout $timeout $test_directory + cp -r reports/node_coverage/lcov-report/* reports/node_coverage/ cd build gcov Release/obj.target/grpc/ext/*.o lcov --base-directory . --directory . -c -o coverage.info @@ -55,8 +56,6 @@ then genhtml -o ../reports/node_ext_coverage --num-spaces 2 \ -t 'Node gRPC test coverage' coverage.info --rc genhtml_hi_limit=95 \ --rc genhtml_med_limit=80 --no-prefix - echo '<html><head><meta http-equiv="refresh" content="0;URL=lcov-report/index.html"></head></html>' > \ - ../reports/node_coverage/index.html else JUNIT_REPORT_PATH=src/node/report.xml JUNIT_REPORT_STACK=1 \ ./node_modules/.bin/mocha --timeout $timeout \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index bc1e34b744..8bba9952d9 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -4040,6 +4040,7 @@ "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", "src/core/lib/channel/subchannel_call_holder.h", + "src/core/lib/client_config/client_channel_factory.h", "src/core/lib/client_config/client_config.h", "src/core/lib/client_config/connector.h", "src/core/lib/client_config/initial_connect_string.h", @@ -4050,7 +4051,6 @@ "src/core/lib/client_config/resolver_factory.h", "src/core/lib/client_config/resolver_registry.h", "src/core/lib/client_config/subchannel.h", - "src/core/lib/client_config/subchannel_factory.h", "src/core/lib/client_config/subchannel_index.h", "src/core/lib/client_config/uri_parser.h", "src/core/lib/compression/algorithm_metadata.h", @@ -4241,6 +4241,8 @@ "src/core/lib/channel/http_server_filter.h", "src/core/lib/channel/subchannel_call_holder.c", "src/core/lib/channel/subchannel_call_holder.h", + "src/core/lib/client_config/client_channel_factory.c", + "src/core/lib/client_config/client_channel_factory.h", "src/core/lib/client_config/client_config.c", "src/core/lib/client_config/client_config.h", "src/core/lib/client_config/connector.c", @@ -4262,8 +4264,6 @@ "src/core/lib/client_config/resolver_registry.h", "src/core/lib/client_config/subchannel.c", "src/core/lib/client_config/subchannel.h", - "src/core/lib/client_config/subchannel_factory.c", - "src/core/lib/client_config/subchannel_factory.h", "src/core/lib/client_config/subchannel_index.c", "src/core/lib/client_config/subchannel_index.h", "src/core/lib/client_config/uri_parser.c", @@ -4654,6 +4654,7 @@ "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", "src/core/lib/channel/subchannel_call_holder.h", + "src/core/lib/client_config/client_channel_factory.h", "src/core/lib/client_config/client_config.h", "src/core/lib/client_config/connector.h", "src/core/lib/client_config/initial_connect_string.h", @@ -4664,7 +4665,6 @@ "src/core/lib/client_config/resolver_factory.h", "src/core/lib/client_config/resolver_registry.h", "src/core/lib/client_config/subchannel.h", - "src/core/lib/client_config/subchannel_factory.h", "src/core/lib/client_config/subchannel_index.h", "src/core/lib/client_config/uri_parser.h", "src/core/lib/compression/algorithm_metadata.h", @@ -4838,6 +4838,8 @@ "src/core/lib/channel/http_server_filter.h", "src/core/lib/channel/subchannel_call_holder.c", "src/core/lib/channel/subchannel_call_holder.h", + "src/core/lib/client_config/client_channel_factory.c", + "src/core/lib/client_config/client_channel_factory.h", "src/core/lib/client_config/client_config.c", "src/core/lib/client_config/client_config.h", "src/core/lib/client_config/connector.c", @@ -4859,8 +4861,6 @@ "src/core/lib/client_config/resolver_registry.h", "src/core/lib/client_config/subchannel.c", "src/core/lib/client_config/subchannel.h", - "src/core/lib/client_config/subchannel_factory.c", - "src/core/lib/client_config/subchannel_factory.h", "src/core/lib/client_config/subchannel_index.c", "src/core/lib/client_config/subchannel_index.h", "src/core/lib/client_config/uri_parser.c", diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index f54c8c643d..10a87f7ae8 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -321,6 +321,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_client_filter.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\subchannel_call_holder.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\client_channel_factory.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\client_config.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\connector.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\initial_connect_string.h" /> @@ -331,7 +332,6 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\resolver_factory.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\resolver_registry.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel.h" /> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel_factory.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel_index.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\uri_parser.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h" /> @@ -517,6 +517,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\subchannel_call_holder.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\client_channel_factory.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\client_config.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\connector.c"> @@ -539,8 +541,6 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel.c"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel_factory.c"> - </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel_index.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\uri_parser.c"> diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index c00b928571..c32f03358c 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -148,6 +148,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\subchannel_call_holder.c"> <Filter>src\core\lib\channel</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\client_channel_factory.c"> + <Filter>src\core\lib\client_config</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\client_config.c"> <Filter>src\core\lib\client_config</Filter> </ClCompile> @@ -181,9 +184,6 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel.c"> <Filter>src\core\lib\client_config</Filter> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel_factory.c"> - <Filter>src\core\lib\client_config</Filter> - </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel_index.c"> <Filter>src\core\lib\client_config</Filter> </ClCompile> @@ -647,6 +647,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\subchannel_call_holder.h"> <Filter>src\core\lib\channel</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\client_channel_factory.h"> + <Filter>src\core\lib\client_config</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\client_config.h"> <Filter>src\core\lib\client_config</Filter> </ClInclude> @@ -677,9 +680,6 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel.h"> <Filter>src\core\lib\client_config</Filter> </ClInclude> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel_factory.h"> - <Filter>src\core\lib\client_config</Filter> - </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel_index.h"> <Filter>src\core\lib\client_config</Filter> </ClInclude> diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index ec8624fb34..1b064aad2e 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -311,6 +311,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_client_filter.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\subchannel_call_holder.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\client_channel_factory.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\client_config.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\connector.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\initial_connect_string.h" /> @@ -321,7 +322,6 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\resolver_factory.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\resolver_registry.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel.h" /> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel_factory.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel_index.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\uri_parser.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h" /> @@ -489,6 +489,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\subchannel_call_holder.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\client_channel_factory.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\client_config.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\connector.c"> @@ -511,8 +513,6 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel.c"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel_factory.c"> - </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel_index.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\uri_parser.c"> diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index 95b76b33de..9fd878bc2c 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -142,6 +142,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\subchannel_call_holder.c"> <Filter>src\core\lib\channel</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\client_channel_factory.c"> + <Filter>src\core\lib\client_config</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\client_config.c"> <Filter>src\core\lib\client_config</Filter> </ClCompile> @@ -175,9 +178,6 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel.c"> <Filter>src\core\lib\client_config</Filter> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel_factory.c"> - <Filter>src\core\lib\client_config</Filter> - </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel_index.c"> <Filter>src\core\lib\client_config</Filter> </ClCompile> @@ -584,6 +584,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\subchannel_call_holder.h"> <Filter>src\core\lib\channel</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\client_channel_factory.h"> + <Filter>src\core\lib\client_config</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\client_config.h"> <Filter>src\core\lib\client_config</Filter> </ClInclude> @@ -614,9 +617,6 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel.h"> <Filter>src\core\lib\client_config</Filter> </ClInclude> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel_factory.h"> - <Filter>src\core\lib\client_config</Filter> - </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\client_config\subchannel_index.h"> <Filter>src\core\lib\client_config</Filter> </ClInclude> |