aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/node_generator.cc21
-rw-r--r--src/compiler/node_generator.h9
-rw-r--r--src/compiler/node_plugin.cc22
-rw-r--r--src/core/ext/filters/client_channel/channel_connectivity.cc2
-rw-r--r--src/core/ext/filters/client_channel/client_channel.cc159
-rw-r--r--src/core/ext/filters/client_channel/lb_policy.cc4
-rw-r--r--src/core/ext/filters/client_channel/lb_policy.h2
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc20
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc91
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h36
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc138
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h69
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc41
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h2
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc365
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc743
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc253
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/subchannel_list.h596
-rw-r--r--src/core/ext/filters/client_channel/method_params.h4
-rw-r--r--src/core/ext/filters/client_channel/resolver.h2
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc30
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc1
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc32
-rw-r--r--src/core/ext/filters/client_channel/retry_throttle.h4
-rw-r--r--src/core/ext/filters/client_channel/subchannel.cc4
-rw-r--r--src/core/ext/filters/http/client_authority_filter.cc9
-rw-r--r--src/core/ext/filters/http/message_compress/message_compress_filter.cc12
-rw-r--r--src/core/ext/transport/chttp2/transport/bin_decoder.cc17
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.cc51
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_settings.cc6
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_encoder.cc4
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_parser.cc2
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_table.cc4
-rw-r--r--src/core/ext/transport/chttp2/transport/parsing.cc26
-rw-r--r--src/core/ext/transport/chttp2/transport/stream_lists.cc6
-rw-r--r--src/core/ext/transport/chttp2/transport/writing.cc22
-rw-r--r--src/core/ext/transport/cronet/transport/cronet_transport.cc8
-rw-r--r--src/core/ext/transport/inproc/inproc_transport.cc84
-rw-r--r--src/core/lib/channel/channel_stack.cc5
-rw-r--r--src/core/lib/channel/channel_stack_builder.cc3
-rw-r--r--src/core/lib/channel/channel_stack_builder.h2
-rw-r--r--src/core/lib/channel/channel_trace.cc6
-rw-r--r--src/core/lib/channel/channel_trace_registry.cc80
-rw-r--r--src/core/lib/channel/channel_trace_registry.h43
-rw-r--r--src/core/lib/channel/channelz_registry.cc77
-rw-r--r--src/core/lib/channel/channelz_registry.h99
-rw-r--r--src/core/lib/channel/handshaker.cc27
-rw-r--r--src/core/lib/debug/stats.h7
-rw-r--r--src/core/lib/debug/stats_data.cc5
-rw-r--r--src/core/lib/debug/stats_data.h120
-rw-r--r--src/core/lib/debug/stats_data.yaml6
-rw-r--r--src/core/lib/debug/stats_data_bq_schema.sql2
-rw-r--r--src/core/lib/debug/trace.h11
-rw-r--r--src/core/lib/gpr/fork.cc78
-rw-r--r--src/core/lib/gpr/fork.h35
-rw-r--r--src/core/lib/gprpp/fork.cc260
-rw-r--r--src/core/lib/gprpp/fork.h79
-rw-r--r--src/core/lib/gprpp/memory.h12
-rw-r--r--src/core/lib/gprpp/orphanable.h16
-rw-r--r--src/core/lib/gprpp/ref_counted.h16
-rw-r--r--src/core/lib/gprpp/thd.h3
-rw-r--r--src/core/lib/gprpp/thd_posix.cc57
-rw-r--r--src/core/lib/gprpp/thd_windows.cc7
-rw-r--r--src/core/lib/http/httpcli_security_connector.cc4
-rw-r--r--src/core/lib/iomgr/call_combiner.cc26
-rw-r--r--src/core/lib/iomgr/closure.h6
-rw-r--r--src/core/lib/iomgr/combiner.cc41
-rw-r--r--src/core/lib/iomgr/ev_epoll1_linux.cc48
-rw-r--r--src/core/lib/iomgr/ev_epollex_linux.cc110
-rw-r--r--src/core/lib/iomgr/ev_epollsig_linux.cc4
-rw-r--r--src/core/lib/iomgr/ev_poll_posix.cc6
-rw-r--r--src/core/lib/iomgr/ev_posix.cc13
-rw-r--r--src/core/lib/iomgr/ev_posix.h6
-rw-r--r--src/core/lib/iomgr/exec_ctx.h53
-rw-r--r--src/core/lib/iomgr/executor.cc12
-rw-r--r--src/core/lib/iomgr/fork_posix.cc48
-rw-r--r--src/core/lib/iomgr/resource_quota.cc23
-rw-r--r--src/core/lib/iomgr/tcp_client_custom.cc4
-rw-r--r--src/core/lib/iomgr/tcp_client_posix.cc11
-rw-r--r--src/core/lib/iomgr/tcp_custom.cc22
-rw-r--r--src/core/lib/iomgr/tcp_posix.cc54
-rw-r--r--src/core/lib/iomgr/tcp_server_custom.cc10
-rw-r--r--src/core/lib/iomgr/tcp_server_posix.cc15
-rw-r--r--src/core/lib/iomgr/tcp_server_utils_posix.h2
-rw-r--r--src/core/lib/iomgr/tcp_server_utils_posix_common.cc16
-rw-r--r--src/core/lib/iomgr/tcp_windows.cc16
-rw-r--r--src/core/lib/iomgr/timer_generic.cc34
-rw-r--r--src/core/lib/iomgr/timer_manager.cc23
-rw-r--r--src/core/lib/profiling/basic_timers.cc1
-rw-r--r--src/core/lib/security/credentials/credentials.h1
-rw-r--r--src/core/lib/security/credentials/google_default/google_default_credentials.cc203
-rw-r--r--src/core/lib/security/credentials/google_default/google_default_credentials.h16
-rw-r--r--src/core/lib/security/security_connector/alts_security_connector.cc3
-rw-r--r--src/core/lib/security/security_connector/security_connector.cc49
-rw-r--r--src/core/lib/security/security_connector/security_connector.h7
-rw-r--r--src/core/lib/security/transport/secure_endpoint.cc4
-rw-r--r--src/core/lib/security/transport/security_handshaker.cc5
-rw-r--r--src/core/lib/slice/slice_hash_table.h4
-rw-r--r--src/core/lib/slice/slice_weak_hash_table.h4
-rw-r--r--src/core/lib/surface/call.cc55
-rw-r--r--src/core/lib/surface/call.h5
-rw-r--r--src/core/lib/surface/channel.cc7
-rw-r--r--src/core/lib/surface/completion_queue.cc1
-rw-r--r--src/core/lib/surface/init.cc15
-rw-r--r--src/core/lib/surface/server.cc16
-rw-r--r--src/core/lib/surface/version.cc2
-rw-r--r--src/core/lib/transport/bdp_estimator.cc6
-rw-r--r--src/core/lib/transport/bdp_estimator.h4
-rw-r--r--src/core/lib/transport/byte_stream.cc2
-rw-r--r--src/core/lib/transport/connectivity_state.cc13
-rw-r--r--src/core/tsi/alts/handshaker/alts_handshaker_client.cc26
-rw-r--r--src/core/tsi/alts/handshaker/alts_handshaker_client.h10
-rw-r--r--src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc30
-rw-r--r--src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h3
-rw-r--r--src/core/tsi/fake_transport_security.cc1
-rw-r--r--src/core/tsi/ssl/session_cache/ssl_session_cache.h4
-rw-r--r--src/core/tsi/ssl_transport_security.cc348
-rw-r--r--src/core/tsi/transport_security.cc14
-rw-r--r--src/core/tsi/transport_security.h2
-rw-r--r--src/core/tsi/transport_security_adapter.cc235
-rw-r--r--src/core/tsi/transport_security_adapter.h41
-rw-r--r--src/core/tsi/transport_security_interface.h12
-rw-r--r--src/cpp/common/version_cc.cc2
-rw-r--r--src/cpp/server/load_reporter/load_data_store.cc273
-rw-r--r--src/cpp/server/load_reporter/load_data_store.h339
-rw-r--r--src/csharp/Grpc.Core.Testing/TestServerCallContext.cs58
-rw-r--r--src/csharp/Grpc.Core/ServerCallContext.cs34
-rwxr-xr-xsrc/csharp/Grpc.Core/Version.csproj.include2
-rw-r--r--src/csharp/Grpc.Core/VersionInfo.cs4
-rw-r--r--src/csharp/Grpc.Examples/Math.cs86
-rw-r--r--src/csharp/Grpc.HealthCheck/Health.cs42
-rw-r--r--src/csharp/Grpc.HealthCheck/HealthGrpc.cs5
-rw-r--r--src/csharp/Grpc.IntegrationTesting/BenchmarkService.cs6
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Control.cs386
-rw-r--r--src/csharp/Grpc.IntegrationTesting/CoreStats/Stats.cs74
-rw-r--r--src/csharp/Grpc.IntegrationTesting/EchoMessages.cs102
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Empty.cs22
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Messages.cs198
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Metrics.cs58
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Payloads.cs70
-rw-r--r--src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioService.cs6
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Stats.cs138
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Test.cs6
-rw-r--r--src/csharp/Grpc.IntegrationTesting/WorkerService.cs6
-rw-r--r--src/csharp/Grpc.Reflection/Reflection.cs134
-rw-r--r--src/csharp/README.md29
-rwxr-xr-xsrc/csharp/build_packages_dotnetcli.bat2
-rwxr-xr-xsrc/csharp/build_packages_dotnetcli.sh4
-rwxr-xr-xsrc/csharp/experimental/build_native_ext_for_android.sh2
-rw-r--r--src/objective-c/!ProtoCompiler-gRPCPlugin.podspec2
-rw-r--r--src/objective-c/BoringSSL.podspec11
-rw-r--r--src/objective-c/GRPCClient/private/GRPCChannel.m1
-rw-r--r--src/objective-c/GRPCClient/private/GRPCHost.m3
-rw-r--r--src/objective-c/GRPCClient/private/NSDictionary+GRPC.m2
-rw-r--r--src/objective-c/GRPCClient/private/NSError+GRPC.m2
-rw-r--r--src/objective-c/GRPCClient/private/version.h2
-rw-r--r--src/objective-c/tests/version.h2
-rwxr-xr-xsrc/php/bin/run_tests.sh6
-rw-r--r--src/php/composer.json2
-rw-r--r--src/php/ext/grpc/byte_buffer.c14
-rw-r--r--src/php/ext/grpc/call.c57
-rw-r--r--src/php/ext/grpc/call.h21
-rw-r--r--src/php/ext/grpc/call_credentials.c31
-rw-r--r--src/php/ext/grpc/call_credentials.h22
-rw-r--r--src/php/ext/grpc/channel.c444
-rw-r--r--src/php/ext/grpc/channel.h32
-rw-r--r--src/php/ext/grpc/channel_credentials.c35
-rw-r--r--src/php/ext/grpc/channel_credentials.h22
-rw-r--r--src/php/ext/grpc/completion_queue.c2
-rwxr-xr-xsrc/php/ext/grpc/config.m48
-rw-r--r--src/php/ext/grpc/php7_wrapper.h24
-rw-r--r--src/php/ext/grpc/php_grpc.c14
-rw-r--r--src/php/ext/grpc/php_grpc.h18
-rw-r--r--src/php/ext/grpc/server.c77
-rw-r--r--src/php/ext/grpc/server.h20
-rw-r--r--src/php/ext/grpc/server_credentials.c20
-rw-r--r--src/php/ext/grpc/server_credentials.h20
-rw-r--r--src/php/ext/grpc/timeval.c54
-rw-r--r--src/php/ext/grpc/timeval.h22
-rw-r--r--src/php/ext/grpc/version.h2
-rw-r--r--src/php/lib/Grpc/BaseStub.php403
-rw-r--r--src/php/lib/Grpc/Interceptor.php86
-rw-r--r--src/php/lib/Grpc/Internal/InterceptorChannel.php76
-rw-r--r--src/php/tests/unit_tests/CallCredentials2Test.php3
-rw-r--r--src/php/tests/unit_tests/CallCredentialsTest.php3
-rw-r--r--src/php/tests/unit_tests/CallTest.php3
-rw-r--r--src/php/tests/unit_tests/ChannelTest.php243
-rw-r--r--src/php/tests/unit_tests/EndToEndTest.php3
-rw-r--r--src/php/tests/unit_tests/InterceptorTest.php423
-rw-r--r--src/php/tests/unit_tests/PersistentChannelTest.php115
-rw-r--r--src/php/tests/unit_tests/PersistentChannelTests/PersistentChannelTest.php489
-rw-r--r--src/php/tests/unit_tests/SecureEndToEndTest.php3
-rw-r--r--src/php/tests/unit_tests/ServerTest.php21
-rw-r--r--src/php/tests/unit_tests/TimevalTest.php3
-rw-r--r--src/proto/grpc/health/v1/health.proto10
-rw-r--r--src/proto/grpc/lb/v1/load_balancer.proto6
-rw-r--r--src/python/grpcio/grpc/__init__.py17
-rw-r--r--src/python/grpcio/grpc/_channel.py445
-rw-r--r--src/python/grpcio/grpc/_common.py34
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/channel.pxd.pxi56
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi477
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd.pxi8
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi93
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi1
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/operation.pxd.pxi2
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/operation.pyx.pxi10
-rw-r--r--src/python/grpcio/grpc/_grpcio_metadata.py2
-rw-r--r--src/python/grpcio/grpc/_interceptor.py13
-rw-r--r--src/python/grpcio/grpc/_server.py10
-rw-r--r--src/python/grpcio/grpc/beta/_server_adaptations.py7
-rw-r--r--src/python/grpcio/grpc_core_dependencies.py6
-rw-r--r--src/python/grpcio/grpc_version.py2
-rw-r--r--src/python/grpcio_health_checking/grpc_version.py2
-rw-r--r--src/python/grpcio_reflection/grpc_version.py2
-rw-r--r--src/python/grpcio_testing/grpc_testing/_channel/_channel.py15
-rw-r--r--src/python/grpcio_testing/grpc_version.py2
-rw-r--r--src/python/grpcio_tests/grpc_version.py2
-rw-r--r--src/python/grpcio_tests/setup.py5
-rw-r--r--src/python/grpcio_tests/tests/tests.json2
-rw-r--r--src/python/grpcio_tests/tests/unit/_channel_close_test.py185
-rw-r--r--src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py50
-rw-r--r--src/python/grpcio_tests/tests/unit/_cython/_channel_test.py28
-rw-r--r--src/python/grpcio_tests/tests/unit/_cython/_common.py3
-rw-r--r--src/python/grpcio_tests/tests/unit/_cython/_no_messages_server_completion_queue_per_call_test.py54
-rw-r--r--src/python/grpcio_tests/tests/unit/_cython/_no_messages_single_server_completion_queue_test.py55
-rw-r--r--src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py73
-rw-r--r--src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py112
-rw-r--r--src/python/grpcio_tests/tests/unit/_invalid_metadata_test.py49
-rw-r--r--src/python/grpcio_tests/tests/unit/_rpc_test.py8
-rw-r--r--src/python/grpcio_tests/tests/unit/_thread_cleanup_test.py115
-rwxr-xr-xsrc/ruby/bin/math_client.rb26
-rw-r--r--src/ruby/lib/grpc/generic/rpc_server.rb3
-rw-r--r--src/ruby/lib/grpc/version.rb2
-rw-r--r--src/ruby/pb/grpc/health/v1/health_services_pb.rb5
-rwxr-xr-xsrc/ruby/pb/test/client.rb2
-rw-r--r--src/ruby/tools/version.rb2
236 files changed, 8331 insertions, 4337 deletions
diff --git a/src/compiler/node_generator.cc b/src/compiler/node_generator.cc
index 661587cbd6..a430628dbc 100644
--- a/src/compiler/node_generator.cc
+++ b/src/compiler/node_generator.cc
@@ -20,6 +20,7 @@
#include "src/compiler/config.h"
#include "src/compiler/generator_helpers.h"
+#include "src/compiler/node_generator.h"
#include "src/compiler/node_generator_helpers.h"
using grpc::protobuf::Descriptor;
@@ -119,7 +120,8 @@ grpc::string NodeObjectPath(const Descriptor* descriptor) {
}
// Prints out the message serializer and deserializer functions
-void PrintMessageTransformer(const Descriptor* descriptor, Printer* out) {
+void PrintMessageTransformer(const Descriptor* descriptor, Printer* out,
+ const Parameters& params) {
map<grpc::string, grpc::string> template_vars;
grpc::string full_name = descriptor->full_name();
template_vars["identifier_name"] = MessageIdentifierName(full_name);
@@ -134,7 +136,12 @@ void PrintMessageTransformer(const Descriptor* descriptor, Printer* out) {
"throw new Error('Expected argument of type $name$');\n");
out->Outdent();
out->Print("}\n");
- out->Print("return new Buffer(arg.serializeBinary());\n");
+ if (params.minimum_node_version > 5) {
+ // Node version is > 5, we should use Buffer.from
+ out->Print("return Buffer.from(arg.serializeBinary());\n");
+ } else {
+ out->Print("return new Buffer(arg.serializeBinary());\n");
+ }
out->Outdent();
out->Print("}\n\n");
@@ -219,12 +226,13 @@ void PrintImports(const FileDescriptor* file, Printer* out) {
out->Print("\n");
}
-void PrintTransformers(const FileDescriptor* file, Printer* out) {
+void PrintTransformers(const FileDescriptor* file, Printer* out,
+ const Parameters& params) {
map<grpc::string, const Descriptor*> messages = GetAllMessages(file);
for (std::map<grpc::string, const Descriptor*>::iterator it =
messages.begin();
it != messages.end(); it++) {
- PrintMessageTransformer(it->second, out);
+ PrintMessageTransformer(it->second, out, params);
}
out->Print("\n");
}
@@ -236,7 +244,8 @@ void PrintServices(const FileDescriptor* file, Printer* out) {
}
} // namespace
-grpc::string GenerateFile(const FileDescriptor* file) {
+grpc::string GenerateFile(const FileDescriptor* file,
+ const Parameters& params) {
grpc::string output;
{
StringOutputStream output_stream(&output);
@@ -257,7 +266,7 @@ grpc::string GenerateFile(const FileDescriptor* file) {
PrintImports(file, &out);
- PrintTransformers(file, &out);
+ PrintTransformers(file, &out, params);
PrintServices(file, &out);
diff --git a/src/compiler/node_generator.h b/src/compiler/node_generator.h
index a9ffe75fc8..f3a531597a 100644
--- a/src/compiler/node_generator.h
+++ b/src/compiler/node_generator.h
@@ -23,7 +23,14 @@
namespace grpc_node_generator {
-grpc::string GenerateFile(const grpc::protobuf::FileDescriptor* file);
+// Contains all the parameters that are parsed from the command line.
+struct Parameters {
+ // Sets the earliest version of nodejs that needs to be supported.
+ int minimum_node_version;
+};
+
+grpc::string GenerateFile(const grpc::protobuf::FileDescriptor* file,
+ const Parameters& params);
} // namespace grpc_node_generator
diff --git a/src/compiler/node_plugin.cc b/src/compiler/node_plugin.cc
index bc38e9018a..0d19d8e982 100644
--- a/src/compiler/node_plugin.cc
+++ b/src/compiler/node_plugin.cc
@@ -36,7 +36,27 @@ class NodeGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
const grpc::string& parameter,
grpc::protobuf::compiler::GeneratorContext* context,
grpc::string* error) const {
- grpc::string code = GenerateFile(file);
+ grpc_node_generator::Parameters generator_parameters;
+ generator_parameters.minimum_node_version = 4;
+
+ if (!parameter.empty()) {
+ std::vector<grpc::string> parameters_list =
+ grpc_generator::tokenize(parameter, ",");
+ for (auto parameter_string = parameters_list.begin();
+ parameter_string != parameters_list.end(); parameter_string++) {
+ std::vector<grpc::string> param =
+ grpc_generator::tokenize(*parameter_string, "=");
+ if (param[0] == "minimum_node_version") {
+ sscanf(param[1].c_str(), "%d",
+ &generator_parameters.minimum_node_version);
+ } else {
+ *error = grpc::string("Unknown parameter: ") + *parameter_string;
+ return false;
+ }
+ }
+ }
+
+ grpc::string code = GenerateFile(file, generator_parameters);
if (code.size() == 0) {
return true;
}
diff --git a/src/core/ext/filters/client_channel/channel_connectivity.cc b/src/core/ext/filters/client_channel/channel_connectivity.cc
index 37860e82e3..c71d10274a 100644
--- a/src/core/ext/filters/client_channel/channel_connectivity.cc
+++ b/src/core/ext/filters/client_channel/channel_connectivity.cc
@@ -40,7 +40,7 @@ grpc_connectivity_state grpc_channel_check_connectivity_state(
GRPC_API_TRACE(
"grpc_channel_check_connectivity_state(channel=%p, try_to_connect=%d)", 2,
(channel, try_to_connect));
- if (client_channel_elem->filter == &grpc_client_channel_filter) {
+ if (GPR_LIKELY(client_channel_elem->filter == &grpc_client_channel_filter)) {
state = grpc_client_channel_check_connectivity_state(client_channel_elem,
try_to_connect);
diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc
index 33cf56519e..fa0c280f80 100644
--- a/src/core/ext/filters/client_channel/client_channel.cc
+++ b/src/core/ext/filters/client_channel/client_channel.cc
@@ -174,7 +174,7 @@ static void set_channel_connectivity_state_locked(channel_data* chand,
}
}
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p: setting connectivity state to %s", chand,
+ gpr_log(GPR_INFO, "chand=%p: setting connectivity state to %s", chand,
grpc_connectivity_state_name(state));
}
grpc_connectivity_state_set(&chand->state_tracker, state, error, reason);
@@ -186,7 +186,7 @@ static void on_lb_policy_state_changed_locked(void* arg, grpc_error* error) {
/* check if the notification is for the latest policy */
if (w->lb_policy == w->chand->lb_policy.get()) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p: lb_policy=%p state changed to %s", w->chand,
+ gpr_log(GPR_INFO, "chand=%p: lb_policy=%p state changed to %s", w->chand,
w->lb_policy, grpc_connectivity_state_name(w->state));
}
set_channel_connectivity_state_locked(w->chand, w->state,
@@ -215,7 +215,7 @@ static void watch_lb_policy_locked(channel_data* chand,
static void start_resolving_locked(channel_data* chand) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p: starting name resolution", chand);
+ gpr_log(GPR_INFO, "chand=%p: starting name resolution", chand);
}
GPR_ASSERT(!chand->started_resolving);
chand->started_resolving = true;
@@ -297,7 +297,7 @@ static void request_reresolution_locked(void* arg, grpc_error* error) {
return;
}
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p: started name re-resolving", chand);
+ gpr_log(GPR_INFO, "chand=%p: started name re-resolving", chand);
}
chand->resolver->RequestReresolutionLocked();
// Give back the closure to the LB policy.
@@ -311,7 +311,7 @@ static void request_reresolution_locked(void* arg, grpc_error* error) {
static void on_resolver_result_changed_locked(void* arg, grpc_error* error) {
channel_data* chand = static_cast<channel_data*>(arg);
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p: got resolver result: resolver_result=%p error=%s", chand,
chand->resolver_result, grpc_error_string(error));
}
@@ -379,7 +379,7 @@ static void on_resolver_result_changed_locked(void* arg, grpc_error* error) {
new_lb_policy =
grpc_core::LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(
lb_policy_name, lb_policy_args);
- if (new_lb_policy == nullptr) {
+ if (GPR_UNLIKELY(new_lb_policy == nullptr)) {
gpr_log(GPR_ERROR, "could not create LB policy \"%s\"",
lb_policy_name);
} else {
@@ -431,7 +431,7 @@ static void on_resolver_result_changed_locked(void* arg, grpc_error* error) {
}
}
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p: resolver result: lb_policy_name=\"%s\"%s, "
"service_config=\"%s\"",
chand, lb_policy_name_dup,
@@ -466,7 +466,7 @@ static void on_resolver_result_changed_locked(void* arg, grpc_error* error) {
chand->resolver == nullptr) {
if (chand->lb_policy != nullptr) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p: unreffing lb_policy=%p", chand,
+ gpr_log(GPR_INFO, "chand=%p: unreffing lb_policy=%p", chand,
chand->lb_policy.get());
}
grpc_pollset_set_del_pollset_set(chand->lb_policy->interested_parties(),
@@ -480,11 +480,11 @@ static void on_resolver_result_changed_locked(void* arg, grpc_error* error) {
// error or shutdown.
if (error != GRPC_ERROR_NONE || chand->resolver == nullptr) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p: shutting down", chand);
+ gpr_log(GPR_INFO, "chand=%p: shutting down", chand);
}
if (chand->resolver != nullptr) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p: shutting down resolver", chand);
+ gpr_log(GPR_INFO, "chand=%p: shutting down resolver", chand);
}
chand->resolver.reset();
}
@@ -506,7 +506,7 @@ static void on_resolver_result_changed_locked(void* arg, grpc_error* error) {
GRPC_ERROR_CREATE_FROM_STATIC_STRING("No load balancing policy");
if (lb_policy_created) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p: initializing new LB policy", chand);
+ gpr_log(GPR_INFO, "chand=%p: initializing new LB policy", chand);
}
GRPC_ERROR_UNREF(state_error);
state = chand->lb_policy->CheckConnectivityLocked(&state_error);
@@ -999,7 +999,7 @@ static void maybe_cache_send_ops_for_batch(call_data* calld,
static void free_cached_send_initial_metadata(channel_data* chand,
call_data* calld) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: destroying calld->send_initial_metadata", chand,
calld);
}
@@ -1010,7 +1010,7 @@ static void free_cached_send_initial_metadata(channel_data* chand,
static void free_cached_send_message(channel_data* chand, call_data* calld,
size_t idx) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: destroying calld->send_messages[%" PRIuPTR "]",
chand, calld, idx);
}
@@ -1021,7 +1021,7 @@ static void free_cached_send_message(channel_data* chand, call_data* calld,
static void free_cached_send_trailing_metadata(channel_data* chand,
call_data* calld) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: destroying calld->send_trailing_metadata",
chand, calld);
}
@@ -1088,7 +1088,7 @@ static void pending_batches_add(grpc_call_element* elem,
call_data* calld = static_cast<call_data*>(elem->call_data);
const size_t idx = get_batch_index(batch);
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: adding pending batch at index %" PRIuPTR, chand,
calld, idx);
}
@@ -1116,7 +1116,7 @@ static void pending_batches_add(grpc_call_element* elem,
}
if (calld->bytes_buffered_for_retry > chand->per_rpc_retry_buffer_size) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: exceeded retry buffer size, committing",
chand, calld);
}
@@ -1131,7 +1131,7 @@ static void pending_batches_add(grpc_call_element* elem,
// retries are disabled so that we don't bother with retry overhead.
if (calld->num_attempts_completed == 0) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: disabling retries before first attempt",
chand, calld);
}
@@ -1178,7 +1178,7 @@ static void pending_batches_fail(grpc_call_element* elem, grpc_error* error,
for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) {
if (calld->pending_batches[i].batch != nullptr) ++num_batches;
}
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: failing %" PRIuPTR " pending batches: %s",
elem->channel_data, calld, num_batches, grpc_error_string(error));
}
@@ -1240,7 +1240,7 @@ static void pending_batches_resume(grpc_call_element* elem) {
for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) {
if (calld->pending_batches[i].batch != nullptr) ++num_batches;
}
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: starting %" PRIuPTR
" pending batches on subchannel_call=%p",
chand, calld, num_batches, calld->subchannel_call);
@@ -1285,7 +1285,7 @@ static void maybe_clear_pending_batch(grpc_call_element* elem,
(!batch->recv_message ||
batch->payload->recv_message.recv_message_ready == nullptr)) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: clearing pending batch", chand,
+ gpr_log(GPR_INFO, "chand=%p calld=%p: clearing pending batch", chand,
calld);
}
pending_batch_clear(calld, pending);
@@ -1375,7 +1375,7 @@ static void retry_commit(grpc_call_element* elem,
if (calld->retry_committed) return;
calld->retry_committed = true;
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: committing retries", chand, calld);
+ gpr_log(GPR_INFO, "chand=%p calld=%p: committing retries", chand, calld);
}
if (retry_state != nullptr) {
free_cached_send_op_data_after_commit(elem, retry_state);
@@ -1420,7 +1420,7 @@ static void do_retry(grpc_call_element* elem,
next_attempt_time = calld->retry_backoff->NextAttemptTime();
}
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: retrying failed call in %" PRIuPTR " ms", chand,
calld, next_attempt_time - grpc_core::ExecCtx::Get()->Now());
}
@@ -1454,7 +1454,7 @@ static bool maybe_retry(grpc_call_element* elem,
batch_data->subchannel_call));
if (retry_state->retry_dispatched) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: retry already dispatched", chand,
+ gpr_log(GPR_INFO, "chand=%p calld=%p: retry already dispatched", chand,
calld);
}
return true;
@@ -1466,14 +1466,14 @@ static bool maybe_retry(grpc_call_element* elem,
calld->retry_throttle_data->RecordSuccess();
}
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: call succeeded", chand, calld);
+ gpr_log(GPR_INFO, "chand=%p calld=%p: call succeeded", chand, calld);
}
return false;
}
// Status is not OK. Check whether the status is retryable.
if (!retry_policy->retryable_status_codes.Contains(status)) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: status %s not configured as retryable", chand,
calld, grpc_status_code_to_string(status));
}
@@ -1489,14 +1489,14 @@ static bool maybe_retry(grpc_call_element* elem,
if (calld->retry_throttle_data != nullptr &&
!calld->retry_throttle_data->RecordFailure()) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: retries throttled", chand, calld);
+ gpr_log(GPR_INFO, "chand=%p calld=%p: retries throttled", chand, calld);
}
return false;
}
// Check whether the call is committed.
if (calld->retry_committed) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: retries already committed", chand,
+ gpr_log(GPR_INFO, "chand=%p calld=%p: retries already committed", chand,
calld);
}
return false;
@@ -1505,7 +1505,7 @@ static bool maybe_retry(grpc_call_element* elem,
++calld->num_attempts_completed;
if (calld->num_attempts_completed >= retry_policy->max_attempts) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: exceeded %d retry attempts", chand,
+ gpr_log(GPR_INFO, "chand=%p calld=%p: exceeded %d retry attempts", chand,
calld, retry_policy->max_attempts);
}
return false;
@@ -1513,7 +1513,7 @@ static bool maybe_retry(grpc_call_element* elem,
// If the call was cancelled from the surface, don't retry.
if (calld->cancel_error != GRPC_ERROR_NONE) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: call cancelled from surface, not retrying",
chand, calld);
}
@@ -1526,16 +1526,15 @@ static bool maybe_retry(grpc_call_element* elem,
uint32_t ms;
if (!grpc_parse_slice_to_uint32(GRPC_MDVALUE(*server_pushback_md), &ms)) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: not retrying due to server push-back",
chand, calld);
}
return false;
} else {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
- "chand=%p calld=%p: server push-back: retry in %u ms", chand,
- calld, ms);
+ gpr_log(GPR_INFO, "chand=%p calld=%p: server push-back: retry in %u ms",
+ chand, calld, ms);
}
server_pushback_ms = (grpc_millis)ms;
}
@@ -1608,7 +1607,7 @@ static void invoke_recv_initial_metadata_callback(void* arg,
batch->payload->recv_initial_metadata.recv_initial_metadata_ready !=
nullptr) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: invoking recv_initial_metadata_ready for "
"pending batch at index %" PRIuPTR,
chand, calld, i);
@@ -1644,7 +1643,7 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: got recv_initial_metadata_ready, error=%s",
chand, calld, grpc_error_string(error));
}
@@ -1659,7 +1658,7 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) {
if ((batch_data->trailing_metadata_available || error != GRPC_ERROR_NONE) &&
!retry_state->completed_recv_trailing_metadata) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: deferring recv_initial_metadata_ready "
"(Trailers-Only)",
chand, calld);
@@ -1701,7 +1700,7 @@ static void invoke_recv_message_callback(void* arg, grpc_error* error) {
if (batch != nullptr && batch->recv_message &&
batch->payload->recv_message.recv_message_ready != nullptr) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: invoking recv_message_ready for "
"pending batch at index %" PRIuPTR,
chand, calld, i);
@@ -1734,7 +1733,7 @@ static void recv_message_ready(void* arg, grpc_error* error) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: got recv_message_ready, error=%s",
+ gpr_log(GPR_INFO, "chand=%p calld=%p: got recv_message_ready, error=%s",
chand, calld, grpc_error_string(error));
}
subchannel_call_retry_state* retry_state =
@@ -1748,7 +1747,7 @@ static void recv_message_ready(void* arg, grpc_error* error) {
if ((batch_data->recv_message == nullptr || error != GRPC_ERROR_NONE) &&
!retry_state->completed_recv_trailing_metadata) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: deferring recv_message_ready (nullptr "
"message and recv_trailing_metadata pending)",
chand, calld);
@@ -1796,7 +1795,7 @@ static void execute_closures_in_call_combiner(grpc_call_element* elem,
// have to re-enter the call combiner.
if (num_closures > 0) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: %s starting closure: %s", chand,
+ gpr_log(GPR_INFO, "chand=%p calld=%p: %s starting closure: %s", chand,
calld, caller, closures[0].reason);
}
GRPC_CLOSURE_SCHED(closures[0].closure, closures[0].error);
@@ -1805,7 +1804,7 @@ static void execute_closures_in_call_combiner(grpc_call_element* elem,
}
for (size_t i = 1; i < num_closures; ++i) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: %s starting closure in call combiner: %s",
chand, calld, caller, closures[i].reason);
}
@@ -1817,7 +1816,7 @@ static void execute_closures_in_call_combiner(grpc_call_element* elem,
}
} else {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: no closures to run for %s", chand,
+ gpr_log(GPR_INFO, "chand=%p calld=%p: no closures to run for %s", chand,
calld, caller);
}
GRPC_CALL_COMBINER_STOP(calld->call_combiner, "no closures to run");
@@ -1912,7 +1911,7 @@ static void add_closures_for_replay_or_pending_send_ops(
}
if (have_pending_send_message_ops || have_pending_send_trailing_metadata_op) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: starting next batch for pending send op(s)",
chand, calld);
}
@@ -1937,7 +1936,7 @@ static void add_closures_for_completed_pending_batches(
pending_batch* pending = &calld->pending_batches[i];
if (pending_batch_is_completed(pending, calld, retry_state)) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: pending batch completed at index %" PRIuPTR,
chand, calld, i);
}
@@ -1970,7 +1969,7 @@ static void add_closures_to_fail_unstarted_pending_batches(
pending_batch* pending = &calld->pending_batches[i];
if (pending_batch_is_unstarted(pending, calld, retry_state)) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: failing unstarted pending batch at index "
"%" PRIuPTR,
chand, calld, i);
@@ -2014,7 +2013,7 @@ static void on_complete(void* arg, grpc_error* error) {
call_data* calld = static_cast<call_data*>(elem->call_data);
if (grpc_client_channel_trace.enabled()) {
char* batch_str = grpc_transport_stream_op_batch_string(&batch_data->batch);
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: got on_complete, error=%s, batch=%s",
+ gpr_log(GPR_INFO, "chand=%p calld=%p: got on_complete, error=%s, batch=%s",
chand, calld, grpc_error_string(error), batch_str);
gpr_free(batch_str);
}
@@ -2031,7 +2030,7 @@ static void on_complete(void* arg, grpc_error* error) {
update_retry_state_for_completed_batch(batch_data, retry_state);
if (call_finished) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: call already finished", chand,
+ gpr_log(GPR_INFO, "chand=%p calld=%p: call already finished", chand,
calld);
}
} else {
@@ -2059,7 +2058,7 @@ static void on_complete(void* arg, grpc_error* error) {
// If the call just finished, check if we should retry.
if (call_finished) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: call finished, status=%s", chand,
+ gpr_log(GPR_INFO, "chand=%p calld=%p: call finished, status=%s", chand,
calld, grpc_status_code_to_string(status));
}
if (maybe_retry(elem, batch_data, status, server_pushback_md)) {
@@ -2201,7 +2200,7 @@ static void add_retriable_send_initial_metadata_op(
&batch_data->send_initial_metadata_storage[calld->send_initial_metadata
.list.count],
retry_md);
- if (error != GRPC_ERROR_NONE) {
+ if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) {
gpr_log(GPR_ERROR, "error adding retry metadata: %s",
grpc_error_string(error));
GPR_ASSERT(false);
@@ -2224,7 +2223,7 @@ static void add_retriable_send_message_op(
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: starting calld->send_messages[%" PRIuPTR "]",
chand, calld, retry_state->started_send_message_count);
}
@@ -2311,7 +2310,7 @@ static void start_internal_recv_trailing_metadata(grpc_call_element* elem) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: call failed but recv_trailing_metadata not "
"started; starting it internally",
chand, calld);
@@ -2343,7 +2342,7 @@ static subchannel_batch_data* maybe_create_subchannel_batch_for_replay(
!retry_state->started_send_initial_metadata &&
!calld->pending_send_initial_metadata) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: replaying previously completed "
"send_initial_metadata op",
chand, calld);
@@ -2359,7 +2358,7 @@ static subchannel_batch_data* maybe_create_subchannel_batch_for_replay(
retry_state->completed_send_message_count &&
!calld->pending_send_message) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: replaying previously completed "
"send_message op",
chand, calld);
@@ -2378,7 +2377,7 @@ static subchannel_batch_data* maybe_create_subchannel_batch_for_replay(
!retry_state->started_send_trailing_metadata &&
!calld->pending_send_trailing_metadata) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: replaying previously completed "
"send_trailing_metadata op",
chand, calld);
@@ -2518,7 +2517,7 @@ static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: constructing retriable batches",
+ gpr_log(GPR_INFO, "chand=%p calld=%p: constructing retriable batches",
chand, calld);
}
subchannel_call_retry_state* retry_state =
@@ -2541,7 +2540,7 @@ static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored) {
&num_closures);
// Start batches on subchannel call.
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: starting %" PRIuPTR
" retriable batches on subchannel_call=%p",
chand, calld, num_closures, calld->subchannel_call);
@@ -2572,7 +2571,7 @@ static void create_subchannel_call(grpc_call_element* elem, grpc_error* error) {
grpc_error* new_error = calld->pick.connected_subchannel->CreateCall(
call_args, &calld->subchannel_call);
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: create subchannel_call=%p: error=%s",
+ gpr_log(GPR_INFO, "chand=%p calld=%p: create subchannel_call=%p: error=%s",
chand, calld, calld->subchannel_call, grpc_error_string(new_error));
}
if (new_error != GRPC_ERROR_NONE) {
@@ -2613,7 +2612,7 @@ static void pick_done(void* arg, grpc_error* error) {
: GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Failed to create subchannel", &error, 1);
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: failed to create subchannel: error=%s",
chand, calld, grpc_error_string(new_error));
}
@@ -2657,7 +2656,7 @@ static void pick_callback_cancel_locked(void* arg, grpc_error* error) {
// the one we started it on. However, this will just be a no-op.
if (error != GRPC_ERROR_NONE && chand->lb_policy != nullptr) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: cancelling pick from LB policy %p",
+ gpr_log(GPR_INFO, "chand=%p calld=%p: cancelling pick from LB policy %p",
chand, calld, chand->lb_policy.get());
}
chand->lb_policy->CancelPickLocked(&calld->pick, GRPC_ERROR_REF(error));
@@ -2672,8 +2671,8 @@ static void pick_callback_done_locked(void* arg, grpc_error* error) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: pick completed asynchronously",
- chand, calld);
+ gpr_log(GPR_INFO, "chand=%p calld=%p: pick completed asynchronously", chand,
+ calld);
}
async_pick_done_locked(elem, GRPC_ERROR_REF(error));
GRPC_CALL_STACK_UNREF(calld->owning_call, "pick_callback");
@@ -2685,7 +2684,7 @@ static void apply_service_config_to_call_locked(grpc_call_element* elem) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: applying service config to call",
+ gpr_log(GPR_INFO, "chand=%p calld=%p: applying service config to call",
chand, calld);
}
if (chand->retry_throttle_data != nullptr) {
@@ -2723,8 +2722,8 @@ static bool pick_callback_start_locked(grpc_call_element* elem) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: starting pick on lb_policy=%p",
- chand, calld, chand->lb_policy.get());
+ gpr_log(GPR_INFO, "chand=%p calld=%p: starting pick on lb_policy=%p", chand,
+ calld, chand->lb_policy.get());
}
// Only get service config data on the first attempt.
if (calld->num_attempts_completed == 0) {
@@ -2771,7 +2770,7 @@ static bool pick_callback_start_locked(grpc_call_element* elem) {
if (pick_done) {
// Pick completed synchronously.
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: pick completed synchronously",
+ gpr_log(GPR_INFO, "chand=%p calld=%p: pick completed synchronously",
chand, calld);
}
GRPC_CALL_STACK_UNREF(calld->owning_call, "pick_callback");
@@ -2815,7 +2814,7 @@ static void pick_after_resolver_result_cancel_locked(void* arg,
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: cancelling pick waiting for resolver result",
chand, calld);
}
@@ -2835,7 +2834,7 @@ static void pick_after_resolver_result_done_locked(void* arg,
if (args->finished) {
/* cancelled, do nothing */
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "call cancelled before resolver result");
+ gpr_log(GPR_INFO, "call cancelled before resolver result");
}
gpr_free(args);
return;
@@ -2846,14 +2845,14 @@ static void pick_after_resolver_result_done_locked(void* arg,
call_data* calld = static_cast<call_data*>(elem->call_data);
if (error != GRPC_ERROR_NONE) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: resolver failed to return data",
+ gpr_log(GPR_INFO, "chand=%p calld=%p: resolver failed to return data",
chand, calld);
}
async_pick_done_locked(elem, GRPC_ERROR_REF(error));
} else if (chand->resolver == nullptr) {
// Shutting down.
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: resolver disconnected", chand,
+ gpr_log(GPR_INFO, "chand=%p calld=%p: resolver disconnected", chand,
calld);
}
async_pick_done_locked(
@@ -2869,7 +2868,7 @@ static void pick_after_resolver_result_done_locked(void* arg,
.send_initial_metadata_flags;
if (send_initial_metadata_flags & GRPC_INITIAL_METADATA_WAIT_FOR_READY) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: resolver returned but no LB policy; "
"wait_for_ready=true; trying again",
chand, calld);
@@ -2877,7 +2876,7 @@ static void pick_after_resolver_result_done_locked(void* arg,
pick_after_resolver_result_start_locked(elem);
} else {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: resolver returned but no LB policy; "
"wait_for_ready=false; failing",
chand, calld);
@@ -2890,7 +2889,7 @@ static void pick_after_resolver_result_done_locked(void* arg,
}
} else {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: resolver returned, doing pick",
+ gpr_log(GPR_INFO, "chand=%p calld=%p: resolver returned, doing pick",
chand, calld);
}
if (pick_callback_start_locked(elem)) {
@@ -2908,7 +2907,7 @@ static void pick_after_resolver_result_start_locked(grpc_call_element* elem) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: deferring pick pending resolver result", chand,
calld);
}
@@ -2975,7 +2974,7 @@ static void cc_start_transport_stream_op_batch(
// If we've previously been cancelled, immediately fail any new batches.
if (calld->cancel_error != GRPC_ERROR_NONE) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: failing batch with error: %s",
+ gpr_log(GPR_INFO, "chand=%p calld=%p: failing batch with error: %s",
chand, calld, grpc_error_string(calld->cancel_error));
}
// Note: This will release the call combiner.
@@ -2994,7 +2993,7 @@ static void cc_start_transport_stream_op_batch(
calld->cancel_error =
GRPC_ERROR_REF(batch->payload->cancel_stream.cancel_error);
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: recording cancel_error=%s", chand,
+ gpr_log(GPR_INFO, "chand=%p calld=%p: recording cancel_error=%s", chand,
calld, grpc_error_string(calld->cancel_error));
}
// If we do not have a subchannel call (i.e., a pick has not yet
@@ -3020,7 +3019,7 @@ static void cc_start_transport_stream_op_batch(
// streaming calls).
if (calld->subchannel_call != nullptr) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: starting batch on subchannel_call=%p", chand,
calld, calld->subchannel_call);
}
@@ -3032,7 +3031,7 @@ static void cc_start_transport_stream_op_batch(
// combiner to start a pick.
if (batch->send_initial_metadata) {
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG, "chand=%p calld=%p: entering client_channel combiner",
+ gpr_log(GPR_INFO, "chand=%p calld=%p: entering client_channel combiner",
chand, calld);
}
GRPC_CLOSURE_SCHED(
@@ -3042,7 +3041,7 @@ static void cc_start_transport_stream_op_batch(
} else {
// For all other batches, release the call combiner.
if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"chand=%p calld=%p: saved batch, yeilding call combiner", chand,
calld);
}
@@ -3243,7 +3242,7 @@ static void on_external_watch_complete_locked(void* arg, grpc_error* error) {
"external_connectivity_watcher");
external_connectivity_watcher_list_remove(w->chand, w);
gpr_free(w);
- GRPC_CLOSURE_RUN(follow_up, GRPC_ERROR_REF(error));
+ GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error));
}
static void watch_connectivity_state_locked(void* arg,
@@ -3253,6 +3252,8 @@ static void watch_connectivity_state_locked(void* arg,
external_connectivity_watcher* found = nullptr;
if (w->state != nullptr) {
external_connectivity_watcher_list_append(w->chand, w);
+ // An assumption is being made that the closure is scheduled on the exec ctx
+ // scheduler and that GRPC_CLOSURE_RUN would run the closure immediately.
GRPC_CLOSURE_RUN(w->watcher_timer_init, GRPC_ERROR_NONE);
GRPC_CLOSURE_INIT(&w->my_closure, on_external_watch_complete_locked, w,
grpc_combiner_scheduler(w->chand->combiner));
diff --git a/src/core/ext/filters/client_channel/lb_policy.cc b/src/core/ext/filters/client_channel/lb_policy.cc
index fa63dd75b5..e065f45639 100644
--- a/src/core/ext/filters/client_channel/lb_policy.cc
+++ b/src/core/ext/filters/client_channel/lb_policy.cc
@@ -44,13 +44,13 @@ void LoadBalancingPolicy::TryReresolutionLocked(
GRPC_CLOSURE_SCHED(request_reresolution_, error);
request_reresolution_ = nullptr;
if (grpc_lb_trace->enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"%s %p: scheduling re-resolution closure with error=%s.",
grpc_lb_trace->name(), this, grpc_error_string(error));
}
} else {
if (grpc_lb_trace->enabled()) {
- gpr_log(GPR_DEBUG, "%s %p: no available re-resolution closure.",
+ gpr_log(GPR_INFO, "%s %p: no available re-resolution closure.",
grpc_lb_trace->name(), this);
}
}
diff --git a/src/core/ext/filters/client_channel/lb_policy.h b/src/core/ext/filters/client_channel/lb_policy.h
index c3e43e5ef6..dab4466b21 100644
--- a/src/core/ext/filters/client_channel/lb_policy.h
+++ b/src/core/ext/filters/client_channel/lb_policy.h
@@ -162,6 +162,8 @@ class LoadBalancingPolicy
GRPC_ABSTRACT_BASE_CLASS
protected:
+ GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
+
explicit LoadBalancingPolicy(const Args& args);
virtual ~LoadBalancingPolicy();
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc
index 18ef1f6ff5..cc259bcdbf 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc
@@ -35,9 +35,10 @@ static grpc_error* init_channel_elem(grpc_channel_element* elem,
static void destroy_channel_elem(grpc_channel_element* elem) {}
namespace {
+
struct call_data {
// Stats object to update.
- grpc_grpclb_client_stats* client_stats;
+ grpc_core::RefCountedPtr<grpc_core::GrpcLbClientStats> client_stats;
// State for intercepting send_initial_metadata.
grpc_closure on_complete_for_send;
grpc_closure* original_on_complete_for_send;
@@ -47,6 +48,7 @@ struct call_data {
grpc_closure* original_recv_initial_metadata_ready;
bool recv_initial_metadata_succeeded;
};
+
} // namespace
static void on_complete_for_send(void* arg, grpc_error* error) {
@@ -72,11 +74,11 @@ static grpc_error* init_call_elem(grpc_call_element* elem,
// Get stats object from context and take a ref.
GPR_ASSERT(args->context != nullptr);
if (args->context[GRPC_GRPCLB_CLIENT_STATS].value != nullptr) {
- calld->client_stats =
- grpc_grpclb_client_stats_ref(static_cast<grpc_grpclb_client_stats*>(
- args->context[GRPC_GRPCLB_CLIENT_STATS].value));
+ calld->client_stats = static_cast<grpc_core::GrpcLbClientStats*>(
+ args->context[GRPC_GRPCLB_CLIENT_STATS].value)
+ ->Ref();
// Record call started.
- grpc_grpclb_client_stats_add_call_started(calld->client_stats);
+ calld->client_stats->AddCallStarted();
}
return GRPC_ERROR_NONE;
}
@@ -88,12 +90,12 @@ static void destroy_call_elem(grpc_call_element* elem,
if (calld->client_stats != nullptr) {
// Record call finished, optionally setting client_failed_to_send and
// received.
- grpc_grpclb_client_stats_add_call_finished(
+ calld->client_stats->AddCallFinished(
!calld->send_initial_metadata_succeeded /* client_failed_to_send */,
- calld->recv_initial_metadata_succeeded /* known_received */,
- calld->client_stats);
+ calld->recv_initial_metadata_succeeded /* known_received */);
// All done, so unref the stats object.
- grpc_grpclb_client_stats_unref(calld->client_stats);
+ // TODO(roth): Eliminate this once filter stack is converted to C++.
+ calld->client_stats.reset();
}
}
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
index 0b2a30818e..0d57fa2d02 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
@@ -76,6 +76,7 @@
#include "src/core/ext/filters/client_channel/client_channel.h"
#include "src/core/ext/filters/client_channel/client_channel_factory.h"
#include "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h"
+#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h"
#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h"
#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h"
#include "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h"
@@ -158,9 +159,8 @@ class GrpcLb : public LoadBalancingPolicy {
// The LB token associated with the pick. This is set via user_data in
// the pick.
grpc_mdelem lb_token;
- // Stats for client-side load reporting. Note that this holds a
- // reference, which must be either passed on via context or unreffed.
- grpc_grpclb_client_stats* client_stats = nullptr;
+ // Stats for client-side load reporting.
+ RefCountedPtr<GrpcLbClientStats> client_stats;
// Next pending pick.
PendingPick* next = nullptr;
};
@@ -185,10 +185,15 @@ class GrpcLb : public LoadBalancingPolicy {
void StartQuery();
- grpc_grpclb_client_stats* client_stats() const { return client_stats_; }
+ GrpcLbClientStats* client_stats() const { return client_stats_.get(); }
+
bool seen_initial_response() const { return seen_initial_response_; }
private:
+ // So Delete() can access our private dtor.
+ template <typename T>
+ friend void grpc_core::Delete(T*);
+
~BalancerCallState();
GrpcLb* grpclb_policy() const {
@@ -232,7 +237,7 @@ class GrpcLb : public LoadBalancingPolicy {
// The stats for client-side load reporting associated with this LB call.
// Created after the first serverlist is received.
- grpc_grpclb_client_stats* client_stats_ = nullptr;
+ RefCountedPtr<GrpcLbClientStats> client_stats_;
grpc_millis client_stats_report_interval_ = 0;
grpc_timer client_load_report_timer_;
bool client_load_report_timer_callback_pending_ = false;
@@ -394,7 +399,7 @@ grpc_lb_addresses* ExtractBackendAddresses(const grpc_lb_addresses* addresses) {
bool IsServerValid(const grpc_grpclb_server* server, size_t idx, bool log) {
if (server->drop) return false;
const grpc_grpclb_ip_address* ip = &server->ip_address;
- if (server->port >> 16 != 0) {
+ if (GPR_UNLIKELY(server->port >> 16 != 0)) {
if (log) {
gpr_log(GPR_ERROR,
"Invalid port '%d' at index %lu of serverlist. Ignoring.",
@@ -402,7 +407,7 @@ bool IsServerValid(const grpc_grpclb_server* server, size_t idx, bool log) {
}
return false;
}
- if (ip->size != 4 && ip->size != 16) {
+ if (GPR_UNLIKELY(ip->size != 4 && ip->size != 16)) {
if (log) {
gpr_log(GPR_ERROR,
"Expected IP to be 4 or 16 bytes, got %d at index %lu of "
@@ -543,9 +548,6 @@ GrpcLb::BalancerCallState::~BalancerCallState() {
grpc_byte_buffer_destroy(send_message_payload_);
grpc_byte_buffer_destroy(recv_message_payload_);
grpc_slice_unref_internal(lb_call_status_details_);
- if (client_stats_ != nullptr) {
- grpc_grpclb_client_stats_unref(client_stats_);
- }
}
void GrpcLb::BalancerCallState::Orphan() {
@@ -668,22 +670,22 @@ void GrpcLb::BalancerCallState::MaybeSendClientLoadReportLocked(
bool GrpcLb::BalancerCallState::LoadReportCountersAreZero(
grpc_grpclb_request* request) {
- grpc_grpclb_dropped_call_counts* drop_entries =
- static_cast<grpc_grpclb_dropped_call_counts*>(
+ GrpcLbClientStats::DroppedCallCounts* drop_entries =
+ static_cast<GrpcLbClientStats::DroppedCallCounts*>(
request->client_stats.calls_finished_with_drop.arg);
return request->client_stats.num_calls_started == 0 &&
request->client_stats.num_calls_finished == 0 &&
request->client_stats.num_calls_finished_with_client_failed_to_send ==
0 &&
request->client_stats.num_calls_finished_known_received == 0 &&
- (drop_entries == nullptr || drop_entries->num_entries == 0);
+ (drop_entries == nullptr || drop_entries->size() == 0);
}
void GrpcLb::BalancerCallState::SendClientLoadReportLocked() {
// Construct message payload.
GPR_ASSERT(send_message_payload_ == nullptr);
grpc_grpclb_request* request =
- grpc_grpclb_load_report_request_create_locked(client_stats_);
+ grpc_grpclb_load_report_request_create_locked(client_stats_.get());
// Skip client load report if the counters were all zero in the last
// report and they are still zero in this one.
if (LoadReportCountersAreZero(request)) {
@@ -710,7 +712,7 @@ void GrpcLb::BalancerCallState::SendClientLoadReportLocked() {
this, grpc_combiner_scheduler(grpclb_policy()->combiner()));
grpc_call_error call_error = grpc_call_start_batch_and_execute(
lb_call_, &op, 1, &client_load_report_closure_);
- if (call_error != GRPC_CALL_OK) {
+ if (GPR_UNLIKELY(call_error != GRPC_CALL_OK)) {
gpr_log(GPR_ERROR, "[grpclb %p] call_error=%d", grpclb_policy_.get(),
call_error);
GPR_ASSERT(GRPC_CALL_OK == call_error);
@@ -809,7 +811,7 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked(
// serverlist returned from the current LB call.
if (lb_calld->client_stats_report_interval_ > 0 &&
lb_calld->client_stats_ == nullptr) {
- lb_calld->client_stats_ = grpc_grpclb_client_stats_create();
+ lb_calld->client_stats_.reset(New<GrpcLbClientStats>());
// TODO(roth): We currently track this ref manually. Once the
// ClosureRef API is ready, we should pass the RefCountedPtr<> along
// with the callback.
@@ -932,7 +934,7 @@ grpc_lb_addresses* ExtractBalancerAddresses(
size_t lb_addresses_idx = 0;
for (size_t i = 0; i < addresses->num_addresses; ++i) {
if (!addresses->addresses[i].is_balancer) continue;
- if (addresses->addresses[i].user_data != nullptr) {
+ if (GPR_UNLIKELY(addresses->addresses[i].user_data != nullptr)) {
gpr_log(GPR_ERROR,
"This LB policy doesn't support user data. It will be ignored");
}
@@ -999,6 +1001,9 @@ grpc_channel_args* BuildBalancerChannelArgs(
// address updates into the LB channel.
grpc_core::FakeResolverResponseGenerator::MakeChannelArg(
response_generator),
+ // A channel arg indicating the target is a grpclb load balancer.
+ grpc_channel_arg_integer_create(
+ const_cast<char*>(GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER), 1),
};
// Construct channel args.
grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove(
@@ -1243,7 +1248,7 @@ bool GrpcLb::PickLocked(PickState* pick) {
}
} else { // rr_policy_ == NULL
if (grpc_lb_glb_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"[grpclb %p] No RR policy. Adding to grpclb's pending picks",
this);
}
@@ -1280,7 +1285,7 @@ void GrpcLb::NotifyOnStateChangeLocked(grpc_connectivity_state* current,
void GrpcLb::ProcessChannelArgsLocked(const grpc_channel_args& args) {
const grpc_arg* arg = grpc_channel_args_find(&args, GRPC_ARG_LB_ADDRESSES);
- if (arg == nullptr || arg->type != GRPC_ARG_POINTER) {
+ if (GPR_UNLIKELY(arg == nullptr || arg->type != GRPC_ARG_POINTER)) {
// Ignore this update.
gpr_log(
GPR_ERROR,
@@ -1409,14 +1414,13 @@ void GrpcLb::OnFallbackTimerLocked(void* arg, grpc_error* error) {
void GrpcLb::StartBalancerCallRetryTimerLocked() {
grpc_millis next_try = lb_call_backoff_.NextAttemptTime();
if (grpc_lb_glb_trace.enabled()) {
- gpr_log(GPR_DEBUG, "[grpclb %p] Connection to LB server lost...", this);
+ gpr_log(GPR_INFO, "[grpclb %p] Connection to LB server lost...", this);
grpc_millis timeout = next_try - ExecCtx::Get()->Now();
if (timeout > 0) {
- gpr_log(GPR_DEBUG,
- "[grpclb %p] ... retry_timer_active in %" PRIuPTR "ms.", this,
- timeout);
+ gpr_log(GPR_INFO, "[grpclb %p] ... retry_timer_active in %" PRIuPTR "ms.",
+ this, timeout);
} else {
- gpr_log(GPR_DEBUG, "[grpclb %p] ... retry_timer_active immediately.",
+ gpr_log(GPR_INFO, "[grpclb %p] ... retry_timer_active immediately.",
this);
}
}
@@ -1509,7 +1513,7 @@ grpc_error* AddLbTokenToInitialMetadata(
// Destroy function used when embedding client stats in call context.
void DestroyClientStats(void* arg) {
- grpc_grpclb_client_stats_unref(static_cast<grpc_grpclb_client_stats*>(arg));
+ static_cast<GrpcLbClientStats*>(arg)->Unref();
}
void GrpcLb::PendingPickSetMetadataAndContext(PendingPick* pp) {
@@ -1517,7 +1521,7 @@ void GrpcLb::PendingPickSetMetadataAndContext(PendingPick* pp) {
* policy (e.g., all addresses failed to connect). There won't be any
* user_data/token available */
if (pp->pick->connected_subchannel != nullptr) {
- if (!GRPC_MDISNULL(pp->lb_token)) {
+ if (GPR_LIKELY(!GRPC_MDISNULL(pp->lb_token))) {
AddLbTokenToInitialMetadata(GRPC_MDELEM_REF(pp->lb_token),
&pp->pick->lb_token_mdelem_storage,
pp->pick->initial_metadata);
@@ -1530,14 +1534,12 @@ void GrpcLb::PendingPickSetMetadataAndContext(PendingPick* pp) {
// Pass on client stats via context. Passes ownership of the reference.
if (pp->client_stats != nullptr) {
pp->pick->subchannel_call_context[GRPC_GRPCLB_CLIENT_STATS].value =
- pp->client_stats;
+ pp->client_stats.release();
pp->pick->subchannel_call_context[GRPC_GRPCLB_CLIENT_STATS].destroy =
DestroyClientStats;
}
} else {
- if (pp->client_stats != nullptr) {
- grpc_grpclb_client_stats_unref(pp->client_stats);
- }
+ pp->client_stats.reset();
}
}
@@ -1603,8 +1605,8 @@ bool GrpcLb::PickFromRoundRobinPolicyLocked(bool force_async, PendingPick* pp) {
// subchannel call (and therefore no client_load_reporting filter)
// for dropped calls.
if (lb_calld_ != nullptr && lb_calld_->client_stats() != nullptr) {
- grpc_grpclb_client_stats_add_call_dropped_locked(
- server->load_balance_token, lb_calld_->client_stats());
+ lb_calld_->client_stats()->AddCallDroppedLocked(
+ server->load_balance_token);
}
if (force_async) {
GRPC_CLOSURE_SCHED(pp->original_on_complete, GRPC_ERROR_NONE);
@@ -1617,7 +1619,7 @@ bool GrpcLb::PickFromRoundRobinPolicyLocked(bool force_async, PendingPick* pp) {
}
// Set client_stats and user_data.
if (lb_calld_ != nullptr && lb_calld_->client_stats() != nullptr) {
- pp->client_stats = grpc_grpclb_client_stats_ref(lb_calld_->client_stats());
+ pp->client_stats = lb_calld_->client_stats()->Ref();
}
GPR_ASSERT(pp->pick->user_data == nullptr);
pp->pick->user_data = (void**)&pp->lb_token;
@@ -1642,7 +1644,7 @@ void GrpcLb::CreateRoundRobinPolicyLocked(const Args& args) {
GPR_ASSERT(rr_policy_ == nullptr);
rr_policy_ = LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(
"round_robin", args);
- if (rr_policy_ == nullptr) {
+ if (GPR_UNLIKELY(rr_policy_ == nullptr)) {
gpr_log(GPR_ERROR, "[grpclb %p] Failure creating a RoundRobin policy",
this);
return;
@@ -1695,9 +1697,11 @@ void GrpcLb::CreateRoundRobinPolicyLocked(const Args& args) {
grpc_channel_args* GrpcLb::CreateRoundRobinPolicyArgsLocked() {
grpc_lb_addresses* addresses;
+ bool is_backend_from_grpclb_load_balancer = false;
if (serverlist_ != nullptr) {
GPR_ASSERT(serverlist_->num_servers > 0);
addresses = ProcessServerlist(serverlist_);
+ is_backend_from_grpclb_load_balancer = true;
} else {
// If CreateOrUpdateRoundRobinPolicyLocked() is invoked when we haven't
// received any serverlist from the balancer, we use the fallback backends
@@ -1711,9 +1715,18 @@ grpc_channel_args* GrpcLb::CreateRoundRobinPolicyArgsLocked() {
// Replace the LB addresses in the channel args that we pass down to
// the subchannel.
static const char* keys_to_remove[] = {GRPC_ARG_LB_ADDRESSES};
- const grpc_arg arg = grpc_lb_addresses_create_channel_arg(addresses);
+ const grpc_arg args_to_add[] = {
+ grpc_lb_addresses_create_channel_arg(addresses),
+ // A channel arg indicating if the target is a backend inferred from a
+ // grpclb load balancer.
+ grpc_channel_arg_integer_create(
+ const_cast<char*>(
+ GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER),
+ is_backend_from_grpclb_load_balancer),
+ };
grpc_channel_args* args = grpc_channel_args_copy_and_add_and_remove(
- args_, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &arg, 1);
+ args_, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), args_to_add,
+ GPR_ARRAY_SIZE(args_to_add));
grpc_lb_addresses_destroy(addresses);
return args;
}
@@ -1724,7 +1737,7 @@ void GrpcLb::CreateOrUpdateRoundRobinPolicyLocked() {
GPR_ASSERT(args != nullptr);
if (rr_policy_ != nullptr) {
if (grpc_lb_glb_trace.enabled()) {
- gpr_log(GPR_DEBUG, "[grpclb %p] Updating RR policy %p", this,
+ gpr_log(GPR_INFO, "[grpclb %p] Updating RR policy %p", this,
rr_policy_.get());
}
rr_policy_->UpdateLocked(*args);
@@ -1735,7 +1748,7 @@ void GrpcLb::CreateOrUpdateRoundRobinPolicyLocked() {
lb_policy_args.args = args;
CreateRoundRobinPolicyLocked(lb_policy_args);
if (grpc_lb_glb_trace.enabled()) {
- gpr_log(GPR_DEBUG, "[grpclb %p] Created new RR policy %p", this,
+ gpr_log(GPR_INFO, "[grpclb %p] Created new RR policy %p", this,
rr_policy_.get());
}
}
@@ -1751,7 +1764,7 @@ void GrpcLb::OnRoundRobinRequestReresolutionLocked(void* arg,
}
if (grpc_lb_glb_trace.enabled()) {
gpr_log(
- GPR_DEBUG,
+ GPR_INFO,
"[grpclb %p] Re-resolution requested from the internal RR policy (%p).",
grpclb_policy, grpclb_policy->rr_policy_.get());
}
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h
new file mode 100644
index 0000000000..4d39c4d504
--- /dev/null
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h
@@ -0,0 +1,36 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_H
+#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_H
+
+#include <grpc/support/port_platform.h>
+
+/** Channel arg indicating if a target corresponding to the address is grpclb
+ * loadbalancer. The type of this arg is an integer and the value is treated as
+ * a bool. */
+#define GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER \
+ "grpc.address_is_grpclb_load_balancer"
+/** Channel arg indicating if a target corresponding to the address is a backend
+ * received from a balancer. The type of this arg is an integer and the value is
+ * treated as a bool. */
+#define GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER \
+ "grpc.address_is_backend_from_grpclb_load_balancer"
+
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_H \
+ */
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc
index dfbaead7d5..087cd8f276 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc
@@ -22,131 +22,65 @@
#include <string.h>
-#include <grpc/support/alloc.h>
#include <grpc/support/atm.h>
#include <grpc/support/string_util.h>
-#include <grpc/support/sync.h>
-#include "src/core/lib/channel/channel_args.h"
+namespace grpc_core {
-#define GRPC_ARG_GRPCLB_CLIENT_STATS "grpc.grpclb_client_stats"
-
-struct grpc_grpclb_client_stats {
- gpr_refcount refs;
- // This field must only be accessed via *_locked() methods.
- grpc_grpclb_dropped_call_counts* drop_token_counts;
- // These fields may be accessed from multiple threads at a time.
- gpr_atm num_calls_started;
- gpr_atm num_calls_finished;
- gpr_atm num_calls_finished_with_client_failed_to_send;
- gpr_atm num_calls_finished_known_received;
-};
-
-grpc_grpclb_client_stats* grpc_grpclb_client_stats_create() {
- grpc_grpclb_client_stats* client_stats =
- static_cast<grpc_grpclb_client_stats*>(gpr_zalloc(sizeof(*client_stats)));
- gpr_ref_init(&client_stats->refs, 1);
- return client_stats;
-}
-
-grpc_grpclb_client_stats* grpc_grpclb_client_stats_ref(
- grpc_grpclb_client_stats* client_stats) {
- gpr_ref(&client_stats->refs);
- return client_stats;
-}
-
-void grpc_grpclb_client_stats_unref(grpc_grpclb_client_stats* client_stats) {
- if (gpr_unref(&client_stats->refs)) {
- grpc_grpclb_dropped_call_counts_destroy(client_stats->drop_token_counts);
- gpr_free(client_stats);
- }
-}
-
-void grpc_grpclb_client_stats_add_call_started(
- grpc_grpclb_client_stats* client_stats) {
- gpr_atm_full_fetch_add(&client_stats->num_calls_started, (gpr_atm)1);
+void GrpcLbClientStats::AddCallStarted() {
+ gpr_atm_full_fetch_add(&num_calls_started_, (gpr_atm)1);
}
-void grpc_grpclb_client_stats_add_call_finished(
- bool finished_with_client_failed_to_send, bool finished_known_received,
- grpc_grpclb_client_stats* client_stats) {
- gpr_atm_full_fetch_add(&client_stats->num_calls_finished, (gpr_atm)1);
+void GrpcLbClientStats::AddCallFinished(
+ bool finished_with_client_failed_to_send, bool finished_known_received) {
+ gpr_atm_full_fetch_add(&num_calls_finished_, (gpr_atm)1);
if (finished_with_client_failed_to_send) {
- gpr_atm_full_fetch_add(
- &client_stats->num_calls_finished_with_client_failed_to_send,
- (gpr_atm)1);
+ gpr_atm_full_fetch_add(&num_calls_finished_with_client_failed_to_send_,
+ (gpr_atm)1);
}
if (finished_known_received) {
- gpr_atm_full_fetch_add(&client_stats->num_calls_finished_known_received,
- (gpr_atm)1);
+ gpr_atm_full_fetch_add(&num_calls_finished_known_received_, (gpr_atm)1);
}
}
-void grpc_grpclb_client_stats_add_call_dropped_locked(
- char* token, grpc_grpclb_client_stats* client_stats) {
+void GrpcLbClientStats::AddCallDroppedLocked(char* token) {
// Increment num_calls_started and num_calls_finished.
- gpr_atm_full_fetch_add(&client_stats->num_calls_started, (gpr_atm)1);
- gpr_atm_full_fetch_add(&client_stats->num_calls_finished, (gpr_atm)1);
+ gpr_atm_full_fetch_add(&num_calls_started_, (gpr_atm)1);
+ gpr_atm_full_fetch_add(&num_calls_finished_, (gpr_atm)1);
// Record the drop.
- if (client_stats->drop_token_counts == nullptr) {
- client_stats->drop_token_counts =
- static_cast<grpc_grpclb_dropped_call_counts*>(
- gpr_zalloc(sizeof(grpc_grpclb_dropped_call_counts)));
+ if (drop_token_counts_ == nullptr) {
+ drop_token_counts_.reset(New<DroppedCallCounts>());
}
- grpc_grpclb_dropped_call_counts* drop_token_counts =
- client_stats->drop_token_counts;
- for (size_t i = 0; i < drop_token_counts->num_entries; ++i) {
- if (strcmp(drop_token_counts->token_counts[i].token, token) == 0) {
- ++drop_token_counts->token_counts[i].count;
+ for (size_t i = 0; i < drop_token_counts_->size(); ++i) {
+ if (strcmp((*drop_token_counts_)[i].token.get(), token) == 0) {
+ ++(*drop_token_counts_)[i].count;
return;
}
}
- // Not found, so add a new entry. We double the size of the array each time.
- size_t new_num_entries = 2;
- while (new_num_entries < drop_token_counts->num_entries + 1) {
- new_num_entries *= 2;
- }
- drop_token_counts->token_counts = static_cast<grpc_grpclb_drop_token_count*>(
- gpr_realloc(drop_token_counts->token_counts,
- new_num_entries * sizeof(grpc_grpclb_drop_token_count)));
- grpc_grpclb_drop_token_count* new_entry =
- &drop_token_counts->token_counts[drop_token_counts->num_entries++];
- new_entry->token = gpr_strdup(token);
- new_entry->count = 1;
+ // Not found, so add a new entry.
+ drop_token_counts_->emplace_back(UniquePtr<char>(gpr_strdup(token)), 1);
}
-static void atomic_get_and_reset_counter(int64_t* value, gpr_atm* counter) {
- *value = static_cast<int64_t>(gpr_atm_acq_load(counter));
- gpr_atm_full_fetch_add(counter, (gpr_atm)(-*value));
+namespace {
+
+void AtomicGetAndResetCounter(int64_t* value, gpr_atm* counter) {
+ *value = static_cast<int64_t>(gpr_atm_full_xchg(counter, (gpr_atm)0));
}
-void grpc_grpclb_client_stats_get_locked(
- grpc_grpclb_client_stats* client_stats, int64_t* num_calls_started,
- int64_t* num_calls_finished,
+} // namespace
+
+void GrpcLbClientStats::GetLocked(
+ int64_t* num_calls_started, int64_t* num_calls_finished,
int64_t* num_calls_finished_with_client_failed_to_send,
int64_t* num_calls_finished_known_received,
- grpc_grpclb_dropped_call_counts** drop_token_counts) {
- atomic_get_and_reset_counter(num_calls_started,
- &client_stats->num_calls_started);
- atomic_get_and_reset_counter(num_calls_finished,
- &client_stats->num_calls_finished);
- atomic_get_and_reset_counter(
- num_calls_finished_with_client_failed_to_send,
- &client_stats->num_calls_finished_with_client_failed_to_send);
- atomic_get_and_reset_counter(
- num_calls_finished_known_received,
- &client_stats->num_calls_finished_known_received);
- *drop_token_counts = client_stats->drop_token_counts;
- client_stats->drop_token_counts = nullptr;
+ UniquePtr<DroppedCallCounts>* drop_token_counts) {
+ AtomicGetAndResetCounter(num_calls_started, &num_calls_started_);
+ AtomicGetAndResetCounter(num_calls_finished, &num_calls_finished_);
+ AtomicGetAndResetCounter(num_calls_finished_with_client_failed_to_send,
+ &num_calls_finished_with_client_failed_to_send_);
+ AtomicGetAndResetCounter(num_calls_finished_known_received,
+ &num_calls_finished_known_received_);
+ *drop_token_counts = std::move(drop_token_counts_);
}
-void grpc_grpclb_dropped_call_counts_destroy(
- grpc_grpclb_dropped_call_counts* drop_entries) {
- if (drop_entries != nullptr) {
- for (size_t i = 0; i < drop_entries->num_entries; ++i) {
- gpr_free(drop_entries->token_counts[i].token);
- }
- gpr_free(drop_entries->token_counts);
- gpr_free(drop_entries);
- }
-}
+} // namespace grpc_core
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h
index c971e56883..18ab2c9452 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h
@@ -21,47 +21,52 @@
#include <grpc/support/port_platform.h>
-#include <stdbool.h>
+#include <grpc/support/atm.h>
-#include <grpc/impl/codegen/grpc_types.h>
+#include "src/core/lib/gprpp/inlined_vector.h"
+#include "src/core/lib/gprpp/memory.h"
+#include "src/core/lib/gprpp/ref_counted.h"
-typedef struct grpc_grpclb_client_stats grpc_grpclb_client_stats;
+namespace grpc_core {
-typedef struct {
- char* token;
- int64_t count;
-} grpc_grpclb_drop_token_count;
+class GrpcLbClientStats : public RefCounted<GrpcLbClientStats> {
+ public:
+ struct DropTokenCount {
+ UniquePtr<char> token;
+ int64_t count;
-typedef struct {
- grpc_grpclb_drop_token_count* token_counts;
- size_t num_entries;
-} grpc_grpclb_dropped_call_counts;
+ DropTokenCount(UniquePtr<char> token, int64_t count)
+ : token(std::move(token)), count(count) {}
+ };
-grpc_grpclb_client_stats* grpc_grpclb_client_stats_create();
-grpc_grpclb_client_stats* grpc_grpclb_client_stats_ref(
- grpc_grpclb_client_stats* client_stats);
-void grpc_grpclb_client_stats_unref(grpc_grpclb_client_stats* client_stats);
+ typedef InlinedVector<DropTokenCount, 10> DroppedCallCounts;
-void grpc_grpclb_client_stats_add_call_started(
- grpc_grpclb_client_stats* client_stats);
-void grpc_grpclb_client_stats_add_call_finished(
- bool finished_with_client_failed_to_send, bool finished_known_received,
- grpc_grpclb_client_stats* client_stats);
+ GrpcLbClientStats() {}
-// This method is not thread-safe; caller must synchronize.
-void grpc_grpclb_client_stats_add_call_dropped_locked(
- char* token, grpc_grpclb_client_stats* client_stats);
+ void AddCallStarted();
+ void AddCallFinished(bool finished_with_client_failed_to_send,
+ bool finished_known_received);
-// This method is not thread-safe; caller must synchronize.
-void grpc_grpclb_client_stats_get_locked(
- grpc_grpclb_client_stats* client_stats, int64_t* num_calls_started,
- int64_t* num_calls_finished,
- int64_t* num_calls_finished_with_client_failed_to_send,
- int64_t* num_calls_finished_known_received,
- grpc_grpclb_dropped_call_counts** drop_token_counts);
+ // This method is not thread-safe; caller must synchronize.
+ void AddCallDroppedLocked(char* token);
-void grpc_grpclb_dropped_call_counts_destroy(
- grpc_grpclb_dropped_call_counts* drop_entries);
+ // This method is not thread-safe; caller must synchronize.
+ void GetLocked(int64_t* num_calls_started, int64_t* num_calls_finished,
+ int64_t* num_calls_finished_with_client_failed_to_send,
+ int64_t* num_calls_finished_known_received,
+ UniquePtr<DroppedCallCounts>* drop_token_counts);
+
+ private:
+ // This field must only be accessed via *_locked() methods.
+ UniquePtr<DroppedCallCounts> drop_token_counts_;
+ // These fields may be accessed from multiple threads at a time.
+ gpr_atm num_calls_started_ = 0;
+ gpr_atm num_calls_finished_ = 0;
+ gpr_atm num_calls_finished_with_client_failed_to_send_ = 0;
+ gpr_atm num_calls_finished_known_received_ = 0;
+};
+
+} // namespace grpc_core
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_CLIENT_STATS_H \
*/
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc
index 7ef3bcf24f..ed246273c9 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc
@@ -29,7 +29,7 @@ static bool count_serverlist(pb_istream_t* stream, const pb_field_t* field,
void** arg) {
grpc_grpclb_serverlist* sl = static_cast<grpc_grpclb_serverlist*>(*arg);
grpc_grpclb_server server;
- if (!pb_decode(stream, grpc_lb_v1_Server_fields, &server)) {
+ if (GPR_UNLIKELY(!pb_decode(stream, grpc_lb_v1_Server_fields, &server))) {
gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(stream));
return false;
}
@@ -52,7 +52,7 @@ static bool decode_serverlist(pb_istream_t* stream, const pb_field_t* field,
GPR_ASSERT(dec_arg->serverlist->num_servers >= dec_arg->decoding_idx);
grpc_grpclb_server* server =
static_cast<grpc_grpclb_server*>(gpr_zalloc(sizeof(grpc_grpclb_server)));
- if (!pb_decode(stream, grpc_lb_v1_Server_fields, server)) {
+ if (GPR_UNLIKELY(!pb_decode(stream, grpc_lb_v1_Server_fields, server))) {
gpr_free(server);
gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(stream));
return false;
@@ -89,16 +89,16 @@ static bool encode_string(pb_ostream_t* stream, const pb_field_t* field,
static bool encode_drops(pb_ostream_t* stream, const pb_field_t* field,
void* const* arg) {
- grpc_grpclb_dropped_call_counts* drop_entries =
- static_cast<grpc_grpclb_dropped_call_counts*>(*arg);
+ grpc_core::GrpcLbClientStats::DroppedCallCounts* drop_entries =
+ static_cast<grpc_core::GrpcLbClientStats::DroppedCallCounts*>(*arg);
if (drop_entries == nullptr) return true;
- for (size_t i = 0; i < drop_entries->num_entries; ++i) {
+ for (size_t i = 0; i < drop_entries->size(); ++i) {
if (!pb_encode_tag_for_field(stream, field)) return false;
grpc_lb_v1_ClientStatsPerToken drop_message;
drop_message.load_balance_token.funcs.encode = encode_string;
- drop_message.load_balance_token.arg = drop_entries->token_counts[i].token;
+ drop_message.load_balance_token.arg = (*drop_entries)[i].token.get();
drop_message.has_num_calls = true;
- drop_message.num_calls = drop_entries->token_counts[i].count;
+ drop_message.num_calls = (*drop_entries)[i].count;
if (!pb_encode_submessage(stream, grpc_lb_v1_ClientStatsPerToken_fields,
&drop_message)) {
return false;
@@ -108,7 +108,7 @@ static bool encode_drops(pb_ostream_t* stream, const pb_field_t* field,
}
grpc_grpclb_request* grpc_grpclb_load_report_request_create_locked(
- grpc_grpclb_client_stats* client_stats) {
+ grpc_core::GrpcLbClientStats* client_stats) {
grpc_grpclb_request* req = static_cast<grpc_grpclb_request*>(
gpr_zalloc(sizeof(grpc_grpclb_request)));
req->has_client_stats = true;
@@ -120,13 +120,15 @@ grpc_grpclb_request* grpc_grpclb_load_report_request_create_locked(
req->client_stats.has_num_calls_finished_with_client_failed_to_send = true;
req->client_stats.has_num_calls_finished_known_received = true;
req->client_stats.calls_finished_with_drop.funcs.encode = encode_drops;
- grpc_grpclb_client_stats_get_locked(
- client_stats, &req->client_stats.num_calls_started,
+ grpc_core::UniquePtr<grpc_core::GrpcLbClientStats::DroppedCallCounts>
+ drop_counts;
+ client_stats->GetLocked(
+ &req->client_stats.num_calls_started,
&req->client_stats.num_calls_finished,
&req->client_stats.num_calls_finished_with_client_failed_to_send,
- &req->client_stats.num_calls_finished_known_received,
- reinterpret_cast<grpc_grpclb_dropped_call_counts**>(
- &req->client_stats.calls_finished_with_drop.arg));
+ &req->client_stats.num_calls_finished_known_received, &drop_counts);
+ // Will be deleted in grpc_grpclb_request_destroy().
+ req->client_stats.calls_finished_with_drop.arg = drop_counts.release();
return req;
}
@@ -149,10 +151,10 @@ grpc_slice grpc_grpclb_request_encode(const grpc_grpclb_request* request) {
void grpc_grpclb_request_destroy(grpc_grpclb_request* request) {
if (request->has_client_stats) {
- grpc_grpclb_dropped_call_counts* drop_entries =
- static_cast<grpc_grpclb_dropped_call_counts*>(
+ grpc_core::GrpcLbClientStats::DroppedCallCounts* drop_entries =
+ static_cast<grpc_core::GrpcLbClientStats::DroppedCallCounts*>(
request->client_stats.calls_finished_with_drop.arg);
- grpc_grpclb_dropped_call_counts_destroy(drop_entries);
+ grpc_core::Delete(drop_entries);
}
gpr_free(request);
}
@@ -165,7 +167,8 @@ grpc_grpclb_initial_response* grpc_grpclb_initial_response_parse(
GRPC_SLICE_LENGTH(encoded_grpc_grpclb_response));
grpc_grpclb_response res;
memset(&res, 0, sizeof(grpc_grpclb_response));
- if (!pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res)) {
+ if (GPR_UNLIKELY(
+ !pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res))) {
gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream));
return nullptr;
}
@@ -195,7 +198,7 @@ grpc_grpclb_serverlist* grpc_grpclb_response_parse_serverlist(
res.server_list.servers.funcs.decode = count_serverlist;
res.server_list.servers.arg = sl;
bool status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res);
- if (!status) {
+ if (GPR_UNLIKELY(!status)) {
gpr_free(sl);
gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream));
return nullptr;
@@ -211,7 +214,7 @@ grpc_grpclb_serverlist* grpc_grpclb_response_parse_serverlist(
res.server_list.servers.arg = &decode_arg;
status = pb_decode(&stream_at_start, grpc_lb_v1_LoadBalanceResponse_fields,
&res);
- if (!status) {
+ if (GPR_UNLIKELY(!status)) {
grpc_grpclb_destroy_serverlist(sl);
gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream));
return nullptr;
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
index d4270f2536..06810a9fe8 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
@@ -42,7 +42,7 @@ typedef struct {
/** Create a request for a gRPC LB service under \a lb_service_name */
grpc_grpclb_request* grpc_grpclb_request_create(const char* lb_service_name);
grpc_grpclb_request* grpc_grpclb_load_report_request_create_locked(
- grpc_grpclb_client_stats* client_stats);
+ grpc_core::GrpcLbClientStats* client_stats);
/** Protocol Buffers v3-encode \a request */
grpc_slice grpc_grpclb_request_encode(const grpc_grpclb_request* request);
diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
index 9090c34412..76df976698 100644
--- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
@@ -62,31 +62,65 @@ class PickFirst : public LoadBalancingPolicy {
private:
~PickFirst();
+ class PickFirstSubchannelList;
+
+ class PickFirstSubchannelData
+ : public SubchannelData<PickFirstSubchannelList,
+ PickFirstSubchannelData> {
+ public:
+ PickFirstSubchannelData(PickFirstSubchannelList* subchannel_list,
+ const grpc_lb_user_data_vtable* user_data_vtable,
+ const grpc_lb_address& address,
+ grpc_subchannel* subchannel,
+ grpc_combiner* combiner)
+ : SubchannelData(subchannel_list, user_data_vtable, address, subchannel,
+ combiner) {}
+
+ void ProcessConnectivityChangeLocked(
+ grpc_connectivity_state connectivity_state, grpc_error* error) override;
+ };
+
+ class PickFirstSubchannelList
+ : public SubchannelList<PickFirstSubchannelList,
+ PickFirstSubchannelData> {
+ public:
+ PickFirstSubchannelList(PickFirst* policy, TraceFlag* tracer,
+ const grpc_lb_addresses* addresses,
+ grpc_combiner* combiner,
+ grpc_client_channel_factory* client_channel_factory,
+ const grpc_channel_args& args)
+ : SubchannelList(policy, tracer, addresses, combiner,
+ client_channel_factory, args) {
+ // Need to maintain a ref to the LB policy as long as we maintain
+ // any references to subchannels, since the subchannels'
+ // pollset_sets will include the LB policy's pollset_set.
+ policy->Ref(DEBUG_LOCATION, "subchannel_list").release();
+ }
+
+ ~PickFirstSubchannelList() {
+ PickFirst* p = static_cast<PickFirst*>(policy());
+ p->Unref(DEBUG_LOCATION, "subchannel_list");
+ }
+ };
+
void ShutdownLocked() override;
void StartPickingLocked();
void DestroyUnselectedSubchannelsLocked();
- static void OnConnectivityChangedLocked(void* arg, grpc_error* error);
-
- void SubchannelListRefForConnectivityWatch(
- grpc_lb_subchannel_list* subchannel_list, const char* reason);
- void SubchannelListUnrefForConnectivityWatch(
- grpc_lb_subchannel_list* subchannel_list, const char* reason);
-
- /** all our subchannels */
- grpc_lb_subchannel_list* subchannel_list_ = nullptr;
- /** latest pending subchannel list */
- grpc_lb_subchannel_list* latest_pending_subchannel_list_ = nullptr;
- /** selected subchannel in \a subchannel_list */
- grpc_lb_subchannel_data* selected_ = nullptr;
- /** have we started picking? */
+ // All our subchannels.
+ OrphanablePtr<PickFirstSubchannelList> subchannel_list_;
+ // Latest pending subchannel list.
+ OrphanablePtr<PickFirstSubchannelList> latest_pending_subchannel_list_;
+ // Selected subchannel in \a subchannel_list_.
+ PickFirstSubchannelData* selected_ = nullptr;
+ // Have we started picking?
bool started_picking_ = false;
- /** are we shut down? */
+ // Are we shut down?
bool shutdown_ = false;
- /** list of picks that are waiting on connectivity */
+ // List of picks that are waiting on connectivity.
PickState* pending_picks_ = nullptr;
- /** our connectivity state tracker */
+ // Our connectivity state tracker.
grpc_connectivity_state_tracker state_tracker_;
};
@@ -95,7 +129,7 @@ PickFirst::PickFirst(const Args& args) : LoadBalancingPolicy(args) {
grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE,
"pick_first");
if (grpc_lb_pick_first_trace.enabled()) {
- gpr_log(GPR_DEBUG, "Pick First %p created.", this);
+ gpr_log(GPR_INFO, "Pick First %p created.", this);
}
UpdateLocked(*args.args);
grpc_subchannel_index_ref();
@@ -103,7 +137,7 @@ PickFirst::PickFirst(const Args& args) : LoadBalancingPolicy(args) {
PickFirst::~PickFirst() {
if (grpc_lb_pick_first_trace.enabled()) {
- gpr_log(GPR_DEBUG, "Destroying Pick First %p", this);
+ gpr_log(GPR_INFO, "Destroying Pick First %p", this);
}
GPR_ASSERT(subchannel_list_ == nullptr);
GPR_ASSERT(latest_pending_subchannel_list_ == nullptr);
@@ -126,7 +160,7 @@ void PickFirst::HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) {
void PickFirst::ShutdownLocked() {
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel shutdown");
if (grpc_lb_pick_first_trace.enabled()) {
- gpr_log(GPR_DEBUG, "Pick First %p Shutting down", this);
+ gpr_log(GPR_INFO, "Pick First %p Shutting down", this);
}
shutdown_ = true;
PickState* pick;
@@ -137,15 +171,8 @@ void PickFirst::ShutdownLocked() {
}
grpc_connectivity_state_set(&state_tracker_, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_REF(error), "shutdown");
- if (subchannel_list_ != nullptr) {
- grpc_lb_subchannel_list_shutdown_and_unref(subchannel_list_, "pf_shutdown");
- subchannel_list_ = nullptr;
- }
- if (latest_pending_subchannel_list_ != nullptr) {
- grpc_lb_subchannel_list_shutdown_and_unref(latest_pending_subchannel_list_,
- "pf_shutdown");
- latest_pending_subchannel_list_ = nullptr;
- }
+ subchannel_list_.reset();
+ latest_pending_subchannel_list_.reset();
TryReresolutionLocked(&grpc_lb_pick_first_trace, GRPC_ERROR_CANCELLED);
GRPC_ERROR_UNREF(error);
}
@@ -192,14 +219,10 @@ void PickFirst::CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
void PickFirst::StartPickingLocked() {
started_picking_ = true;
- if (subchannel_list_ != nullptr && subchannel_list_->num_subchannels > 0) {
- subchannel_list_->checking_subchannel = 0;
- for (size_t i = 0; i < subchannel_list_->num_subchannels; ++i) {
- if (subchannel_list_->subchannels[i].subchannel != nullptr) {
- SubchannelListRefForConnectivityWatch(
- subchannel_list_, "connectivity_watch+start_picking");
- grpc_lb_subchannel_data_start_connectivity_watch(
- &subchannel_list_->subchannels[i]);
+ if (subchannel_list_ != nullptr) {
+ for (size_t i = 0; i < subchannel_list_->num_subchannels(); ++i) {
+ if (subchannel_list_->subchannel(i)->subchannel() != nullptr) {
+ subchannel_list_->subchannel(i)->StartConnectivityWatchLocked();
break;
}
}
@@ -215,7 +238,7 @@ void PickFirst::ExitIdleLocked() {
bool PickFirst::PickLocked(PickState* pick) {
// If we have a selected subchannel already, return synchronously.
if (selected_ != nullptr) {
- pick->connected_subchannel = selected_->connected_subchannel;
+ pick->connected_subchannel = selected_->connected_subchannel()->Ref();
return true;
}
// No subchannel selected yet, so handle asynchronously.
@@ -228,11 +251,10 @@ bool PickFirst::PickLocked(PickState* pick) {
}
void PickFirst::DestroyUnselectedSubchannelsLocked() {
- for (size_t i = 0; i < subchannel_list_->num_subchannels; ++i) {
- grpc_lb_subchannel_data* sd = &subchannel_list_->subchannels[i];
+ for (size_t i = 0; i < subchannel_list_->num_subchannels(); ++i) {
+ PickFirstSubchannelData* sd = subchannel_list_->subchannel(i);
if (selected_ != sd) {
- grpc_lb_subchannel_data_unref_subchannel(sd,
- "selected_different_subchannel");
+ sd->UnrefSubchannelLocked("selected_different_subchannel");
}
}
}
@@ -249,7 +271,7 @@ void PickFirst::NotifyOnStateChangeLocked(grpc_connectivity_state* current,
void PickFirst::PingOneLocked(grpc_closure* on_initiate, grpc_closure* on_ack) {
if (selected_ != nullptr) {
- selected_->connected_subchannel->Ping(on_initiate, on_ack);
+ selected_->connected_subchannel()->Ping(on_initiate, on_ack);
} else {
GRPC_CLOSURE_SCHED(on_initiate,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Not connected"));
@@ -258,24 +280,6 @@ void PickFirst::PingOneLocked(grpc_closure* on_initiate, grpc_closure* on_ack) {
}
}
-void PickFirst::SubchannelListRefForConnectivityWatch(
- grpc_lb_subchannel_list* subchannel_list, const char* reason) {
- // TODO(roth): We currently track this ref manually. Once the new
- // ClosureRef API is ready and the subchannel_list code has been
- // converted to a C++ API, find a way to hold the RefCountedPtr<>
- // somewhere (maybe in the subchannel_data object) instead of doing
- // this manually.
- auto self = Ref(DEBUG_LOCATION, reason);
- self.release();
- grpc_lb_subchannel_list_ref(subchannel_list, reason);
-}
-
-void PickFirst::SubchannelListUnrefForConnectivityWatch(
- grpc_lb_subchannel_list* subchannel_list, const char* reason) {
- Unref(DEBUG_LOCATION, reason);
- grpc_lb_subchannel_list_unref(subchannel_list, reason);
-}
-
void PickFirst::UpdateLocked(const grpc_channel_args& args) {
const grpc_arg* arg = grpc_channel_args_find(&args, GRPC_ARG_LB_ADDRESSES);
if (arg == nullptr || arg->type != GRPC_ARG_POINTER) {
@@ -295,75 +299,67 @@ void PickFirst::UpdateLocked(const grpc_channel_args& args) {
return;
}
const grpc_lb_addresses* addresses =
- (const grpc_lb_addresses*)arg->value.pointer.p;
+ static_cast<const grpc_lb_addresses*>(arg->value.pointer.p);
if (grpc_lb_pick_first_trace.enabled()) {
gpr_log(GPR_INFO,
"Pick First %p received update with %" PRIuPTR " addresses", this,
addresses->num_addresses);
}
- grpc_lb_subchannel_list* subchannel_list = grpc_lb_subchannel_list_create(
+ auto subchannel_list = MakeOrphanable<PickFirstSubchannelList>(
this, &grpc_lb_pick_first_trace, addresses, combiner(),
- client_channel_factory(), args, &PickFirst::OnConnectivityChangedLocked);
- if (subchannel_list->num_subchannels == 0) {
+ client_channel_factory(), args);
+ if (subchannel_list->num_subchannels() == 0) {
// Empty update or no valid subchannels. Unsubscribe from all current
// subchannels and put the channel in TRANSIENT_FAILURE.
grpc_connectivity_state_set(
&state_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
"pf_update_empty");
- if (subchannel_list_ != nullptr) {
- grpc_lb_subchannel_list_shutdown_and_unref(subchannel_list_,
- "sl_shutdown_empty_update");
- }
- subchannel_list_ = subchannel_list; // Empty list.
+ subchannel_list_ = std::move(subchannel_list); // Empty list.
selected_ = nullptr;
return;
}
if (selected_ == nullptr) {
// We don't yet have a selected subchannel, so replace the current
// subchannel list immediately.
- if (subchannel_list_ != nullptr) {
- grpc_lb_subchannel_list_shutdown_and_unref(subchannel_list_,
- "pf_update_before_selected");
+ subchannel_list_ = std::move(subchannel_list);
+ // If we've started picking, start trying to connect to the first
+ // subchannel in the new list.
+ if (started_picking_) {
+ subchannel_list_->subchannel(0)->StartConnectivityWatchLocked();
}
- subchannel_list_ = subchannel_list;
} else {
// We do have a selected subchannel.
// Check if it's present in the new list. If so, we're done.
- for (size_t i = 0; i < subchannel_list->num_subchannels; ++i) {
- grpc_lb_subchannel_data* sd = &subchannel_list->subchannels[i];
- if (sd->subchannel == selected_->subchannel) {
+ for (size_t i = 0; i < subchannel_list->num_subchannels(); ++i) {
+ PickFirstSubchannelData* sd = subchannel_list->subchannel(i);
+ if (sd->subchannel() == selected_->subchannel()) {
// The currently selected subchannel is in the update: we are done.
if (grpc_lb_pick_first_trace.enabled()) {
gpr_log(GPR_INFO,
"Pick First %p found already selected subchannel %p "
"at update index %" PRIuPTR " of %" PRIuPTR "; update done",
- this, selected_->subchannel, i,
- subchannel_list->num_subchannels);
- }
- if (selected_->connected_subchannel != nullptr) {
- sd->connected_subchannel = selected_->connected_subchannel;
+ this, selected_->subchannel(), i,
+ subchannel_list->num_subchannels());
}
- selected_ = sd;
- if (subchannel_list_ != nullptr) {
- grpc_lb_subchannel_list_shutdown_and_unref(
- subchannel_list_, "pf_update_includes_selected");
+ // Make sure it's in state READY. It might not be if we grabbed
+ // the combiner while a connectivity state notification
+ // informing us otherwise is pending.
+ // Note that CheckConnectivityStateLocked() also takes a ref to
+ // the connected subchannel.
+ grpc_error* error = GRPC_ERROR_NONE;
+ if (sd->CheckConnectivityStateLocked(&error) == GRPC_CHANNEL_READY) {
+ selected_ = sd;
+ subchannel_list_ = std::move(subchannel_list);
+ DestroyUnselectedSubchannelsLocked();
+ sd->StartConnectivityWatchLocked();
+ // If there was a previously pending update (which may or may
+ // not have contained the currently selected subchannel), drop
+ // it, so that it doesn't override what we've done here.
+ latest_pending_subchannel_list_.reset();
+ return;
}
- subchannel_list_ = subchannel_list;
- DestroyUnselectedSubchannelsLocked();
- SubchannelListRefForConnectivityWatch(
- subchannel_list, "connectivity_watch+replace_selected");
- grpc_lb_subchannel_data_start_connectivity_watch(sd);
- // If there was a previously pending update (which may or may
- // not have contained the currently selected subchannel), drop
- // it, so that it doesn't override what we've done here.
- if (latest_pending_subchannel_list_ != nullptr) {
- grpc_lb_subchannel_list_shutdown_and_unref(
- latest_pending_subchannel_list_,
- "pf_update_includes_selected+outdated");
- latest_pending_subchannel_list_ = nullptr;
- }
- return;
+ GRPC_ERROR_UNREF(error);
}
}
// Not keeping the previous selected subchannel, so set the latest
@@ -372,88 +368,66 @@ void PickFirst::UpdateLocked(const grpc_channel_args& args) {
// subchannel list.
if (latest_pending_subchannel_list_ != nullptr) {
if (grpc_lb_pick_first_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"Pick First %p Shutting down latest pending subchannel list "
"%p, about to be replaced by newer latest %p",
- this, latest_pending_subchannel_list_, subchannel_list);
+ this, latest_pending_subchannel_list_.get(),
+ subchannel_list.get());
}
- grpc_lb_subchannel_list_shutdown_and_unref(
- latest_pending_subchannel_list_, "sl_outdated_dont_smash");
}
- latest_pending_subchannel_list_ = subchannel_list;
- }
- // If we've started picking, start trying to connect to the first
- // subchannel in the new list.
- if (started_picking_) {
- SubchannelListRefForConnectivityWatch(subchannel_list,
- "connectivity_watch+update");
- grpc_lb_subchannel_data_start_connectivity_watch(
- &subchannel_list->subchannels[0]);
+ latest_pending_subchannel_list_ = std::move(subchannel_list);
+ // If we've started picking, start trying to connect to the first
+ // subchannel in the new list.
+ if (started_picking_) {
+ latest_pending_subchannel_list_->subchannel(0)
+ ->StartConnectivityWatchLocked();
+ }
}
}
-void PickFirst::OnConnectivityChangedLocked(void* arg, grpc_error* error) {
- grpc_lb_subchannel_data* sd = static_cast<grpc_lb_subchannel_data*>(arg);
- PickFirst* p = static_cast<PickFirst*>(sd->subchannel_list->policy);
- if (grpc_lb_pick_first_trace.enabled()) {
- gpr_log(GPR_DEBUG,
- "Pick First %p connectivity changed for subchannel %p (%" PRIuPTR
- " of %" PRIuPTR
- "), subchannel_list %p: state=%s p->shutdown_=%d "
- "sd->subchannel_list->shutting_down=%d error=%s",
- p, sd->subchannel, sd->subchannel_list->checking_subchannel,
- sd->subchannel_list->num_subchannels, sd->subchannel_list,
- grpc_connectivity_state_name(sd->pending_connectivity_state_unsafe),
- p->shutdown_, sd->subchannel_list->shutting_down,
- grpc_error_string(error));
- }
- // If the policy is shutting down, unref and return.
- if (p->shutdown_) {
- grpc_lb_subchannel_data_stop_connectivity_watch(sd);
- grpc_lb_subchannel_data_unref_subchannel(sd, "pf_shutdown");
- p->SubchannelListUnrefForConnectivityWatch(sd->subchannel_list,
- "pf_shutdown");
- return;
- }
- // If the subchannel list is shutting down, stop watching.
- if (sd->subchannel_list->shutting_down || error == GRPC_ERROR_CANCELLED) {
- grpc_lb_subchannel_data_stop_connectivity_watch(sd);
- grpc_lb_subchannel_data_unref_subchannel(sd, "pf_sl_shutdown");
- p->SubchannelListUnrefForConnectivityWatch(sd->subchannel_list,
- "pf_sl_shutdown");
- return;
- }
- // If we're still here, the notification must be for a subchannel in
- // either the current or latest pending subchannel lists.
- GPR_ASSERT(sd->subchannel_list == p->subchannel_list_ ||
- sd->subchannel_list == p->latest_pending_subchannel_list_);
- // Update state.
- sd->curr_connectivity_state = sd->pending_connectivity_state_unsafe;
+void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
+ grpc_connectivity_state connectivity_state, grpc_error* error) {
+ PickFirst* p = static_cast<PickFirst*>(subchannel_list()->policy());
+ // The notification must be for a subchannel in either the current or
+ // latest pending subchannel lists.
+ GPR_ASSERT(subchannel_list() == p->subchannel_list_.get() ||
+ subchannel_list() == p->latest_pending_subchannel_list_.get());
// Handle updates for the currently selected subchannel.
- if (p->selected_ == sd) {
+ if (p->selected_ == this) {
+ if (grpc_lb_pick_first_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "Pick First %p connectivity changed for selected subchannel", p);
+ }
// If the new state is anything other than READY and there is a
// pending update, switch to the pending update.
- if (sd->curr_connectivity_state != GRPC_CHANNEL_READY &&
+ if (connectivity_state != GRPC_CHANNEL_READY &&
p->latest_pending_subchannel_list_ != nullptr) {
+ if (grpc_lb_pick_first_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "Pick First %p promoting pending subchannel list %p to "
+ "replace %p",
+ p, p->latest_pending_subchannel_list_.get(),
+ p->subchannel_list_.get());
+ }
p->selected_ = nullptr;
- grpc_lb_subchannel_data_stop_connectivity_watch(sd);
- p->SubchannelListUnrefForConnectivityWatch(
- sd->subchannel_list, "selected_not_ready+switch_to_update");
- grpc_lb_subchannel_list_shutdown_and_unref(
- p->subchannel_list_, "selected_not_ready+switch_to_update");
- p->subchannel_list_ = p->latest_pending_subchannel_list_;
- p->latest_pending_subchannel_list_ = nullptr;
+ StopConnectivityWatchLocked();
+ p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_);
grpc_connectivity_state_set(
&p->state_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE,
- GRPC_ERROR_REF(error), "selected_not_ready+switch_to_update");
+ error != GRPC_ERROR_NONE
+ ? GRPC_ERROR_REF(error)
+ : GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "selected subchannel not ready; switching to pending "
+ "update"),
+ "selected_not_ready+switch_to_update");
} else {
// TODO(juanlishen): we re-resolve when the selected subchannel goes to
// TRANSIENT_FAILURE because we used to shut down in this case before
// re-resolution is introduced. But we need to investigate whether we
// really want to take any action instead of waiting for the selected
// subchannel reconnecting.
- GPR_ASSERT(sd->curr_connectivity_state != GRPC_CHANNEL_SHUTDOWN);
- if (sd->curr_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
+ GPR_ASSERT(connectivity_state != GRPC_CHANNEL_SHUTDOWN);
+ if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
// If the selected channel goes bad, request a re-resolution.
grpc_connectivity_state_set(&p->state_tracker_, GRPC_CHANNEL_IDLE,
GRPC_ERROR_NONE,
@@ -462,19 +436,16 @@ void PickFirst::OnConnectivityChangedLocked(void* arg, grpc_error* error) {
p->TryReresolutionLocked(&grpc_lb_pick_first_trace, GRPC_ERROR_NONE);
// In transient failure. Rely on re-resolution to recover.
p->selected_ = nullptr;
- grpc_lb_subchannel_data_stop_connectivity_watch(sd);
- p->SubchannelListUnrefForConnectivityWatch(sd->subchannel_list,
- "pf_selected_shutdown");
- grpc_lb_subchannel_data_unref_subchannel(
- sd, "pf_selected_shutdown"); // Unrefs connected subchannel
+ UnrefSubchannelLocked("pf_selected_shutdown");
+ StopConnectivityWatchLocked();
} else {
- grpc_connectivity_state_set(&p->state_tracker_,
- sd->curr_connectivity_state,
+ grpc_connectivity_state_set(&p->state_tracker_, connectivity_state,
GRPC_ERROR_REF(error), "selected_changed");
// Renew notification.
- grpc_lb_subchannel_data_start_connectivity_watch(sd);
+ RenewConnectivityWatchLocked();
}
}
+ GRPC_ERROR_UNREF(error);
return;
}
// If we get here, there are two possible cases:
@@ -486,26 +457,27 @@ void PickFirst::OnConnectivityChangedLocked(void* arg, grpc_error* error) {
// for a subchannel in p->latest_pending_subchannel_list_. The
// goal here is to find a subchannel from the update that we can
// select in place of the current one.
- switch (sd->curr_connectivity_state) {
+ switch (connectivity_state) {
case GRPC_CHANNEL_READY: {
// Case 2. Promote p->latest_pending_subchannel_list_ to
// p->subchannel_list_.
- sd->connected_subchannel =
- grpc_subchannel_get_connected_subchannel(sd->subchannel);
- if (sd->subchannel_list == p->latest_pending_subchannel_list_) {
- GPR_ASSERT(p->subchannel_list_ != nullptr);
- grpc_lb_subchannel_list_shutdown_and_unref(p->subchannel_list_,
- "finish_update");
- p->subchannel_list_ = p->latest_pending_subchannel_list_;
- p->latest_pending_subchannel_list_ = nullptr;
+ if (subchannel_list() == p->latest_pending_subchannel_list_.get()) {
+ if (grpc_lb_pick_first_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "Pick First %p promoting pending subchannel list %p to "
+ "replace %p",
+ p, p->latest_pending_subchannel_list_.get(),
+ p->subchannel_list_.get());
+ }
+ p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_);
}
// Cases 1 and 2.
grpc_connectivity_state_set(&p->state_tracker_, GRPC_CHANNEL_READY,
GRPC_ERROR_NONE, "connecting_ready");
- p->selected_ = sd;
+ p->selected_ = this;
if (grpc_lb_pick_first_trace.enabled()) {
gpr_log(GPR_INFO, "Pick First %p selected subchannel %p", p,
- sd->subchannel);
+ subchannel());
}
// Drop all other subchannels, since we are now connected.
p->DestroyUnselectedSubchannelsLocked();
@@ -513,7 +485,8 @@ void PickFirst::OnConnectivityChangedLocked(void* arg, grpc_error* error) {
PickState* pick;
while ((pick = p->pending_picks_)) {
p->pending_picks_ = pick->next;
- pick->connected_subchannel = p->selected_->connected_subchannel;
+ pick->connected_subchannel =
+ p->selected_->connected_subchannel()->Ref();
if (grpc_lb_pick_first_trace.enabled()) {
gpr_log(GPR_INFO,
"Servicing pending pick with selected subchannel %p",
@@ -522,45 +495,43 @@ void PickFirst::OnConnectivityChangedLocked(void* arg, grpc_error* error) {
GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_NONE);
}
// Renew notification.
- grpc_lb_subchannel_data_start_connectivity_watch(sd);
+ RenewConnectivityWatchLocked();
break;
}
case GRPC_CHANNEL_TRANSIENT_FAILURE: {
- grpc_lb_subchannel_data_stop_connectivity_watch(sd);
+ StopConnectivityWatchLocked();
+ PickFirstSubchannelData* sd = this;
do {
- sd->subchannel_list->checking_subchannel =
- (sd->subchannel_list->checking_subchannel + 1) %
- sd->subchannel_list->num_subchannels;
- sd = &sd->subchannel_list
- ->subchannels[sd->subchannel_list->checking_subchannel];
- } while (sd->subchannel == nullptr);
+ size_t next_index =
+ (sd->Index() + 1) % subchannel_list()->num_subchannels();
+ sd = subchannel_list()->subchannel(next_index);
+ } while (sd->subchannel() == nullptr);
// Case 1: Only set state to TRANSIENT_FAILURE if we've tried
// all subchannels.
- if (sd->subchannel_list->checking_subchannel == 0 &&
- sd->subchannel_list == p->subchannel_list_) {
+ if (sd->Index() == 0 && subchannel_list() == p->subchannel_list_.get()) {
grpc_connectivity_state_set(
&p->state_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_REF(error), "connecting_transient_failure");
}
- // Reuses the connectivity refs from the previous watch.
- grpc_lb_subchannel_data_start_connectivity_watch(sd);
+ sd->StartConnectivityWatchLocked();
break;
}
case GRPC_CHANNEL_CONNECTING:
case GRPC_CHANNEL_IDLE: {
// Only update connectivity state in case 1.
- if (sd->subchannel_list == p->subchannel_list_) {
+ if (subchannel_list() == p->subchannel_list_.get()) {
grpc_connectivity_state_set(&p->state_tracker_, GRPC_CHANNEL_CONNECTING,
GRPC_ERROR_REF(error),
"connecting_changed");
}
// Renew notification.
- grpc_lb_subchannel_data_start_connectivity_watch(sd);
+ RenewConnectivityWatchLocked();
break;
}
case GRPC_CHANNEL_SHUTDOWN:
GPR_UNREACHABLE_CODE(break);
}
+ GRPC_ERROR_UNREF(error);
}
//
diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
index e534131c02..b177385065 100644
--- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
@@ -73,23 +73,127 @@ class RoundRobin : public LoadBalancingPolicy {
private:
~RoundRobin();
- void ShutdownLocked() override;
+ // Forward declaration.
+ class RoundRobinSubchannelList;
+
+ // Data for a particular subchannel in a subchannel list.
+ // This subclass adds the following functionality:
+ // - Tracks user_data associated with each address, which will be
+ // returned along with picks that select the subchannel.
+ // - Tracks the previous connectivity state of the subchannel, so that
+ // we know how many subchannels are in each state.
+ class RoundRobinSubchannelData
+ : public SubchannelData<RoundRobinSubchannelList,
+ RoundRobinSubchannelData> {
+ public:
+ RoundRobinSubchannelData(RoundRobinSubchannelList* subchannel_list,
+ const grpc_lb_user_data_vtable* user_data_vtable,
+ const grpc_lb_address& address,
+ grpc_subchannel* subchannel,
+ grpc_combiner* combiner)
+ : SubchannelData(subchannel_list, user_data_vtable, address, subchannel,
+ combiner),
+ user_data_vtable_(user_data_vtable),
+ user_data_(user_data_vtable_ != nullptr
+ ? user_data_vtable_->copy(address.user_data)
+ : nullptr) {}
+
+ void UnrefSubchannelLocked(const char* reason) override {
+ SubchannelData::UnrefSubchannelLocked(reason);
+ if (user_data_ != nullptr) {
+ GPR_ASSERT(user_data_vtable_ != nullptr);
+ user_data_vtable_->destroy(user_data_);
+ user_data_ = nullptr;
+ }
+ }
- void StartPickingLocked();
- size_t GetNextReadySubchannelIndexLocked();
- void UpdateLastReadySubchannelIndexLocked(size_t last_ready_index);
- void UpdateConnectivityStatusLocked(grpc_lb_subchannel_data* sd,
- grpc_error* error);
+ void* user_data() const { return user_data_; }
+
+ grpc_connectivity_state connectivity_state() const {
+ return last_connectivity_state_;
+ }
- static void OnConnectivityChangedLocked(void* arg, grpc_error* error);
+ void UpdateConnectivityStateLocked(
+ grpc_connectivity_state connectivity_state, grpc_error* error);
+
+ private:
+ void ProcessConnectivityChangeLocked(
+ grpc_connectivity_state connectivity_state, grpc_error* error) override;
+
+ const grpc_lb_user_data_vtable* user_data_vtable_;
+ void* user_data_ = nullptr;
+ grpc_connectivity_state last_connectivity_state_ = GRPC_CHANNEL_IDLE;
+ };
+
+ // A list of subchannels.
+ class RoundRobinSubchannelList
+ : public SubchannelList<RoundRobinSubchannelList,
+ RoundRobinSubchannelData> {
+ public:
+ RoundRobinSubchannelList(
+ RoundRobin* policy, TraceFlag* tracer,
+ const grpc_lb_addresses* addresses, grpc_combiner* combiner,
+ grpc_client_channel_factory* client_channel_factory,
+ const grpc_channel_args& args)
+ : SubchannelList(policy, tracer, addresses, combiner,
+ client_channel_factory, args) {
+ // Need to maintain a ref to the LB policy as long as we maintain
+ // any references to subchannels, since the subchannels'
+ // pollset_sets will include the LB policy's pollset_set.
+ policy->Ref(DEBUG_LOCATION, "subchannel_list").release();
+ }
- void SubchannelListRefForConnectivityWatch(
- grpc_lb_subchannel_list* subchannel_list, const char* reason);
- void SubchannelListUnrefForConnectivityWatch(
- grpc_lb_subchannel_list* subchannel_list, const char* reason);
+ ~RoundRobinSubchannelList() {
+ GRPC_ERROR_UNREF(last_transient_failure_error_);
+ RoundRobin* p = static_cast<RoundRobin*>(policy());
+ p->Unref(DEBUG_LOCATION, "subchannel_list");
+ }
+
+ // Starts watching the subchannels in this list.
+ void StartWatchingLocked();
+
+ // Updates the counters of subchannels in each state when a
+ // subchannel transitions from old_state to new_state.
+ // transient_failure_error is the error that is reported when
+ // new_state is TRANSIENT_FAILURE.
+ void UpdateStateCountersLocked(grpc_connectivity_state old_state,
+ grpc_connectivity_state new_state,
+ grpc_error* transient_failure_error);
+
+ // If this subchannel list is the RR policy's current subchannel
+ // list, updates the RR policy's connectivity state based on the
+ // subchannel list's state counters.
+ void MaybeUpdateRoundRobinConnectivityStateLocked();
+
+ // Updates the RR policy's overall state based on the counters of
+ // subchannels in each state.
+ void UpdateRoundRobinStateFromSubchannelStateCountsLocked();
+
+ size_t GetNextReadySubchannelIndexLocked();
+ void UpdateLastReadySubchannelIndexLocked(size_t last_ready_index);
+
+ private:
+ size_t num_ready_ = 0;
+ size_t num_connecting_ = 0;
+ size_t num_transient_failure_ = 0;
+ grpc_error* last_transient_failure_error_ = GRPC_ERROR_NONE;
+ size_t last_ready_index_ = -1; // Index into list of last pick.
+ };
+
+ void ShutdownLocked() override;
+
+ void StartPickingLocked();
+ bool DoPickLocked(PickState* pick);
+ void DrainPendingPicksLocked();
/** list of subchannels */
- grpc_lb_subchannel_list* subchannel_list_ = nullptr;
+ OrphanablePtr<RoundRobinSubchannelList> subchannel_list_;
+ /** Latest version of the subchannel list.
+ * Subchannel connectivity callbacks will only promote updated subchannel
+ * lists if they equal \a latest_pending_subchannel_list. In other words,
+ * racing callbacks that reference outdated subchannel lists won't perform any
+ * update. */
+ OrphanablePtr<RoundRobinSubchannelList> latest_pending_subchannel_list_;
/** have we started picking? */
bool started_picking_ = false;
/** are we shutting down? */
@@ -98,14 +202,6 @@ class RoundRobin : public LoadBalancingPolicy {
PickState* pending_picks_ = nullptr;
/** our connectivity state tracker */
grpc_connectivity_state_tracker state_tracker_;
- /** Index into subchannels for last pick. */
- size_t last_ready_subchannel_index_ = 0;
- /** Latest version of the subchannel list.
- * Subchannel connectivity callbacks will only promote updated subchannel
- * lists if they equal \a latest_pending_subchannel_list. In other words,
- * racing callbacks that reference outdated subchannel lists won't perform any
- * update. */
- grpc_lb_subchannel_list* latest_pending_subchannel_list_ = nullptr;
};
RoundRobin::RoundRobin(const Args& args) : LoadBalancingPolicy(args) {
@@ -114,15 +210,15 @@ RoundRobin::RoundRobin(const Args& args) : LoadBalancingPolicy(args) {
"round_robin");
UpdateLocked(*args.args);
if (grpc_lb_round_robin_trace.enabled()) {
- gpr_log(GPR_DEBUG, "[RR %p] Created with %" PRIuPTR " subchannels", this,
- subchannel_list_->num_subchannels);
+ gpr_log(GPR_INFO, "[RR %p] Created with %" PRIuPTR " subchannels", this,
+ subchannel_list_->num_subchannels());
}
grpc_subchannel_index_ref();
}
RoundRobin::~RoundRobin() {
if (grpc_lb_round_robin_trace.enabled()) {
- gpr_log(GPR_DEBUG, "[RR %p] Destroying Round Robin policy", this);
+ gpr_log(GPR_INFO, "[RR %p] Destroying Round Robin policy", this);
}
GPR_ASSERT(subchannel_list_ == nullptr);
GPR_ASSERT(latest_pending_subchannel_list_ == nullptr);
@@ -131,68 +227,6 @@ RoundRobin::~RoundRobin() {
grpc_subchannel_index_unref();
}
-/** Returns the index into p->subchannel_list->subchannels of the next
- * subchannel in READY state, or p->subchannel_list->num_subchannels if no
- * subchannel is READY.
- *
- * Note that this function does *not* update p->last_ready_subchannel_index.
- * The caller must do that if it returns a pick. */
-size_t RoundRobin::GetNextReadySubchannelIndexLocked() {
- GPR_ASSERT(subchannel_list_ != nullptr);
- if (grpc_lb_round_robin_trace.enabled()) {
- gpr_log(GPR_INFO,
- "[RR %p] getting next ready subchannel (out of %" PRIuPTR
- "), "
- "last_ready_subchannel_index=%" PRIuPTR,
- this, subchannel_list_->num_subchannels,
- last_ready_subchannel_index_);
- }
- for (size_t i = 0; i < subchannel_list_->num_subchannels; ++i) {
- const size_t index = (i + last_ready_subchannel_index_ + 1) %
- subchannel_list_->num_subchannels;
- if (grpc_lb_round_robin_trace.enabled()) {
- gpr_log(
- GPR_DEBUG,
- "[RR %p] checking subchannel %p, subchannel_list %p, index %" PRIuPTR
- ": state=%s",
- this, subchannel_list_->subchannels[index].subchannel,
- subchannel_list_, index,
- grpc_connectivity_state_name(
- subchannel_list_->subchannels[index].curr_connectivity_state));
- }
- if (subchannel_list_->subchannels[index].curr_connectivity_state ==
- GRPC_CHANNEL_READY) {
- if (grpc_lb_round_robin_trace.enabled()) {
- gpr_log(GPR_DEBUG,
- "[RR %p] found next ready subchannel (%p) at index %" PRIuPTR
- " of subchannel_list %p",
- this, subchannel_list_->subchannels[index].subchannel, index,
- subchannel_list_);
- }
- return index;
- }
- }
- if (grpc_lb_round_robin_trace.enabled()) {
- gpr_log(GPR_DEBUG, "[RR %p] no subchannels in ready state", this);
- }
- return subchannel_list_->num_subchannels;
-}
-
-// Sets last_ready_subchannel_index_ to last_ready_index.
-void RoundRobin::UpdateLastReadySubchannelIndexLocked(size_t last_ready_index) {
- GPR_ASSERT(last_ready_index < subchannel_list_->num_subchannels);
- last_ready_subchannel_index_ = last_ready_index;
- if (grpc_lb_round_robin_trace.enabled()) {
- gpr_log(GPR_DEBUG,
- "[RR %p] setting last_ready_subchannel_index=%" PRIuPTR
- " (SC %p, CSC %p)",
- this, last_ready_index,
- subchannel_list_->subchannels[last_ready_index].subchannel,
- subchannel_list_->subchannels[last_ready_index]
- .connected_subchannel.get());
- }
-}
-
void RoundRobin::HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) {
PickState* pick;
while ((pick = pending_picks_) != nullptr) {
@@ -207,7 +241,7 @@ void RoundRobin::HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) {
void RoundRobin::ShutdownLocked() {
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel shutdown");
if (grpc_lb_round_robin_trace.enabled()) {
- gpr_log(GPR_DEBUG, "[RR %p] Shutting down", this);
+ gpr_log(GPR_INFO, "[RR %p] Shutting down", this);
}
shutdown_ = true;
PickState* pick;
@@ -218,16 +252,8 @@ void RoundRobin::ShutdownLocked() {
}
grpc_connectivity_state_set(&state_tracker_, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_REF(error), "rr_shutdown");
- if (subchannel_list_ != nullptr) {
- grpc_lb_subchannel_list_shutdown_and_unref(subchannel_list_,
- "sl_shutdown_rr_shutdown");
- subchannel_list_ = nullptr;
- }
- if (latest_pending_subchannel_list_ != nullptr) {
- grpc_lb_subchannel_list_shutdown_and_unref(
- latest_pending_subchannel_list_, "sl_shutdown_pending_rr_shutdown");
- latest_pending_subchannel_list_ = nullptr;
- }
+ subchannel_list_.reset();
+ latest_pending_subchannel_list_.reset();
TryReresolutionLocked(&grpc_lb_round_robin_trace, GRPC_ERROR_CANCELLED);
GRPC_ERROR_UNREF(error);
}
@@ -273,70 +299,59 @@ void RoundRobin::CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
GRPC_ERROR_UNREF(error);
}
-void RoundRobin::SubchannelListRefForConnectivityWatch(
- grpc_lb_subchannel_list* subchannel_list, const char* reason) {
- // TODO(roth): We currently track this ref manually. Once the new
- // ClosureRef API is ready and the subchannel_list code has been
- // converted to a C++ API, find a way to hold the RefCountedPtr<>
- // somewhere (maybe in the subchannel_data object) instead of doing
- // this manually.
- auto self = Ref(DEBUG_LOCATION, reason);
- self.release();
- grpc_lb_subchannel_list_ref(subchannel_list, reason);
+void RoundRobin::StartPickingLocked() {
+ started_picking_ = true;
+ subchannel_list_->StartWatchingLocked();
}
-void RoundRobin::SubchannelListUnrefForConnectivityWatch(
- grpc_lb_subchannel_list* subchannel_list, const char* reason) {
- Unref(DEBUG_LOCATION, reason);
- grpc_lb_subchannel_list_unref(subchannel_list, reason);
+void RoundRobin::ExitIdleLocked() {
+ if (!started_picking_) {
+ StartPickingLocked();
+ }
}
-void RoundRobin::StartPickingLocked() {
- started_picking_ = true;
- for (size_t i = 0; i < subchannel_list_->num_subchannels; i++) {
- if (subchannel_list_->subchannels[i].subchannel != nullptr) {
- SubchannelListRefForConnectivityWatch(subchannel_list_,
- "connectivity_watch");
- grpc_lb_subchannel_data_start_connectivity_watch(
- &subchannel_list_->subchannels[i]);
+bool RoundRobin::DoPickLocked(PickState* pick) {
+ const size_t next_ready_index =
+ subchannel_list_->GetNextReadySubchannelIndexLocked();
+ if (next_ready_index < subchannel_list_->num_subchannels()) {
+ /* readily available, report right away */
+ RoundRobinSubchannelData* sd =
+ subchannel_list_->subchannel(next_ready_index);
+ GPR_ASSERT(sd->connected_subchannel() != nullptr);
+ pick->connected_subchannel = sd->connected_subchannel()->Ref();
+ if (pick->user_data != nullptr) {
+ *pick->user_data = sd->user_data();
}
+ if (grpc_lb_round_robin_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "[RR %p] Picked target <-- Subchannel %p (connected %p) (sl %p, "
+ "index %" PRIuPTR ")",
+ this, sd->subchannel(), pick->connected_subchannel.get(),
+ sd->subchannel_list(), next_ready_index);
+ }
+ /* only advance the last picked pointer if the selection was used */
+ subchannel_list_->UpdateLastReadySubchannelIndexLocked(next_ready_index);
+ return true;
}
+ return false;
}
-void RoundRobin::ExitIdleLocked() {
- if (!started_picking_) {
- StartPickingLocked();
+void RoundRobin::DrainPendingPicksLocked() {
+ PickState* pick;
+ while ((pick = pending_picks_)) {
+ pending_picks_ = pick->next;
+ GPR_ASSERT(DoPickLocked(pick));
+ GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_NONE);
}
}
bool RoundRobin::PickLocked(PickState* pick) {
if (grpc_lb_round_robin_trace.enabled()) {
- gpr_log(GPR_DEBUG, "[RR %p] Trying to pick (shutdown: %d)", this,
- shutdown_);
+ gpr_log(GPR_INFO, "[RR %p] Trying to pick (shutdown: %d)", this, shutdown_);
}
GPR_ASSERT(!shutdown_);
if (subchannel_list_ != nullptr) {
- const size_t next_ready_index = GetNextReadySubchannelIndexLocked();
- if (next_ready_index < subchannel_list_->num_subchannels) {
- /* readily available, report right away */
- grpc_lb_subchannel_data* sd =
- &subchannel_list_->subchannels[next_ready_index];
- pick->connected_subchannel = sd->connected_subchannel;
- if (pick->user_data != nullptr) {
- *pick->user_data = sd->user_data;
- }
- if (grpc_lb_round_robin_trace.enabled()) {
- gpr_log(
- GPR_DEBUG,
- "[RR %p] Picked target <-- Subchannel %p (connected %p) (sl %p, "
- "index %" PRIuPTR ")",
- this, sd->subchannel, pick->connected_subchannel.get(),
- sd->subchannel_list, next_ready_index);
- }
- /* only advance the last picked pointer if the selection was used */
- UpdateLastReadySubchannelIndexLocked(next_ready_index);
- return true;
- }
+ if (DoPickLocked(pick)) return true;
}
/* no pick currently available. Save for later in list of pending picks */
if (!started_picking_) {
@@ -347,36 +362,62 @@ bool RoundRobin::PickLocked(PickState* pick) {
return false;
}
-void UpdateStateCountersLocked(grpc_lb_subchannel_data* sd) {
- grpc_lb_subchannel_list* subchannel_list = sd->subchannel_list;
- GPR_ASSERT(sd->prev_connectivity_state != GRPC_CHANNEL_SHUTDOWN);
- GPR_ASSERT(sd->curr_connectivity_state != GRPC_CHANNEL_SHUTDOWN);
- if (sd->prev_connectivity_state == GRPC_CHANNEL_READY) {
- GPR_ASSERT(subchannel_list->num_ready > 0);
- --subchannel_list->num_ready;
- } else if (sd->prev_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
- GPR_ASSERT(subchannel_list->num_transient_failures > 0);
- --subchannel_list->num_transient_failures;
- } else if (sd->prev_connectivity_state == GRPC_CHANNEL_IDLE) {
- GPR_ASSERT(subchannel_list->num_idle > 0);
- --subchannel_list->num_idle;
+void RoundRobin::RoundRobinSubchannelList::StartWatchingLocked() {
+ if (num_subchannels() == 0) return;
+ // Check current state of each subchannel synchronously, since any
+ // subchannel already used by some other channel may have a non-IDLE
+ // state.
+ for (size_t i = 0; i < num_subchannels(); ++i) {
+ grpc_error* error = GRPC_ERROR_NONE;
+ grpc_connectivity_state state =
+ subchannel(i)->CheckConnectivityStateLocked(&error);
+ if (state != GRPC_CHANNEL_IDLE) {
+ subchannel(i)->UpdateConnectivityStateLocked(state, error);
+ }
}
- sd->prev_connectivity_state = sd->curr_connectivity_state;
- if (sd->curr_connectivity_state == GRPC_CHANNEL_READY) {
- ++subchannel_list->num_ready;
- } else if (sd->curr_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
- ++subchannel_list->num_transient_failures;
- } else if (sd->curr_connectivity_state == GRPC_CHANNEL_IDLE) {
- ++subchannel_list->num_idle;
+ // Now set the LB policy's state based on the subchannels' states.
+ UpdateRoundRobinStateFromSubchannelStateCountsLocked();
+ // Start connectivity watch for each subchannel.
+ for (size_t i = 0; i < num_subchannels(); i++) {
+ if (subchannel(i)->subchannel() != nullptr) {
+ subchannel(i)->StartConnectivityWatchLocked();
+ }
}
}
-/** Sets the policy's connectivity status based on that of the passed-in \a sd
- * (the grpc_lb_subchannel_data associated with the updated subchannel) and the
- * subchannel list \a sd belongs to (sd->subchannel_list). \a error will be used
- * only if the policy transitions to state TRANSIENT_FAILURE. */
-void RoundRobin::UpdateConnectivityStatusLocked(grpc_lb_subchannel_data* sd,
- grpc_error* error) {
+void RoundRobin::RoundRobinSubchannelList::UpdateStateCountersLocked(
+ grpc_connectivity_state old_state, grpc_connectivity_state new_state,
+ grpc_error* transient_failure_error) {
+ GPR_ASSERT(old_state != GRPC_CHANNEL_SHUTDOWN);
+ GPR_ASSERT(new_state != GRPC_CHANNEL_SHUTDOWN);
+ if (old_state == GRPC_CHANNEL_READY) {
+ GPR_ASSERT(num_ready_ > 0);
+ --num_ready_;
+ } else if (old_state == GRPC_CHANNEL_CONNECTING) {
+ GPR_ASSERT(num_connecting_ > 0);
+ --num_connecting_;
+ } else if (old_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
+ GPR_ASSERT(num_transient_failure_ > 0);
+ --num_transient_failure_;
+ }
+ if (new_state == GRPC_CHANNEL_READY) {
+ ++num_ready_;
+ } else if (new_state == GRPC_CHANNEL_CONNECTING) {
+ ++num_connecting_;
+ } else if (new_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
+ ++num_transient_failure_;
+ }
+ GRPC_ERROR_UNREF(last_transient_failure_error_);
+ last_transient_failure_error_ = transient_failure_error;
+}
+
+// Sets the RR policy's connectivity state based on the current
+// subchannel list.
+void RoundRobin::RoundRobinSubchannelList::
+ MaybeUpdateRoundRobinConnectivityStateLocked() {
+ RoundRobin* p = static_cast<RoundRobin*>(policy());
+ // Only set connectivity state if this is the current subchannel list.
+ if (p->subchannel_list_.get() != this) return;
/* In priority order. The first rule to match terminates the search (ie, if we
* are on rule n, all previous rules were unfulfilled).
*
@@ -391,155 +432,151 @@ void RoundRobin::UpdateConnectivityStatusLocked(grpc_lb_subchannel_data* sd,
* CHECK: subchannel_list->num_transient_failures ==
* subchannel_list->num_subchannels.
*/
- grpc_lb_subchannel_list* subchannel_list = sd->subchannel_list;
- GPR_ASSERT(sd->curr_connectivity_state != GRPC_CHANNEL_IDLE);
- if (subchannel_list->num_ready > 0) {
+ if (num_ready_ > 0) {
/* 1) READY */
- grpc_connectivity_state_set(&state_tracker_, GRPC_CHANNEL_READY,
+ grpc_connectivity_state_set(&p->state_tracker_, GRPC_CHANNEL_READY,
GRPC_ERROR_NONE, "rr_ready");
- } else if (sd->curr_connectivity_state == GRPC_CHANNEL_CONNECTING) {
+ } else if (num_connecting_ > 0) {
/* 2) CONNECTING */
- grpc_connectivity_state_set(&state_tracker_, GRPC_CHANNEL_CONNECTING,
+ grpc_connectivity_state_set(&p->state_tracker_, GRPC_CHANNEL_CONNECTING,
GRPC_ERROR_NONE, "rr_connecting");
- } else if (subchannel_list->num_transient_failures ==
- subchannel_list->num_subchannels) {
+ } else if (num_transient_failure_ == num_subchannels()) {
/* 3) TRANSIENT_FAILURE */
- grpc_connectivity_state_set(&state_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE,
- GRPC_ERROR_REF(error),
+ grpc_connectivity_state_set(&p->state_tracker_,
+ GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_ERROR_REF(last_transient_failure_error_),
"rr_exhausted_subchannels");
}
- GRPC_ERROR_UNREF(error);
}
-void RoundRobin::OnConnectivityChangedLocked(void* arg, grpc_error* error) {
- grpc_lb_subchannel_data* sd = static_cast<grpc_lb_subchannel_data*>(arg);
- RoundRobin* p = static_cast<RoundRobin*>(sd->subchannel_list->policy);
+void RoundRobin::RoundRobinSubchannelList::
+ UpdateRoundRobinStateFromSubchannelStateCountsLocked() {
+ RoundRobin* p = static_cast<RoundRobin*>(policy());
+ if (num_ready_ > 0) {
+ if (p->subchannel_list_.get() != this) {
+ // Promote this list to p->subchannel_list_.
+ // This list must be p->latest_pending_subchannel_list_, because
+ // any previous update would have been shut down already and
+ // therefore we would not be receiving a notification for them.
+ GPR_ASSERT(p->latest_pending_subchannel_list_.get() == this);
+ GPR_ASSERT(!shutting_down());
+ if (grpc_lb_round_robin_trace.enabled()) {
+ const size_t old_num_subchannels =
+ p->subchannel_list_ != nullptr
+ ? p->subchannel_list_->num_subchannels()
+ : 0;
+ gpr_log(GPR_INFO,
+ "[RR %p] phasing out subchannel list %p (size %" PRIuPTR
+ ") in favor of %p (size %" PRIuPTR ")",
+ p, p->subchannel_list_.get(), old_num_subchannels, this,
+ num_subchannels());
+ }
+ p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_);
+ }
+ // Drain pending picks.
+ p->DrainPendingPicksLocked();
+ }
+ // Update the RR policy's connectivity state if needed.
+ MaybeUpdateRoundRobinConnectivityStateLocked();
+}
+
+void RoundRobin::RoundRobinSubchannelData::UpdateConnectivityStateLocked(
+ grpc_connectivity_state connectivity_state, grpc_error* error) {
+ RoundRobin* p = static_cast<RoundRobin*>(subchannel_list()->policy());
if (grpc_lb_round_robin_trace.enabled()) {
gpr_log(
- GPR_DEBUG,
- "[RR %p] connectivity changed for subchannel %p, subchannel_list %p: "
- "prev_state=%s new_state=%s p->shutdown=%d "
- "sd->subchannel_list->shutting_down=%d error=%s",
- p, sd->subchannel, sd->subchannel_list,
- grpc_connectivity_state_name(sd->prev_connectivity_state),
- grpc_connectivity_state_name(sd->pending_connectivity_state_unsafe),
- p->shutdown_, sd->subchannel_list->shutting_down,
- grpc_error_string(error));
- }
- GPR_ASSERT(sd->subchannel != nullptr);
- // If the policy is shutting down, unref and return.
- if (p->shutdown_) {
- grpc_lb_subchannel_data_stop_connectivity_watch(sd);
- grpc_lb_subchannel_data_unref_subchannel(sd, "rr_shutdown");
- p->SubchannelListUnrefForConnectivityWatch(sd->subchannel_list,
- "rr_shutdown");
- return;
+ GPR_INFO,
+ "[RR %p] connectivity changed for subchannel %p, subchannel_list %p "
+ "(index %" PRIuPTR " of %" PRIuPTR "): prev_state=%s new_state=%s",
+ p, subchannel(), subchannel_list(), Index(),
+ subchannel_list()->num_subchannels(),
+ grpc_connectivity_state_name(last_connectivity_state_),
+ grpc_connectivity_state_name(connectivity_state));
+ }
+ subchannel_list()->UpdateStateCountersLocked(last_connectivity_state_,
+ connectivity_state, error);
+ last_connectivity_state_ = connectivity_state;
+}
+
+void RoundRobin::RoundRobinSubchannelData::ProcessConnectivityChangeLocked(
+ grpc_connectivity_state connectivity_state, grpc_error* error) {
+ RoundRobin* p = static_cast<RoundRobin*>(subchannel_list()->policy());
+ GPR_ASSERT(subchannel() != nullptr);
+ // If the new state is TRANSIENT_FAILURE, re-resolve.
+ // Only do this if we've started watching, not at startup time.
+ // Otherwise, if the subchannel was already in state TRANSIENT_FAILURE
+ // when the subchannel list was created, we'd wind up in a constant
+ // loop of re-resolution.
+ if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
+ if (grpc_lb_round_robin_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "[RR %p] Subchannel %p has gone into TRANSIENT_FAILURE. "
+ "Requesting re-resolution",
+ p, subchannel());
+ }
+ p->TryReresolutionLocked(&grpc_lb_round_robin_trace, GRPC_ERROR_NONE);
}
- // If the subchannel list is shutting down, stop watching.
- if (sd->subchannel_list->shutting_down || error == GRPC_ERROR_CANCELLED) {
- grpc_lb_subchannel_data_stop_connectivity_watch(sd);
- grpc_lb_subchannel_data_unref_subchannel(sd, "rr_sl_shutdown");
- p->SubchannelListUnrefForConnectivityWatch(sd->subchannel_list,
- "rr_sl_shutdown");
- return;
+ // Update state counters.
+ UpdateConnectivityStateLocked(connectivity_state, error);
+ // Update overall state and renew notification.
+ subchannel_list()->UpdateRoundRobinStateFromSubchannelStateCountsLocked();
+ RenewConnectivityWatchLocked();
+}
+
+/** Returns the index into p->subchannel_list->subchannels of the next
+ * subchannel in READY state, or p->subchannel_list->num_subchannels if no
+ * subchannel is READY.
+ *
+ * Note that this function does *not* update p->last_ready_subchannel_index.
+ * The caller must do that if it returns a pick. */
+size_t
+RoundRobin::RoundRobinSubchannelList::GetNextReadySubchannelIndexLocked() {
+ if (grpc_lb_round_robin_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "[RR %p] getting next ready subchannel (out of %" PRIuPTR
+ "), last_ready_index=%" PRIuPTR,
+ policy(), num_subchannels(), last_ready_index_);
}
- // If we're still here, the notification must be for a subchannel in
- // either the current or latest pending subchannel lists.
- GPR_ASSERT(sd->subchannel_list == p->subchannel_list_ ||
- sd->subchannel_list == p->latest_pending_subchannel_list_);
- GPR_ASSERT(sd->pending_connectivity_state_unsafe != GRPC_CHANNEL_SHUTDOWN);
- // Now that we're inside the combiner, copy the pending connectivity
- // state (which was set by the connectivity state watcher) to
- // curr_connectivity_state, which is what we use inside of the combiner.
- sd->curr_connectivity_state = sd->pending_connectivity_state_unsafe;
- // If the sd's new state is TRANSIENT_FAILURE, unref the *connected*
- // subchannel, if any.
- switch (sd->curr_connectivity_state) {
- case GRPC_CHANNEL_TRANSIENT_FAILURE: {
- sd->connected_subchannel.reset();
- if (grpc_lb_round_robin_trace.enabled()) {
- gpr_log(GPR_DEBUG,
- "[RR %p] Subchannel %p has gone into TRANSIENT_FAILURE. "
- "Requesting re-resolution",
- p, sd->subchannel);
- }
- p->TryReresolutionLocked(&grpc_lb_round_robin_trace, GRPC_ERROR_NONE);
- break;
+ for (size_t i = 0; i < num_subchannels(); ++i) {
+ const size_t index = (i + last_ready_index_ + 1) % num_subchannels();
+ if (grpc_lb_round_robin_trace.enabled()) {
+ gpr_log(
+ GPR_INFO,
+ "[RR %p] checking subchannel %p, subchannel_list %p, index %" PRIuPTR
+ ": state=%s",
+ policy(), subchannel(index)->subchannel(), this, index,
+ grpc_connectivity_state_name(
+ subchannel(index)->connectivity_state()));
}
- case GRPC_CHANNEL_READY: {
- if (sd->connected_subchannel == nullptr) {
- sd->connected_subchannel =
- grpc_subchannel_get_connected_subchannel(sd->subchannel);
- }
- if (sd->subchannel_list != p->subchannel_list_) {
- // promote sd->subchannel_list to p->subchannel_list_.
- // sd->subchannel_list must be equal to
- // p->latest_pending_subchannel_list_ because we have already filtered
- // for sds belonging to outdated subchannel lists.
- GPR_ASSERT(sd->subchannel_list == p->latest_pending_subchannel_list_);
- GPR_ASSERT(!sd->subchannel_list->shutting_down);
- if (grpc_lb_round_robin_trace.enabled()) {
- const size_t num_subchannels =
- p->subchannel_list_ != nullptr
- ? p->subchannel_list_->num_subchannels
- : 0;
- gpr_log(GPR_DEBUG,
- "[RR %p] phasing out subchannel list %p (size %" PRIuPTR
- ") in favor of %p (size %" PRIuPTR ")",
- p, p->subchannel_list_, num_subchannels, sd->subchannel_list,
- num_subchannels);
- }
- if (p->subchannel_list_ != nullptr) {
- // dispose of the current subchannel_list
- grpc_lb_subchannel_list_shutdown_and_unref(p->subchannel_list_,
- "sl_phase_out_shutdown");
- }
- p->subchannel_list_ = p->latest_pending_subchannel_list_;
- p->latest_pending_subchannel_list_ = nullptr;
- }
- /* at this point we know there's at least one suitable subchannel. Go
- * ahead and pick one and notify the pending suitors in
- * p->pending_picks. This preemptively replicates rr_pick()'s actions. */
- const size_t next_ready_index = p->GetNextReadySubchannelIndexLocked();
- GPR_ASSERT(next_ready_index < p->subchannel_list_->num_subchannels);
- grpc_lb_subchannel_data* selected =
- &p->subchannel_list_->subchannels[next_ready_index];
- if (p->pending_picks_ != nullptr) {
- // if the selected subchannel is going to be used for the pending
- // picks, update the last picked pointer
- p->UpdateLastReadySubchannelIndexLocked(next_ready_index);
- }
- PickState* pick;
- while ((pick = p->pending_picks_)) {
- p->pending_picks_ = pick->next;
- pick->connected_subchannel = selected->connected_subchannel;
- if (pick->user_data != nullptr) {
- *pick->user_data = selected->user_data;
- }
- if (grpc_lb_round_robin_trace.enabled()) {
- gpr_log(GPR_DEBUG,
- "[RR %p] Fulfilling pending pick. Target <-- subchannel %p "
- "(subchannel_list %p, index %" PRIuPTR ")",
- p, selected->subchannel, p->subchannel_list_,
- next_ready_index);
- }
- GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_NONE);
+ if (subchannel(index)->connectivity_state() == GRPC_CHANNEL_READY) {
+ if (grpc_lb_round_robin_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "[RR %p] found next ready subchannel (%p) at index %" PRIuPTR
+ " of subchannel_list %p",
+ policy(), subchannel(index)->subchannel(), index, this);
}
- break;
+ return index;
}
- case GRPC_CHANNEL_SHUTDOWN:
- GPR_UNREACHABLE_CODE(return );
- case GRPC_CHANNEL_CONNECTING:
- case GRPC_CHANNEL_IDLE:; // fallthrough
}
- // Update state counters.
- UpdateStateCountersLocked(sd);
- // Only update connectivity based on the selected subchannel list.
- if (sd->subchannel_list == p->subchannel_list_) {
- p->UpdateConnectivityStatusLocked(sd, GRPC_ERROR_REF(error));
+ if (grpc_lb_round_robin_trace.enabled()) {
+ gpr_log(GPR_INFO, "[RR %p] no subchannels in ready state", this);
+ }
+ return num_subchannels();
+}
+
+// Sets last_ready_index_ to last_ready_index.
+void RoundRobin::RoundRobinSubchannelList::UpdateLastReadySubchannelIndexLocked(
+ size_t last_ready_index) {
+ GPR_ASSERT(last_ready_index < num_subchannels());
+ last_ready_index_ = last_ready_index;
+ if (grpc_lb_round_robin_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "[RR %p] setting last_ready_subchannel_index=%" PRIuPTR
+ " (SC %p, CSC %p)",
+ policy(), last_ready_index,
+ subchannel(last_ready_index)->subchannel(),
+ subchannel(last_ready_index)->connected_subchannel());
}
- // Renew notification.
- grpc_lb_subchannel_data_start_connectivity_watch(sd);
}
grpc_connectivity_state RoundRobin::CheckConnectivityLocked(
@@ -555,11 +592,12 @@ void RoundRobin::NotifyOnStateChangeLocked(grpc_connectivity_state* current,
void RoundRobin::PingOneLocked(grpc_closure* on_initiate,
grpc_closure* on_ack) {
- const size_t next_ready_index = GetNextReadySubchannelIndexLocked();
- if (next_ready_index < subchannel_list_->num_subchannels) {
- grpc_lb_subchannel_data* selected =
- &subchannel_list_->subchannels[next_ready_index];
- selected->connected_subchannel->Ping(on_initiate, on_ack);
+ const size_t next_ready_index =
+ subchannel_list_->GetNextReadySubchannelIndexLocked();
+ if (next_ready_index < subchannel_list_->num_subchannels()) {
+ RoundRobinSubchannelData* selected =
+ subchannel_list_->subchannel(next_ready_index);
+ selected->connected_subchannel()->Ping(on_initiate, on_ack);
} else {
GRPC_CLOSURE_SCHED(on_initiate, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Round Robin not connected"));
@@ -570,7 +608,7 @@ void RoundRobin::PingOneLocked(grpc_closure* on_initiate,
void RoundRobin::UpdateLocked(const grpc_channel_args& args) {
const grpc_arg* arg = grpc_channel_args_find(&args, GRPC_ARG_LB_ADDRESSES);
- if (arg == nullptr || arg->type != GRPC_ARG_POINTER) {
+ if (GPR_UNLIKELY(arg == nullptr || arg->type != GRPC_ARG_POINTER)) {
gpr_log(GPR_ERROR, "[RR %p] update provided no addresses; ignoring", this);
// If we don't have a current subchannel list, go into TRANSIENT_FAILURE.
// Otherwise, keep using the current subchannel list (ignore this update).
@@ -582,80 +620,37 @@ void RoundRobin::UpdateLocked(const grpc_channel_args& args) {
}
return;
}
- grpc_lb_addresses* addresses = (grpc_lb_addresses*)arg->value.pointer.p;
+ grpc_lb_addresses* addresses =
+ static_cast<grpc_lb_addresses*>(arg->value.pointer.p);
if (grpc_lb_round_robin_trace.enabled()) {
- gpr_log(GPR_DEBUG, "[RR %p] received update with %" PRIuPTR " addresses",
+ gpr_log(GPR_INFO, "[RR %p] received update with %" PRIuPTR " addresses",
this, addresses->num_addresses);
}
- grpc_lb_subchannel_list* subchannel_list = grpc_lb_subchannel_list_create(
- this, &grpc_lb_round_robin_trace, addresses, combiner(),
- client_channel_factory(), args, &RoundRobin::OnConnectivityChangedLocked);
- if (subchannel_list->num_subchannels == 0) {
- grpc_connectivity_state_set(
- &state_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE,
- GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
- "rr_update_empty");
- if (subchannel_list_ != nullptr) {
- grpc_lb_subchannel_list_shutdown_and_unref(subchannel_list_,
- "sl_shutdown_empty_update");
+ // Replace latest_pending_subchannel_list_.
+ if (latest_pending_subchannel_list_ != nullptr) {
+ if (grpc_lb_round_robin_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "[RR %p] Shutting down previous pending subchannel list %p", this,
+ latest_pending_subchannel_list_.get());
}
- subchannel_list_ = subchannel_list; // empty list
- return;
}
- if (started_picking_) {
- for (size_t i = 0; i < subchannel_list->num_subchannels; ++i) {
- const grpc_connectivity_state subchannel_state =
- grpc_subchannel_check_connectivity(
- subchannel_list->subchannels[i].subchannel, nullptr);
- // Override the default setting of IDLE for connectivity notification
- // purposes if the subchannel is already in transient failure. Otherwise
- // we'd be immediately notified of the IDLE-TRANSIENT_FAILURE
- // discrepancy, attempt to re-resolve and end up here again.
- // TODO(roth): As part of C++-ifying the subchannel_list API, design a
- // better API for notifying the LB policy of subchannel states, which can
- // be used both for the subchannel's initial state and for subsequent
- // state changes. This will allow us to handle this more generally instead
- // of special-casing TRANSIENT_FAILURE (e.g., we can also distribute any
- // pending picks across all READY subchannels rather than sending them all
- // to the first one).
- if (subchannel_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
- subchannel_list->subchannels[i].pending_connectivity_state_unsafe =
- subchannel_list->subchannels[i].curr_connectivity_state =
- subchannel_list->subchannels[i].prev_connectivity_state =
- subchannel_state;
- --subchannel_list->num_idle;
- ++subchannel_list->num_transient_failures;
- }
- }
- if (latest_pending_subchannel_list_ != nullptr) {
- if (grpc_lb_round_robin_trace.enabled()) {
- gpr_log(GPR_DEBUG,
- "[RR %p] Shutting down latest pending subchannel list %p, "
- "about to be replaced by newer latest %p",
- this, latest_pending_subchannel_list_, subchannel_list);
- }
- grpc_lb_subchannel_list_shutdown_and_unref(
- latest_pending_subchannel_list_, "sl_outdated");
- }
- latest_pending_subchannel_list_ = subchannel_list;
- for (size_t i = 0; i < subchannel_list->num_subchannels; ++i) {
- /* Watch every new subchannel. A subchannel list becomes active the
- * moment one of its subchannels is READY. At that moment, we swap
- * p->subchannel_list for sd->subchannel_list, provided the subchannel
- * list is still valid (ie, isn't shutting down) */
- SubchannelListRefForConnectivityWatch(subchannel_list,
- "connectivity_watch");
- grpc_lb_subchannel_data_start_connectivity_watch(
- &subchannel_list->subchannels[i]);
+ latest_pending_subchannel_list_ = MakeOrphanable<RoundRobinSubchannelList>(
+ this, &grpc_lb_round_robin_trace, addresses, combiner(),
+ client_channel_factory(), args);
+ // If we haven't started picking yet or the new list is empty,
+ // immediately promote the new list to the current list.
+ if (!started_picking_ ||
+ latest_pending_subchannel_list_->num_subchannels() == 0) {
+ if (latest_pending_subchannel_list_->num_subchannels() == 0) {
+ grpc_connectivity_state_set(
+ &state_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
+ "rr_update_empty");
}
+ subchannel_list_ = std::move(latest_pending_subchannel_list_);
} else {
- // The policy isn't picking yet. Save the update for later, disposing of
- // previous version if any.
- if (subchannel_list_ != nullptr) {
- grpc_lb_subchannel_list_shutdown_and_unref(
- subchannel_list_, "rr_update_before_started_picking");
- }
- subchannel_list_ = subchannel_list;
+ // If we've started picking, start watching the new list.
+ latest_pending_subchannel_list_->StartWatchingLocked();
}
}
diff --git a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc
deleted file mode 100644
index 79cb64c6c6..0000000000
--- a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- *
- * Copyright 2015 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <grpc/support/port_platform.h>
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-
-#include "src/core/ext/filters/client_channel/lb_policy/subchannel_list.h"
-#include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/debug/trace.h"
-#include "src/core/lib/iomgr/closure.h"
-#include "src/core/lib/iomgr/combiner.h"
-#include "src/core/lib/iomgr/sockaddr_utils.h"
-#include "src/core/lib/transport/connectivity_state.h"
-
-void grpc_lb_subchannel_data_unref_subchannel(grpc_lb_subchannel_data* sd,
- const char* reason) {
- if (sd->subchannel != nullptr) {
- if (sd->subchannel_list->tracer->enabled()) {
- gpr_log(GPR_DEBUG,
- "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
- " (subchannel %p): unreffing subchannel",
- sd->subchannel_list->tracer->name(), sd->subchannel_list->policy,
- sd->subchannel_list,
- static_cast<size_t>(sd - sd->subchannel_list->subchannels),
- sd->subchannel_list->num_subchannels, sd->subchannel);
- }
- GRPC_SUBCHANNEL_UNREF(sd->subchannel, reason);
- sd->subchannel = nullptr;
- sd->connected_subchannel.reset();
- if (sd->user_data != nullptr) {
- GPR_ASSERT(sd->user_data_vtable != nullptr);
- sd->user_data_vtable->destroy(sd->user_data);
- sd->user_data = nullptr;
- }
- }
-}
-
-void grpc_lb_subchannel_data_start_connectivity_watch(
- grpc_lb_subchannel_data* sd) {
- if (sd->subchannel_list->tracer->enabled()) {
- gpr_log(
- GPR_DEBUG,
- "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
- " (subchannel %p): requesting connectivity change "
- "notification (from %s)",
- sd->subchannel_list->tracer->name(), sd->subchannel_list->policy,
- sd->subchannel_list,
- static_cast<size_t>(sd - sd->subchannel_list->subchannels),
- sd->subchannel_list->num_subchannels, sd->subchannel,
- grpc_connectivity_state_name(sd->pending_connectivity_state_unsafe));
- }
- sd->connectivity_notification_pending = true;
- grpc_subchannel_notify_on_state_change(
- sd->subchannel, sd->subchannel_list->policy->interested_parties(),
- &sd->pending_connectivity_state_unsafe,
- &sd->connectivity_changed_closure);
-}
-
-void grpc_lb_subchannel_data_stop_connectivity_watch(
- grpc_lb_subchannel_data* sd) {
- if (sd->subchannel_list->tracer->enabled()) {
- gpr_log(GPR_DEBUG,
- "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
- " (subchannel %p): stopping connectivity watch",
- sd->subchannel_list->tracer->name(), sd->subchannel_list->policy,
- sd->subchannel_list,
- static_cast<size_t>(sd - sd->subchannel_list->subchannels),
- sd->subchannel_list->num_subchannels, sd->subchannel);
- }
- GPR_ASSERT(sd->connectivity_notification_pending);
- sd->connectivity_notification_pending = false;
-}
-
-grpc_lb_subchannel_list* grpc_lb_subchannel_list_create(
- grpc_core::LoadBalancingPolicy* p, grpc_core::TraceFlag* tracer,
- const grpc_lb_addresses* addresses, grpc_combiner* combiner,
- grpc_client_channel_factory* client_channel_factory,
- const grpc_channel_args& args, grpc_iomgr_cb_func connectivity_changed_cb) {
- grpc_lb_subchannel_list* subchannel_list =
- static_cast<grpc_lb_subchannel_list*>(
- gpr_zalloc(sizeof(*subchannel_list)));
- if (tracer->enabled()) {
- gpr_log(GPR_DEBUG,
- "[%s %p] Creating subchannel list %p for %" PRIuPTR " subchannels",
- tracer->name(), p, subchannel_list, addresses->num_addresses);
- }
- subchannel_list->policy = p;
- subchannel_list->tracer = tracer;
- gpr_ref_init(&subchannel_list->refcount, 1);
- subchannel_list->subchannels = static_cast<grpc_lb_subchannel_data*>(
- gpr_zalloc(sizeof(grpc_lb_subchannel_data) * addresses->num_addresses));
- // We need to remove the LB addresses in order to be able to compare the
- // subchannel keys of subchannels from a different batch of addresses.
- static const char* keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS,
- GRPC_ARG_LB_ADDRESSES};
- // Create a subchannel for each address.
- grpc_subchannel_args sc_args;
- size_t subchannel_index = 0;
- for (size_t i = 0; i < addresses->num_addresses; i++) {
- // If there were any balancer, we would have chosen grpclb policy instead.
- GPR_ASSERT(!addresses->addresses[i].is_balancer);
- memset(&sc_args, 0, sizeof(grpc_subchannel_args));
- grpc_arg addr_arg =
- grpc_create_subchannel_address_arg(&addresses->addresses[i].address);
- grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove(
- &args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &addr_arg, 1);
- gpr_free(addr_arg.value.string);
- sc_args.args = new_args;
- grpc_subchannel* subchannel = grpc_client_channel_factory_create_subchannel(
- client_channel_factory, &sc_args);
- grpc_channel_args_destroy(new_args);
- if (subchannel == nullptr) {
- // Subchannel could not be created.
- if (tracer->enabled()) {
- char* address_uri =
- grpc_sockaddr_to_uri(&addresses->addresses[i].address);
- gpr_log(GPR_DEBUG,
- "[%s %p] could not create subchannel for address uri %s, "
- "ignoring",
- tracer->name(), subchannel_list->policy, address_uri);
- gpr_free(address_uri);
- }
- continue;
- }
- if (tracer->enabled()) {
- char* address_uri =
- grpc_sockaddr_to_uri(&addresses->addresses[i].address);
- gpr_log(GPR_DEBUG,
- "[%s %p] subchannel list %p index %" PRIuPTR
- ": Created subchannel %p for address uri %s",
- tracer->name(), p, subchannel_list, subchannel_index, subchannel,
- address_uri);
- gpr_free(address_uri);
- }
- grpc_lb_subchannel_data* sd =
- &subchannel_list->subchannels[subchannel_index++];
- sd->subchannel_list = subchannel_list;
- sd->subchannel = subchannel;
- GRPC_CLOSURE_INIT(&sd->connectivity_changed_closure,
- connectivity_changed_cb, sd,
- grpc_combiner_scheduler(combiner));
- // We assume that the current state is IDLE. If not, we'll get a
- // callback telling us that.
- sd->prev_connectivity_state = GRPC_CHANNEL_IDLE;
- sd->curr_connectivity_state = GRPC_CHANNEL_IDLE;
- sd->pending_connectivity_state_unsafe = GRPC_CHANNEL_IDLE;
- sd->user_data_vtable = addresses->user_data_vtable;
- if (sd->user_data_vtable != nullptr) {
- sd->user_data =
- sd->user_data_vtable->copy(addresses->addresses[i].user_data);
- }
- }
- subchannel_list->num_subchannels = subchannel_index;
- subchannel_list->num_idle = subchannel_index;
- return subchannel_list;
-}
-
-static void subchannel_list_destroy(grpc_lb_subchannel_list* subchannel_list) {
- if (subchannel_list->tracer->enabled()) {
- gpr_log(GPR_DEBUG, "[%s %p] Destroying subchannel_list %p",
- subchannel_list->tracer->name(), subchannel_list->policy,
- subchannel_list);
- }
- for (size_t i = 0; i < subchannel_list->num_subchannels; i++) {
- grpc_lb_subchannel_data* sd = &subchannel_list->subchannels[i];
- grpc_lb_subchannel_data_unref_subchannel(sd, "subchannel_list_destroy");
- }
- gpr_free(subchannel_list->subchannels);
- gpr_free(subchannel_list);
-}
-
-void grpc_lb_subchannel_list_ref(grpc_lb_subchannel_list* subchannel_list,
- const char* reason) {
- gpr_ref_non_zero(&subchannel_list->refcount);
- if (subchannel_list->tracer->enabled()) {
- const gpr_atm count = gpr_atm_acq_load(&subchannel_list->refcount.count);
- gpr_log(GPR_DEBUG, "[%s %p] subchannel_list %p REF %lu->%lu (%s)",
- subchannel_list->tracer->name(), subchannel_list->policy,
- subchannel_list, static_cast<unsigned long>(count - 1),
- static_cast<unsigned long>(count), reason);
- }
-}
-
-void grpc_lb_subchannel_list_unref(grpc_lb_subchannel_list* subchannel_list,
- const char* reason) {
- const bool done = gpr_unref(&subchannel_list->refcount);
- if (subchannel_list->tracer->enabled()) {
- const gpr_atm count = gpr_atm_acq_load(&subchannel_list->refcount.count);
- gpr_log(GPR_DEBUG, "[%s %p] subchannel_list %p UNREF %lu->%lu (%s)",
- subchannel_list->tracer->name(), subchannel_list->policy,
- subchannel_list, static_cast<unsigned long>(count + 1),
- static_cast<unsigned long>(count), reason);
- }
- if (done) {
- subchannel_list_destroy(subchannel_list);
- }
-}
-
-static void subchannel_data_cancel_connectivity_watch(
- grpc_lb_subchannel_data* sd, const char* reason) {
- if (sd->subchannel_list->tracer->enabled()) {
- gpr_log(GPR_DEBUG,
- "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
- " (subchannel %p): canceling connectivity watch (%s)",
- sd->subchannel_list->tracer->name(), sd->subchannel_list->policy,
- sd->subchannel_list,
- static_cast<size_t>(sd - sd->subchannel_list->subchannels),
- sd->subchannel_list->num_subchannels, sd->subchannel, reason);
- }
- grpc_subchannel_notify_on_state_change(sd->subchannel, nullptr, nullptr,
- &sd->connectivity_changed_closure);
-}
-
-void grpc_lb_subchannel_list_shutdown_and_unref(
- grpc_lb_subchannel_list* subchannel_list, const char* reason) {
- if (subchannel_list->tracer->enabled()) {
- gpr_log(GPR_DEBUG, "[%s %p] Shutting down subchannel_list %p (%s)",
- subchannel_list->tracer->name(), subchannel_list->policy,
- subchannel_list, reason);
- }
- GPR_ASSERT(!subchannel_list->shutting_down);
- subchannel_list->shutting_down = true;
- for (size_t i = 0; i < subchannel_list->num_subchannels; i++) {
- grpc_lb_subchannel_data* sd = &subchannel_list->subchannels[i];
- // If there's a pending notification for this subchannel, cancel it;
- // the callback is responsible for unreffing the subchannel.
- // Otherwise, unref the subchannel directly.
- if (sd->connectivity_notification_pending) {
- subchannel_data_cancel_connectivity_watch(sd, reason);
- } else if (sd->subchannel != nullptr) {
- grpc_lb_subchannel_data_unref_subchannel(sd, reason);
- }
- }
- grpc_lb_subchannel_list_unref(subchannel_list, reason);
-}
diff --git a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
index 6889d596ac..7e2046bcdc 100644
--- a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
+++ b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
@@ -21,116 +21,516 @@
#include <grpc/support/port_platform.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+
#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
#include "src/core/ext/filters/client_channel/subchannel.h"
+#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/debug/trace.h"
+#include "src/core/lib/gprpp/abstract.h"
+#include "src/core/lib/gprpp/inlined_vector.h"
+#include "src/core/lib/gprpp/orphanable.h"
+#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/iomgr/closure.h"
+#include "src/core/lib/iomgr/combiner.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/transport/connectivity_state.h"
-// TODO(roth): This code is intended to be shared between pick_first and
-// round_robin. However, the interface needs more work to provide clean
-// encapsulation. For example, the structs here have some fields that are
-// only used in one of the two (e.g., the state counters in
-// grpc_lb_subchannel_list and the prev_connectivity_state field in
-// grpc_lb_subchannel_data are only used in round_robin, and the
-// checking_subchannel field in grpc_lb_subchannel_list is only used by
-// pick_first). Also, there is probably some code duplication between the
-// connectivity state notification callback code in both pick_first and
-// round_robin that could be refactored and moved here. In a future PR,
-// need to clean this up.
-
-typedef struct grpc_lb_subchannel_list grpc_lb_subchannel_list;
-
-typedef struct {
- /** backpointer to owning subchannel list */
- grpc_lb_subchannel_list* subchannel_list;
- /** subchannel itself */
- grpc_subchannel* subchannel;
- grpc_core::RefCountedPtr<grpc_core::ConnectedSubchannel> connected_subchannel;
- /** Is a connectivity notification pending? */
- bool connectivity_notification_pending;
- /** notification that connectivity has changed on subchannel */
- grpc_closure connectivity_changed_closure;
- /** previous and current connectivity states. Updated by \a
- * \a connectivity_changed_closure based on
- * \a pending_connectivity_state_unsafe. */
- grpc_connectivity_state prev_connectivity_state;
- grpc_connectivity_state curr_connectivity_state;
- /** connectivity state to be updated by
- * grpc_subchannel_notify_on_state_change(), not guarded by
- * the combiner. To be copied to \a curr_connectivity_state by
- * \a connectivity_changed_closure. */
- grpc_connectivity_state pending_connectivity_state_unsafe;
- /** the subchannel's target user data */
- void* user_data;
- /** vtable to operate over \a user_data */
- const grpc_lb_user_data_vtable* user_data_vtable;
-} grpc_lb_subchannel_data;
-
-/// Unrefs the subchannel contained in sd.
-void grpc_lb_subchannel_data_unref_subchannel(grpc_lb_subchannel_data* sd,
- const char* reason);
-
-/// Starts watching the connectivity state of the subchannel.
-/// The connectivity_changed_cb callback must invoke either
-/// grpc_lb_subchannel_data_stop_connectivity_watch() or again call
-/// grpc_lb_subchannel_data_start_connectivity_watch().
-void grpc_lb_subchannel_data_start_connectivity_watch(
- grpc_lb_subchannel_data* sd);
-
-/// Stops watching the connectivity state of the subchannel.
-void grpc_lb_subchannel_data_stop_connectivity_watch(
- grpc_lb_subchannel_data* sd);
-
-struct grpc_lb_subchannel_list {
- /** backpointer to owning policy */
- grpc_core::LoadBalancingPolicy* policy;
-
- grpc_core::TraceFlag* tracer;
-
- /** all our subchannels */
- size_t num_subchannels;
- grpc_lb_subchannel_data* subchannels;
-
- /** Index into subchannels of the one we're currently checking.
- * Used when connecting to subchannels serially instead of in parallel. */
- // TODO(roth): When we have time, we can probably make this go away
- // and compute the index dynamically by subtracting
- // subchannel_list->subchannels from the subchannel_data pointer.
- size_t checking_subchannel;
-
- /** how many subchannels are in state READY */
- size_t num_ready;
- /** how many subchannels are in state TRANSIENT_FAILURE */
- size_t num_transient_failures;
- /** how many subchannels are in state IDLE */
- size_t num_idle;
-
- /** There will be one ref for each entry in subchannels for which there is a
- * pending connectivity state watcher callback. */
- gpr_refcount refcount;
-
- /** Is this list shutting down? This may be true due to the shutdown of the
- * policy itself or because a newer update has arrived while this one hadn't
- * finished processing. */
- bool shutting_down;
+// Code for maintaining a list of subchannels within an LB policy.
+//
+// To use this, callers must create their own subclasses, like so:
+/*
+
+class MySubchannelList; // Forward declaration.
+
+class MySubchannelData
+ : public SubchannelData<MySubchannelList, MySubchannelData> {
+ public:
+ void ProcessConnectivityChangeLocked(
+ grpc_connectivity_state connectivity_state, grpc_error* error) override {
+ // ...code to handle connectivity changes...
+ }
+};
+
+class MySubchannelList
+ : public SubchannelList<MySubchannelList, MySubchannelData> {
};
-grpc_lb_subchannel_list* grpc_lb_subchannel_list_create(
- grpc_core::LoadBalancingPolicy* p, grpc_core::TraceFlag* tracer,
+*/
+// All methods with a Locked() suffix must be called from within the
+// client_channel combiner.
+
+namespace grpc_core {
+
+// Stores data for a particular subchannel in a subchannel list.
+// Callers must create a subclass that implements the
+// ProcessConnectivityChangeLocked() method.
+template <typename SubchannelListType, typename SubchannelDataType>
+class SubchannelData {
+ public:
+ // Returns a pointer to the subchannel list containing this object.
+ SubchannelListType* subchannel_list() const { return subchannel_list_; }
+
+ // Returns the index into the subchannel list of this object.
+ size_t Index() const {
+ return static_cast<size_t>(static_cast<const SubchannelDataType*>(this) -
+ subchannel_list_->subchannel(0));
+ }
+
+ // Returns a pointer to the subchannel.
+ grpc_subchannel* subchannel() const { return subchannel_; }
+
+ // Returns the connected subchannel. Will be null if the subchannel
+ // is not connected.
+ ConnectedSubchannel* connected_subchannel() const {
+ return connected_subchannel_.get();
+ }
+
+ // Synchronously checks the subchannel's connectivity state.
+ // Must not be called while there is a connectivity notification
+ // pending (i.e., between calling StartConnectivityWatchLocked() or
+ // RenewConnectivityWatchLocked() and the resulting invocation of
+ // ProcessConnectivityChangeLocked()).
+ grpc_connectivity_state CheckConnectivityStateLocked(grpc_error** error) {
+ GPR_ASSERT(!connectivity_notification_pending_);
+ pending_connectivity_state_unsafe_ =
+ grpc_subchannel_check_connectivity(subchannel(), error);
+ UpdateConnectedSubchannelLocked();
+ return pending_connectivity_state_unsafe_;
+ }
+
+ // Unrefs the subchannel. May be used if an individual subchannel is
+ // no longer needed even though the subchannel list as a whole is not
+ // being unreffed.
+ virtual void UnrefSubchannelLocked(const char* reason);
+
+ // Starts watching the connectivity state of the subchannel.
+ // ProcessConnectivityChangeLocked() will be called when the
+ // connectivity state changes.
+ void StartConnectivityWatchLocked();
+
+ // Renews watching the connectivity state of the subchannel.
+ void RenewConnectivityWatchLocked();
+
+ // Stops watching the connectivity state of the subchannel.
+ void StopConnectivityWatchLocked();
+
+ // Cancels watching the connectivity state of the subchannel.
+ // Must be called only while there is a connectivity notification
+ // pending (i.e., between calling StartConnectivityWatchLocked() or
+ // RenewConnectivityWatchLocked() and the resulting invocation of
+ // ProcessConnectivityChangeLocked()).
+ // From within ProcessConnectivityChangeLocked(), use
+ // StopConnectivityWatchLocked() instead.
+ void CancelConnectivityWatchLocked(const char* reason);
+
+ // Cancels any pending connectivity watch and unrefs the subchannel.
+ void ShutdownLocked();
+
+ GRPC_ABSTRACT_BASE_CLASS
+
+ protected:
+ SubchannelData(SubchannelListType* subchannel_list,
+ const grpc_lb_user_data_vtable* user_data_vtable,
+ const grpc_lb_address& address, grpc_subchannel* subchannel,
+ grpc_combiner* combiner);
+
+ virtual ~SubchannelData();
+
+ // After StartConnectivityWatchLocked() or RenewConnectivityWatchLocked()
+ // is called, this method will be invoked when the subchannel's connectivity
+ // state changes.
+ // Implementations must invoke either RenewConnectivityWatchLocked() or
+ // StopConnectivityWatchLocked() before returning.
+ virtual void ProcessConnectivityChangeLocked(
+ grpc_connectivity_state connectivity_state,
+ grpc_error* error) GRPC_ABSTRACT;
+
+ private:
+ // Updates connected_subchannel_ based on pending_connectivity_state_unsafe_.
+ // Returns true if the connectivity state should be reported.
+ bool UpdateConnectedSubchannelLocked();
+
+ static void OnConnectivityChangedLocked(void* arg, grpc_error* error);
+
+ // Backpointer to owning subchannel list. Not owned.
+ SubchannelListType* subchannel_list_;
+
+ // The subchannel and connected subchannel.
+ grpc_subchannel* subchannel_;
+ RefCountedPtr<ConnectedSubchannel> connected_subchannel_;
+
+ // Notification that connectivity has changed on subchannel.
+ grpc_closure connectivity_changed_closure_;
+ // Is a connectivity notification pending?
+ bool connectivity_notification_pending_ = false;
+ // Connectivity state to be updated by
+ // grpc_subchannel_notify_on_state_change(), not guarded by
+ // the combiner.
+ grpc_connectivity_state pending_connectivity_state_unsafe_;
+};
+
+// A list of subchannels.
+template <typename SubchannelListType, typename SubchannelDataType>
+class SubchannelList
+ : public InternallyRefCountedWithTracing<SubchannelListType> {
+ public:
+ typedef InlinedVector<SubchannelDataType, 10> SubchannelVector;
+
+ // The number of subchannels in the list.
+ size_t num_subchannels() const { return subchannels_.size(); }
+
+ // The data for the subchannel at a particular index.
+ SubchannelDataType* subchannel(size_t index) { return &subchannels_[index]; }
+
+ // Returns true if the subchannel list is shutting down.
+ bool shutting_down() const { return shutting_down_; }
+
+ // Accessors.
+ LoadBalancingPolicy* policy() const { return policy_; }
+ TraceFlag* tracer() const { return tracer_; }
+
+ // Note: Caller must ensure that this is invoked inside of the combiner.
+ void Orphan() override {
+ ShutdownLocked();
+ InternallyRefCountedWithTracing<SubchannelListType>::Unref(DEBUG_LOCATION,
+ "shutdown");
+ }
+
+ GRPC_ABSTRACT_BASE_CLASS
+
+ protected:
+ SubchannelList(LoadBalancingPolicy* policy, TraceFlag* tracer,
+ const grpc_lb_addresses* addresses, grpc_combiner* combiner,
+ grpc_client_channel_factory* client_channel_factory,
+ const grpc_channel_args& args);
+
+ virtual ~SubchannelList();
+
+ private:
+ // So New() can call our private ctor.
+ template <typename T, typename... Args>
+ friend T* New(Args&&... args);
+
+ // For accessing Ref() and Unref().
+ friend class SubchannelData<SubchannelListType, SubchannelDataType>;
+
+ void ShutdownLocked();
+
+ // Backpointer to owning policy.
+ LoadBalancingPolicy* policy_;
+
+ TraceFlag* tracer_;
+
+ grpc_combiner* combiner_;
+
+ // The list of subchannels.
+ SubchannelVector subchannels_;
+
+ // Is this list shutting down? This may be true due to the shutdown of the
+ // policy itself or because a newer update has arrived while this one hadn't
+ // finished processing.
+ bool shutting_down_ = false;
+};
+
+//
+// implementation -- no user-servicable parts below
+//
+
+//
+// SubchannelData
+//
+
+template <typename SubchannelListType, typename SubchannelDataType>
+SubchannelData<SubchannelListType, SubchannelDataType>::SubchannelData(
+ SubchannelListType* subchannel_list,
+ const grpc_lb_user_data_vtable* user_data_vtable,
+ const grpc_lb_address& address, grpc_subchannel* subchannel,
+ grpc_combiner* combiner)
+ : subchannel_list_(subchannel_list),
+ subchannel_(subchannel),
+ // We assume that the current state is IDLE. If not, we'll get a
+ // callback telling us that.
+ pending_connectivity_state_unsafe_(GRPC_CHANNEL_IDLE) {
+ GRPC_CLOSURE_INIT(
+ &connectivity_changed_closure_,
+ (&SubchannelData<SubchannelListType,
+ SubchannelDataType>::OnConnectivityChangedLocked),
+ this, grpc_combiner_scheduler(combiner));
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+SubchannelData<SubchannelListType, SubchannelDataType>::~SubchannelData() {
+ UnrefSubchannelLocked("subchannel_data_destroy");
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+void SubchannelData<SubchannelListType, SubchannelDataType>::
+ UnrefSubchannelLocked(const char* reason) {
+ if (subchannel_ != nullptr) {
+ if (subchannel_list_->tracer()->enabled()) {
+ gpr_log(GPR_INFO,
+ "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
+ " (subchannel %p): unreffing subchannel",
+ subchannel_list_->tracer()->name(), subchannel_list_->policy(),
+ subchannel_list_, Index(), subchannel_list_->num_subchannels(),
+ subchannel_);
+ }
+ GRPC_SUBCHANNEL_UNREF(subchannel_, reason);
+ subchannel_ = nullptr;
+ connected_subchannel_.reset();
+ }
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+void SubchannelData<SubchannelListType,
+ SubchannelDataType>::StartConnectivityWatchLocked() {
+ if (subchannel_list_->tracer()->enabled()) {
+ gpr_log(GPR_INFO,
+ "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
+ " (subchannel %p): starting watch: requesting connectivity change "
+ "notification (from %s)",
+ subchannel_list_->tracer()->name(), subchannel_list_->policy(),
+ subchannel_list_, Index(), subchannel_list_->num_subchannels(),
+ subchannel_,
+ grpc_connectivity_state_name(pending_connectivity_state_unsafe_));
+ }
+ GPR_ASSERT(!connectivity_notification_pending_);
+ connectivity_notification_pending_ = true;
+ subchannel_list()->Ref(DEBUG_LOCATION, "connectivity_watch").release();
+ grpc_subchannel_notify_on_state_change(
+ subchannel_, subchannel_list_->policy()->interested_parties(),
+ &pending_connectivity_state_unsafe_, &connectivity_changed_closure_);
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+void SubchannelData<SubchannelListType,
+ SubchannelDataType>::RenewConnectivityWatchLocked() {
+ if (subchannel_list_->tracer()->enabled()) {
+ gpr_log(GPR_INFO,
+ "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
+ " (subchannel %p): renewing watch: requesting connectivity change "
+ "notification (from %s)",
+ subchannel_list_->tracer()->name(), subchannel_list_->policy(),
+ subchannel_list_, Index(), subchannel_list_->num_subchannels(),
+ subchannel_,
+ grpc_connectivity_state_name(pending_connectivity_state_unsafe_));
+ }
+ GPR_ASSERT(connectivity_notification_pending_);
+ grpc_subchannel_notify_on_state_change(
+ subchannel_, subchannel_list_->policy()->interested_parties(),
+ &pending_connectivity_state_unsafe_, &connectivity_changed_closure_);
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+void SubchannelData<SubchannelListType,
+ SubchannelDataType>::StopConnectivityWatchLocked() {
+ if (subchannel_list_->tracer()->enabled()) {
+ gpr_log(GPR_INFO,
+ "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
+ " (subchannel %p): stopping connectivity watch",
+ subchannel_list_->tracer()->name(), subchannel_list_->policy(),
+ subchannel_list_, Index(), subchannel_list_->num_subchannels(),
+ subchannel_);
+ }
+ GPR_ASSERT(connectivity_notification_pending_);
+ connectivity_notification_pending_ = false;
+ subchannel_list()->Unref(DEBUG_LOCATION, "connectivity_watch");
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+void SubchannelData<SubchannelListType, SubchannelDataType>::
+ CancelConnectivityWatchLocked(const char* reason) {
+ if (subchannel_list_->tracer()->enabled()) {
+ gpr_log(GPR_INFO,
+ "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
+ " (subchannel %p): canceling connectivity watch (%s)",
+ subchannel_list_->tracer()->name(), subchannel_list_->policy(),
+ subchannel_list_, Index(), subchannel_list_->num_subchannels(),
+ subchannel_, reason);
+ }
+ GPR_ASSERT(connectivity_notification_pending_);
+ grpc_subchannel_notify_on_state_change(subchannel_, nullptr, nullptr,
+ &connectivity_changed_closure_);
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+bool SubchannelData<SubchannelListType,
+ SubchannelDataType>::UpdateConnectedSubchannelLocked() {
+ // If the subchannel is READY, take a ref to the connected subchannel.
+ if (pending_connectivity_state_unsafe_ == GRPC_CHANNEL_READY) {
+ connected_subchannel_ =
+ grpc_subchannel_get_connected_subchannel(subchannel_);
+ // If the subchannel became disconnected between the time that READY
+ // was reported and the time we got here (e.g., between when a
+ // notification callback is scheduled and when it was actually run in
+ // the combiner), then the connected subchannel may have disappeared out
+ // from under us. In that case, we don't actually want to consider the
+ // subchannel to be in state READY. Instead, we use IDLE as the
+ // basis for any future connectivity watch; this is the one state that
+ // the subchannel will never transition back into, so this ensures
+ // that we will get a notification for the next state, even if that state
+ // is READY again (e.g., if the subchannel has transitioned back to
+ // READY before the next watch gets requested).
+ if (connected_subchannel_ == nullptr) {
+ if (subchannel_list_->tracer()->enabled()) {
+ gpr_log(GPR_INFO,
+ "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
+ " (subchannel %p): state is READY but connected subchannel is "
+ "null; moving to state IDLE",
+ subchannel_list_->tracer()->name(), subchannel_list_->policy(),
+ subchannel_list_, Index(), subchannel_list_->num_subchannels(),
+ subchannel_);
+ }
+ pending_connectivity_state_unsafe_ = GRPC_CHANNEL_IDLE;
+ return false;
+ }
+ } else {
+ // For any state other than READY, unref the connected subchannel.
+ connected_subchannel_.reset();
+ }
+ return true;
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+void SubchannelData<SubchannelListType, SubchannelDataType>::
+ OnConnectivityChangedLocked(void* arg, grpc_error* error) {
+ SubchannelData* sd = static_cast<SubchannelData*>(arg);
+ if (sd->subchannel_list_->tracer()->enabled()) {
+ gpr_log(
+ GPR_INFO,
+ "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
+ " (subchannel %p): connectivity changed: state=%s, error=%s, "
+ "shutting_down=%d",
+ sd->subchannel_list_->tracer()->name(), sd->subchannel_list_->policy(),
+ sd->subchannel_list_, sd->Index(),
+ sd->subchannel_list_->num_subchannels(), sd->subchannel_,
+ grpc_connectivity_state_name(sd->pending_connectivity_state_unsafe_),
+ grpc_error_string(error), sd->subchannel_list_->shutting_down());
+ }
+ // If shutting down, unref subchannel and stop watching.
+ if (sd->subchannel_list_->shutting_down() || error == GRPC_ERROR_CANCELLED) {
+ sd->UnrefSubchannelLocked("connectivity_shutdown");
+ sd->StopConnectivityWatchLocked();
+ return;
+ }
+ // Get or release ref to connected subchannel.
+ if (!sd->UpdateConnectedSubchannelLocked()) {
+ // We don't want to report this connectivity state, so renew the watch.
+ sd->RenewConnectivityWatchLocked();
+ return;
+ }
+ // Call the subclass's ProcessConnectivityChangeLocked() method.
+ sd->ProcessConnectivityChangeLocked(sd->pending_connectivity_state_unsafe_,
+ GRPC_ERROR_REF(error));
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+void SubchannelData<SubchannelListType, SubchannelDataType>::ShutdownLocked() {
+ // If there's a pending notification for this subchannel, cancel it;
+ // the callback is responsible for unreffing the subchannel.
+ // Otherwise, unref the subchannel directly.
+ if (connectivity_notification_pending_) {
+ CancelConnectivityWatchLocked("shutdown");
+ } else if (subchannel_ != nullptr) {
+ UnrefSubchannelLocked("shutdown");
+ }
+}
+
+//
+// SubchannelList
+//
+
+template <typename SubchannelListType, typename SubchannelDataType>
+SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList(
+ LoadBalancingPolicy* policy, TraceFlag* tracer,
const grpc_lb_addresses* addresses, grpc_combiner* combiner,
grpc_client_channel_factory* client_channel_factory,
- const grpc_channel_args& args, grpc_iomgr_cb_func connectivity_changed_cb);
+ const grpc_channel_args& args)
+ : InternallyRefCountedWithTracing<SubchannelListType>(tracer),
+ policy_(policy),
+ tracer_(tracer),
+ combiner_(GRPC_COMBINER_REF(combiner, "subchannel_list")) {
+ if (tracer_->enabled()) {
+ gpr_log(GPR_INFO,
+ "[%s %p] Creating subchannel list %p for %" PRIuPTR " subchannels",
+ tracer_->name(), policy, this, addresses->num_addresses);
+ }
+ subchannels_.reserve(addresses->num_addresses);
+ // We need to remove the LB addresses in order to be able to compare the
+ // subchannel keys of subchannels from a different batch of addresses.
+ static const char* keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS,
+ GRPC_ARG_LB_ADDRESSES};
+ // Create a subchannel for each address.
+ grpc_subchannel_args sc_args;
+ for (size_t i = 0; i < addresses->num_addresses; i++) {
+ // If there were any balancer, we would have chosen grpclb policy instead.
+ GPR_ASSERT(!addresses->addresses[i].is_balancer);
+ memset(&sc_args, 0, sizeof(grpc_subchannel_args));
+ grpc_arg addr_arg =
+ grpc_create_subchannel_address_arg(&addresses->addresses[i].address);
+ grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove(
+ &args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &addr_arg, 1);
+ gpr_free(addr_arg.value.string);
+ sc_args.args = new_args;
+ grpc_subchannel* subchannel = grpc_client_channel_factory_create_subchannel(
+ client_channel_factory, &sc_args);
+ grpc_channel_args_destroy(new_args);
+ if (subchannel == nullptr) {
+ // Subchannel could not be created.
+ if (tracer_->enabled()) {
+ char* address_uri =
+ grpc_sockaddr_to_uri(&addresses->addresses[i].address);
+ gpr_log(GPR_INFO,
+ "[%s %p] could not create subchannel for address uri %s, "
+ "ignoring",
+ tracer_->name(), policy_, address_uri);
+ gpr_free(address_uri);
+ }
+ continue;
+ }
+ if (tracer_->enabled()) {
+ char* address_uri =
+ grpc_sockaddr_to_uri(&addresses->addresses[i].address);
+ gpr_log(GPR_INFO,
+ "[%s %p] subchannel list %p index %" PRIuPTR
+ ": Created subchannel %p for address uri %s",
+ tracer_->name(), policy_, this, subchannels_.size(), subchannel,
+ address_uri);
+ gpr_free(address_uri);
+ }
+ subchannels_.emplace_back(static_cast<SubchannelListType*>(this),
+ addresses->user_data_vtable,
+ addresses->addresses[i], subchannel, combiner);
+ }
+}
-void grpc_lb_subchannel_list_ref(grpc_lb_subchannel_list* subchannel_list,
- const char* reason);
+template <typename SubchannelListType, typename SubchannelDataType>
+SubchannelList<SubchannelListType, SubchannelDataType>::~SubchannelList() {
+ if (tracer_->enabled()) {
+ gpr_log(GPR_INFO, "[%s %p] Destroying subchannel_list %p", tracer_->name(),
+ policy_, this);
+ }
+ GRPC_COMBINER_UNREF(combiner_, "subchannel_list");
+}
-void grpc_lb_subchannel_list_unref(grpc_lb_subchannel_list* subchannel_list,
- const char* reason);
+template <typename SubchannelListType, typename SubchannelDataType>
+void SubchannelList<SubchannelListType, SubchannelDataType>::ShutdownLocked() {
+ if (tracer_->enabled()) {
+ gpr_log(GPR_INFO, "[%s %p] Shutting down subchannel_list %p",
+ tracer_->name(), policy_, this);
+ }
+ GPR_ASSERT(!shutting_down_);
+ shutting_down_ = true;
+ for (size_t i = 0; i < subchannels_.size(); i++) {
+ SubchannelDataType* sd = &subchannels_[i];
+ sd->ShutdownLocked();
+ }
+}
-/// Mark subchannel_list as discarded. Unsubscribes all its subchannels. The
-/// connectivity state notification callback will ultimately unref it.
-void grpc_lb_subchannel_list_shutdown_and_unref(
- grpc_lb_subchannel_list* subchannel_list, const char* reason);
+} // namespace grpc_core
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_SUBCHANNEL_LIST_H */
diff --git a/src/core/ext/filters/client_channel/method_params.h b/src/core/ext/filters/client_channel/method_params.h
index 099924edf3..a31d360f17 100644
--- a/src/core/ext/filters/client_channel/method_params.h
+++ b/src/core/ext/filters/client_channel/method_params.h
@@ -60,6 +60,10 @@ class ClientChannelMethodParams : public RefCounted<ClientChannelMethodParams> {
template <typename T, typename... Args>
friend T* grpc_core::New(Args&&... args);
+ // So Delete() can call our private dtor.
+ template <typename T>
+ friend void grpc_core::Delete(T*);
+
ClientChannelMethodParams() {}
virtual ~ClientChannelMethodParams() {}
diff --git a/src/core/ext/filters/client_channel/resolver.h b/src/core/ext/filters/client_channel/resolver.h
index cdb5a20ea3..c7e37e4468 100644
--- a/src/core/ext/filters/client_channel/resolver.h
+++ b/src/core/ext/filters/client_channel/resolver.h
@@ -105,6 +105,8 @@ class Resolver : public InternallyRefCountedWithTracing<Resolver> {
GRPC_ABSTRACT_BASE_CLASS
protected:
+ GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
+
/// Does NOT take ownership of the reference to \a combiner.
// TODO(roth): Once we have a C++-like interface for combiners, this
// API should change to take a RefCountedPtr<>, so that we always take
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
index 6ac9a77635..c3c62b60bf 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
@@ -363,6 +363,15 @@ void AresDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) {
}
void AresDnsResolver::MaybeStartResolvingLocked() {
+ // If there is an existing timer, the time it fires is the earliest time we
+ // can start the next resolution.
+ if (have_next_resolution_timer_) {
+ // TODO(dgq): remove the following two lines once Pick First stops
+ // discarding subchannels after selecting.
+ ++resolved_version_;
+ MaybeFinishNextLocked();
+ return;
+ }
if (last_resolution_timestamp_ >= 0) {
const grpc_millis earliest_next_resolution =
last_resolution_timestamp_ + min_time_between_resolutions_;
@@ -375,17 +384,15 @@ void AresDnsResolver::MaybeStartResolvingLocked() {
"In cooldown from last resolution (from %" PRIdPTR
" ms ago). Will resolve again in %" PRIdPTR " ms",
last_resolution_ago, ms_until_next_resolution);
- if (!have_next_resolution_timer_) {
- have_next_resolution_timer_ = true;
- // TODO(roth): We currently deal with this ref manually. Once the
- // new closure API is done, find a way to track this ref with the timer
- // callback as part of the type system.
- RefCountedPtr<Resolver> self =
- Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown");
- self.release();
- grpc_timer_init(&next_resolution_timer_, ms_until_next_resolution,
- &on_next_resolution_);
- }
+ have_next_resolution_timer_ = true;
+ // TODO(roth): We currently deal with this ref manually. Once the
+ // new closure API is done, find a way to track this ref with the timer
+ // callback as part of the type system.
+ RefCountedPtr<Resolver> self =
+ Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown");
+ self.release();
+ grpc_timer_init(&next_resolution_timer_, ms_until_next_resolution,
+ &on_next_resolution_);
// TODO(dgq): remove the following two lines once Pick First stops
// discarding subchannels after selecting.
++resolved_version_;
@@ -397,6 +404,7 @@ void AresDnsResolver::MaybeStartResolvingLocked() {
}
void AresDnsResolver::StartResolvingLocked() {
+ gpr_log(GPR_DEBUG, "Start resolving.");
// TODO(roth): We currently deal with this ref manually. Once the
// new closure API is done, find a way to track this ref with the timer
// callback as part of the type system.
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
index e86ab5a37e..18d0a7b9f6 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
@@ -270,7 +270,6 @@ static void on_hostbyname_done_cb(void* arg, int status, int timeouts,
static void on_srv_query_done_cb(void* arg, int status, int timeouts,
unsigned char* abuf, int alen) {
grpc_ares_request* r = static_cast<grpc_ares_request*>(arg);
- grpc_core::ExecCtx exec_ctx;
gpr_log(GPR_DEBUG, "on_query_srv_done_cb");
if (status == ARES_SUCCESS) {
gpr_log(GPR_DEBUG, "on_query_srv_done_cb ARES_SUCCESS");
diff --git a/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc b/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
index fbab136421..920a492fdb 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
+++ b/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
@@ -236,6 +236,15 @@ void NativeDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) {
}
void NativeDnsResolver::MaybeStartResolvingLocked() {
+ // If there is an existing timer, the time it fires is the earliest time we
+ // can start the next resolution.
+ if (have_next_resolution_timer_) {
+ // TODO(dgq): remove the following two lines once Pick First stops
+ // discarding subchannels after selecting.
+ ++resolved_version_;
+ MaybeFinishNextLocked();
+ return;
+ }
if (last_resolution_timestamp_ >= 0) {
const grpc_millis earliest_next_resolution =
last_resolution_timestamp_ + min_time_between_resolutions_;
@@ -248,17 +257,15 @@ void NativeDnsResolver::MaybeStartResolvingLocked() {
"In cooldown from last resolution (from %" PRIdPTR
" ms ago). Will resolve again in %" PRIdPTR " ms",
last_resolution_ago, ms_until_next_resolution);
- if (!have_next_resolution_timer_) {
- have_next_resolution_timer_ = true;
- // TODO(roth): We currently deal with this ref manually. Once the
- // new closure API is done, find a way to track this ref with the timer
- // callback as part of the type system.
- RefCountedPtr<Resolver> self =
- Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown");
- self.release();
- grpc_timer_init(&next_resolution_timer_, ms_until_next_resolution,
- &on_next_resolution_);
- }
+ have_next_resolution_timer_ = true;
+ // TODO(roth): We currently deal with this ref manually. Once the
+ // new closure API is done, find a way to track this ref with the timer
+ // callback as part of the type system.
+ RefCountedPtr<Resolver> self =
+ Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown");
+ self.release();
+ grpc_timer_init(&next_resolution_timer_, ms_until_next_resolution,
+ &on_next_resolution_);
// TODO(dgq): remove the following two lines once Pick First stops
// discarding subchannels after selecting.
++resolved_version_;
@@ -270,6 +277,7 @@ void NativeDnsResolver::MaybeStartResolvingLocked() {
}
void NativeDnsResolver::StartResolvingLocked() {
+ gpr_log(GPR_DEBUG, "Start resolving.");
// TODO(roth): We currently deal with this ref manually. Once the
// new closure API is done, find a way to track this ref with the timer
// callback as part of the type system.
@@ -302,7 +310,7 @@ class NativeDnsResolverFactory : public ResolverFactory {
public:
OrphanablePtr<Resolver> CreateResolver(
const ResolverArgs& args) const override {
- if (0 != strcmp(args.uri->authority, "")) {
+ if (GPR_UNLIKELY(0 != strcmp(args.uri->authority, ""))) {
gpr_log(GPR_ERROR, "authority based dns uri's not supported");
return OrphanablePtr<Resolver>(nullptr);
}
diff --git a/src/core/ext/filters/client_channel/retry_throttle.h b/src/core/ext/filters/client_channel/retry_throttle.h
index 2b6fa0a70b..fddafcd903 100644
--- a/src/core/ext/filters/client_channel/retry_throttle.h
+++ b/src/core/ext/filters/client_channel/retry_throttle.h
@@ -42,6 +42,10 @@ class ServerRetryThrottleData : public RefCounted<ServerRetryThrottleData> {
intptr_t milli_token_ratio() const { return milli_token_ratio_; }
private:
+ // So Delete() can call our private dtor.
+ template <typename T>
+ friend void grpc_core::Delete(T*);
+
~ServerRetryThrottleData();
void GetReplacementThrottleDataIfNeeded(
diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc
index d7815fb7e1..ad6b6dd192 100644
--- a/src/core/ext/filters/client_channel/subchannel.cc
+++ b/src/core/ext/filters/client_channel/subchannel.cc
@@ -408,7 +408,7 @@ static void on_external_state_watcher_done(void* arg, grpc_error* error) {
gpr_mu_unlock(&w->subchannel->mu);
GRPC_SUBCHANNEL_WEAK_UNREF(w->subchannel, "external_state_watcher");
gpr_free(w);
- GRPC_CLOSURE_RUN(follow_up, GRPC_ERROR_REF(error));
+ GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error));
}
static void on_alarm(void* arg, grpc_error* error) {
@@ -803,7 +803,7 @@ grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args,
};
grpc_error* error = grpc_call_stack_init(
channel_stack_, 1, subchannel_call_destroy, *call, &call_args);
- if (error != GRPC_ERROR_NONE) {
+ if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) {
const char* error_string = grpc_error_string(error);
gpr_log(GPR_ERROR, "error: %s", error_string);
return error;
diff --git a/src/core/ext/filters/http/client_authority_filter.cc b/src/core/ext/filters/http/client_authority_filter.cc
index 1f57ab5ce6..ddc939ed12 100644
--- a/src/core/ext/filters/http/client_authority_filter.cc
+++ b/src/core/ext/filters/http/client_authority_filter.cc
@@ -59,8 +59,9 @@ void authority_start_transport_stream_op_batch(
initial_metadata->idx.named.authority == nullptr) {
grpc_error* error = grpc_metadata_batch_add_head(
initial_metadata, &calld->authority_storage,
- grpc_mdelem_from_slices(GRPC_MDSTR_AUTHORITY,
- grpc_slice_ref(chand->default_authority)));
+ grpc_mdelem_from_slices(
+ GRPC_MDSTR_AUTHORITY,
+ grpc_slice_ref_internal(chand->default_authority)));
if (error != GRPC_ERROR_NONE) {
grpc_transport_stream_op_batch_finish_with_failure(batch, error,
calld->call_combiner);
@@ -102,7 +103,7 @@ grpc_error* init_channel_elem(grpc_channel_element* elem,
"GRPC_ARG_DEFAULT_AUTHORITY channel arg. must be a string");
}
chand->default_authority =
- grpc_slice_from_copied_string(default_authority_str);
+ grpc_slice_intern(grpc_slice_from_static_string(default_authority_str));
GPR_ASSERT(!args->is_last);
return GRPC_ERROR_NONE;
}
@@ -110,7 +111,7 @@ grpc_error* init_channel_elem(grpc_channel_element* elem,
/* Destructor for channel data */
void destroy_channel_elem(grpc_channel_element* elem) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
- grpc_slice_unref(chand->default_authority);
+ grpc_slice_unref_internal(chand->default_authority);
}
} // namespace
diff --git a/src/core/ext/filters/http/message_compress/message_compress_filter.cc b/src/core/ext/filters/http/message_compress/message_compress_filter.cc
index e7d9949386..933fe3c77b 100644
--- a/src/core/ext/filters/http/message_compress/message_compress_filter.cc
+++ b/src/core/ext/filters/http/message_compress/message_compress_filter.cc
@@ -116,8 +116,8 @@ static grpc_error* process_send_initial_metadata(
if (initial_metadata->idx.named.grpc_internal_encoding_request != nullptr) {
grpc_mdelem md =
initial_metadata->idx.named.grpc_internal_encoding_request->md;
- if (!grpc_compression_algorithm_parse(GRPC_MDVALUE(md),
- &compression_algorithm)) {
+ if (GPR_UNLIKELY(!grpc_compression_algorithm_parse(
+ GRPC_MDVALUE(md), &compression_algorithm))) {
char* val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
gpr_log(GPR_ERROR,
"Invalid compression algorithm: '%s' (unknown). Ignoring.", val);
@@ -125,8 +125,8 @@ static grpc_error* process_send_initial_metadata(
calld->message_compression_algorithm = GRPC_MESSAGE_COMPRESS_NONE;
stream_compression_algorithm = GRPC_STREAM_COMPRESS_NONE;
}
- if (!GPR_BITGET(channeld->enabled_algorithms_bitset,
- compression_algorithm)) {
+ if (GPR_UNLIKELY(!GPR_BITGET(channeld->enabled_algorithms_bitset,
+ compression_algorithm))) {
char* val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
gpr_log(GPR_ERROR,
"Invalid compression algorithm: '%s' (previously disabled). "
@@ -234,7 +234,7 @@ static void finish_send_message(grpc_call_element* elem) {
static_cast<float>(before_size);
GPR_ASSERT(grpc_message_compression_algorithm_name(
calld->message_compression_algorithm, &algo_name));
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"Compressed[%s] %" PRIuPTR " bytes vs. %" PRIuPTR
" bytes (%.2f%% savings)",
algo_name, before_size, after_size, 100 * savings_ratio);
@@ -246,7 +246,7 @@ static void finish_send_message(grpc_call_element* elem) {
const char* algo_name;
GPR_ASSERT(grpc_message_compression_algorithm_name(
calld->message_compression_algorithm, &algo_name));
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"Algorithm '%s' enabled but decided not to compress. Input size: "
"%" PRIuPTR,
algo_name, calld->slices.length);
diff --git a/src/core/ext/transport/chttp2/transport/bin_decoder.cc b/src/core/ext/transport/chttp2/transport/bin_decoder.cc
index f0f32da028..b660a45652 100644
--- a/src/core/ext/transport/chttp2/transport/bin_decoder.cc
+++ b/src/core/ext/transport/chttp2/transport/bin_decoder.cc
@@ -55,7 +55,7 @@ static bool input_is_valid(uint8_t* input_ptr, size_t length) {
size_t i;
for (i = 0; i < length; ++i) {
- if ((decode_table[input_ptr[i]] & 0xC0) != 0) {
+ if (GPR_UNLIKELY((decode_table[input_ptr[i]] & 0xC0) != 0)) {
gpr_log(GPR_ERROR,
"Base64 decoding failed, invalid character '%c' in base64 "
"input.\n",
@@ -86,14 +86,14 @@ size_t grpc_chttp2_base64_infer_length_after_decode(const grpc_slice& slice) {
while (len > 0 && bytes[len - 1] == '=') {
len--;
}
- if (GRPC_SLICE_LENGTH(slice) - len > 2) {
+ if (GPR_UNLIKELY(GRPC_SLICE_LENGTH(slice) - len > 2)) {
gpr_log(GPR_ERROR,
"Base64 decoding failed. Input has more than 2 paddings.");
return 0;
}
size_t tuples = len / 4;
size_t tail_case = len % 4;
- if (tail_case == 1) {
+ if (GPR_UNLIKELY(tail_case == 1)) {
gpr_log(GPR_ERROR,
"Base64 decoding failed. Input has a length of %zu (without"
" padding), which is invalid.\n",
@@ -164,7 +164,7 @@ grpc_slice grpc_chttp2_base64_decode(grpc_slice input) {
struct grpc_base64_decode_context ctx;
grpc_slice output;
- if (input_length % 4 != 0) {
+ if (GPR_UNLIKELY(input_length % 4 != 0)) {
gpr_log(GPR_ERROR,
"Base64 decoding failed, input of "
"grpc_chttp2_base64_decode has a length of %d, which is not a "
@@ -190,7 +190,7 @@ grpc_slice grpc_chttp2_base64_decode(grpc_slice input) {
ctx.output_end = GRPC_SLICE_END_PTR(output);
ctx.contains_tail = false;
- if (!grpc_base64_decode_partial(&ctx)) {
+ if (GPR_UNLIKELY(!grpc_base64_decode_partial(&ctx))) {
char* s = grpc_slice_to_c_string(input);
gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s);
gpr_free(s);
@@ -209,7 +209,7 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_slice input,
struct grpc_base64_decode_context ctx;
// The length of a base64 string cannot be 4 * n + 1
- if (input_length % 4 == 1) {
+ if (GPR_UNLIKELY(input_length % 4 == 1)) {
gpr_log(GPR_ERROR,
"Base64 decoding failed, input of "
"grpc_chttp2_base64_decode_with_length has a length of %d, which "
@@ -219,7 +219,8 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_slice input,
return grpc_empty_slice();
}
- if (output_length > input_length / 4 * 3 + tail_xtra[input_length % 4]) {
+ if (GPR_UNLIKELY(output_length >
+ input_length / 4 * 3 + tail_xtra[input_length % 4])) {
gpr_log(
GPR_ERROR,
"Base64 decoding failed, output_length %d is longer "
@@ -236,7 +237,7 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_slice input,
ctx.output_end = GRPC_SLICE_END_PTR(output);
ctx.contains_tail = true;
- if (!grpc_base64_decode_partial(&ctx)) {
+ if (GPR_UNLIKELY(!grpc_base64_decode_partial(&ctx))) {
char* s = grpc_slice_to_c_string(input);
gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s);
gpr_free(s);
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
index 6980b8671e..cc4a823798 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
@@ -718,7 +718,7 @@ static void destroy_stream_locked(void* sp, grpc_error* error) {
grpc_chttp2_list_remove_stalled_by_stream(t, s);
for (int i = 0; i < STREAM_LIST_COUNT; i++) {
- if (s->included[i]) {
+ if (GPR_UNLIKELY(s->included[i])) {
gpr_log(GPR_ERROR, "%s stream %d still included in list %d",
t->is_client ? "client" : "server", s->id, i);
abort();
@@ -807,7 +807,7 @@ static const char* write_state_name(grpc_chttp2_write_state st) {
static void set_write_state(grpc_chttp2_transport* t,
grpc_chttp2_write_state st, const char* reason) {
- GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_DEBUG, "W:%p %s state %s -> %s [%s]", t,
+ GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "W:%p %s state %s -> %s [%s]", t,
t->is_client ? "CLIENT" : "SERVER",
write_state_name(t->write_state),
write_state_name(st), reason));
@@ -1072,7 +1072,7 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t,
uint32_t goaway_error,
grpc_slice goaway_text) {
// GRPC_CHTTP2_IF_TRACING(
- // gpr_log(GPR_DEBUG, "got goaway [%d]: %s", goaway_error, msg));
+ // gpr_log(GPR_INFO, "got goaway [%d]: %s", goaway_error, msg));
// Discard the error from a previous goaway frame (if any)
if (t->goaway_error != GRPC_ERROR_NONE) {
@@ -1088,8 +1088,9 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t,
* data equal to "too_many_pings", it should log the occurrence at a log level
* that is enabled by default and double the configured KEEPALIVE_TIME used
* for new connections on that channel. */
- if (t->is_client && goaway_error == GRPC_HTTP2_ENHANCE_YOUR_CALM &&
- grpc_slice_str_cmp(goaway_text, "too_many_pings") == 0) {
+ if (GPR_UNLIKELY(t->is_client &&
+ goaway_error == GRPC_HTTP2_ENHANCE_YOUR_CALM &&
+ grpc_slice_str_cmp(goaway_text, "too_many_pings") == 0)) {
gpr_log(GPR_ERROR,
"Received a GOAWAY with error code ENHANCE_YOUR_CALM and debug "
"data equal to \"too_many_pings\"");
@@ -1118,7 +1119,7 @@ static void maybe_start_some_streams(grpc_chttp2_transport* t) {
grpc_chttp2_list_pop_waiting_for_concurrency(t, &s)) {
/* safe since we can't (legally) be parsing this stream yet */
GRPC_CHTTP2_IF_TRACING(gpr_log(
- GPR_DEBUG, "HTTP:%s: Allocating new grpc_chttp2_stream %p to id %d",
+ GPR_INFO, "HTTP:%s: Allocating new grpc_chttp2_stream %p to id %d",
t->is_client ? "CLI" : "SVR", s, t->next_stream_id));
GPR_ASSERT(s->id == 0);
@@ -1183,7 +1184,7 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
if (grpc_http_trace.enabled()) {
const char* errstr = grpc_error_string(error);
gpr_log(
- GPR_DEBUG,
+ GPR_INFO,
"complete_closure_step: t=%p %p refs=%d flags=0x%04x desc=%s err=%s "
"write_state=%s",
t, closure,
@@ -1336,7 +1337,7 @@ static void perform_stream_op_locked(void* stream_op,
if (grpc_http_trace.enabled()) {
char* str = grpc_transport_stream_op_batch_string(op);
- gpr_log(GPR_DEBUG, "perform_stream_op_locked: %s; on_complete = %p", str,
+ gpr_log(GPR_INFO, "perform_stream_op_locked: %s; on_complete = %p", str,
op->on_complete);
gpr_free(str);
if (op->send_initial_metadata) {
@@ -1638,7 +1639,7 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
if (grpc_http_trace.enabled()) {
char* str = grpc_transport_stream_op_batch_string(op);
- gpr_log(GPR_DEBUG, "perform_stream_op[s=%p]: %s", s, str);
+ gpr_log(GPR_INFO, "perform_stream_op[s=%p]: %s", s, str);
gpr_free(str);
}
@@ -1683,16 +1684,16 @@ static void send_ping_locked(grpc_chttp2_transport* t,
*/
static void send_keepalive_ping_locked(grpc_chttp2_transport* t) {
if (t->closed_with_error != GRPC_ERROR_NONE) {
- GRPC_CLOSURE_SCHED(&t->start_keepalive_ping_locked,
- GRPC_ERROR_REF(t->closed_with_error));
- GRPC_CLOSURE_SCHED(&t->finish_keepalive_ping_locked,
- GRPC_ERROR_REF(t->closed_with_error));
+ GRPC_CLOSURE_RUN(&t->start_keepalive_ping_locked,
+ GRPC_ERROR_REF(t->closed_with_error));
+ GRPC_CLOSURE_RUN(&t->finish_keepalive_ping_locked,
+ GRPC_ERROR_REF(t->closed_with_error));
return;
}
grpc_chttp2_ping_queue* pq = &t->ping_queue;
if (!grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_INFLIGHT])) {
/* There is a ping in flight. Add yourself to the inflight closure list. */
- GRPC_CLOSURE_SCHED(&t->start_keepalive_ping_locked, GRPC_ERROR_NONE);
+ GRPC_CLOSURE_RUN(&t->start_keepalive_ping_locked, GRPC_ERROR_NONE);
grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_INFLIGHT],
&t->finish_keepalive_ping_locked, GRPC_ERROR_NONE);
return;
@@ -1800,8 +1801,11 @@ static void perform_transport_op_locked(void* stream_op,
static void perform_transport_op(grpc_transport* gt, grpc_transport_op* op) {
grpc_chttp2_transport* t = reinterpret_cast<grpc_chttp2_transport*>(gt);
- char* msg = grpc_transport_op_string(op);
- gpr_free(msg);
+ if (grpc_http_trace.enabled()) {
+ char* msg = grpc_transport_op_string(op);
+ gpr_log(GPR_INFO, "perform_transport_op[t=%p]: %s", t, msg);
+ gpr_free(msg);
+ }
op->handler_private.extra_arg = gt;
GRPC_CHTTP2_REF_TRANSPORT(t, "transport_op");
GRPC_CLOSURE_SCHED(GRPC_CLOSURE_INIT(&op->handler_private.closure,
@@ -2529,7 +2533,7 @@ static void schedule_bdp_ping_locked(grpc_chttp2_transport* t) {
static void start_bdp_ping_locked(void* tp, grpc_error* error) {
grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(tp);
if (grpc_http_trace.enabled()) {
- gpr_log(GPR_DEBUG, "%s: Start BDP ping err=%s", t->peer_string,
+ gpr_log(GPR_INFO, "%s: Start BDP ping err=%s", t->peer_string,
grpc_error_string(error));
}
/* Reset the keepalive ping timer */
@@ -2542,7 +2546,7 @@ static void start_bdp_ping_locked(void* tp, grpc_error* error) {
static void finish_bdp_ping_locked(void* tp, grpc_error* error) {
grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(tp);
if (grpc_http_trace.enabled()) {
- gpr_log(GPR_DEBUG, "%s: Complete BDP ping err=%s", t->peer_string,
+ gpr_log(GPR_INFO, "%s: Complete BDP ping err=%s", t->peer_string,
grpc_error_string(error));
}
if (error != GRPC_ERROR_NONE) {
@@ -2701,7 +2705,7 @@ static void keepalive_watchdog_fired_locked(void* arg, grpc_error* error) {
} else {
/* The watchdog timer should have been cancelled by
* finish_keepalive_ping_locked. */
- if (error != GRPC_ERROR_CANCELLED) {
+ if (GPR_UNLIKELY(error != GRPC_ERROR_CANCELLED)) {
gpr_log(GPR_ERROR, "keepalive_ping_end state error: %d (expect: %d)",
t->keepalive_state, GRPC_CHTTP2_KEEPALIVE_STATE_PINGING);
}
@@ -2716,8 +2720,7 @@ static void keepalive_watchdog_fired_locked(void* arg, grpc_error* error) {
static void connectivity_state_set(grpc_chttp2_transport* t,
grpc_connectivity_state state,
grpc_error* error, const char* reason) {
- GRPC_CHTTP2_IF_TRACING(
- gpr_log(GPR_DEBUG, "set connectivity_state=%d", state));
+ GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "set connectivity_state=%d", state));
grpc_connectivity_state_set(&t->channel_callback.state_tracker, state, error,
reason);
}
@@ -2984,7 +2987,7 @@ static void benign_reclaimer_locked(void* arg, grpc_error* error) {
/* Channel with no active streams: send a goaway to try and make it
* disconnect cleanly */
if (grpc_resource_quota_trace.enabled()) {
- gpr_log(GPR_DEBUG, "HTTP2: %s - send goaway to free memory",
+ gpr_log(GPR_INFO, "HTTP2: %s - send goaway to free memory",
t->peer_string);
}
send_goaway(t,
@@ -2992,7 +2995,7 @@ static void benign_reclaimer_locked(void* arg, grpc_error* error) {
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Buffers full"),
GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_ENHANCE_YOUR_CALM));
} else if (error == GRPC_ERROR_NONE && grpc_resource_quota_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"HTTP2: %s - skip benign reclamation, there are still %" PRIdPTR
" streams",
t->peer_string, grpc_chttp2_stream_map_size(&t->stream_map));
@@ -3013,7 +3016,7 @@ static void destructive_reclaimer_locked(void* arg, grpc_error* error) {
grpc_chttp2_stream* s = static_cast<grpc_chttp2_stream*>(
grpc_chttp2_stream_map_rand(&t->stream_map));
if (grpc_resource_quota_trace.enabled()) {
- gpr_log(GPR_DEBUG, "HTTP2: %s - abandon stream id %d", t->peer_string,
+ gpr_log(GPR_INFO, "HTTP2: %s - abandon stream id %d", t->peer_string,
s->id);
}
grpc_chttp2_cancel_stream(
diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.cc b/src/core/ext/transport/chttp2/transport/frame_settings.cc
index 9ea27dcd47..987ac0e79d 100644
--- a/src/core/ext/transport/chttp2/transport/frame_settings.cc
+++ b/src/core/ext/transport/chttp2/transport/frame_settings.cc
@@ -217,14 +217,14 @@ grpc_error* grpc_chttp2_settings_parser_parse(void* p, grpc_chttp2_transport* t,
t->initial_window_update += static_cast<int64_t>(parser->value) -
parser->incoming_settings[id];
if (grpc_http_trace.enabled() || grpc_flowctl_trace.enabled()) {
- gpr_log(GPR_DEBUG, "%p[%s] adding %d for initial_window change",
- t, t->is_client ? "cli" : "svr",
+ gpr_log(GPR_INFO, "%p[%s] adding %d for initial_window change", t,
+ t->is_client ? "cli" : "svr",
static_cast<int>(t->initial_window_update));
}
}
parser->incoming_settings[id] = parser->value;
if (grpc_http_trace.enabled()) {
- gpr_log(GPR_DEBUG, "CHTTP2:%s:%s: got setting %s = %d",
+ gpr_log(GPR_INFO, "CHTTP2:%s:%s: got setting %s = %d",
t->is_client ? "CLI" : "SVR", t->peer_string, sp->name,
parser->value);
}
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.cc b/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
index e4f3c1b81e..d5ef063883 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
@@ -470,7 +470,7 @@ static void hpack_enc(grpc_chttp2_hpack_compressor* c, grpc_mdelem elem,
v = grpc_slice_to_c_string(GRPC_MDVALUE(elem));
}
gpr_log(
- GPR_DEBUG,
+ GPR_INFO,
"Encode: '%s: %s', elem_interned=%d [%d], k_interned=%d, v_interned=%d",
k, v, GRPC_MDELEM_IS_INTERNED(elem), GRPC_MDELEM_STORAGE(elem),
grpc_slice_is_interned(GRPC_MDKEY(elem)),
@@ -654,7 +654,7 @@ void grpc_chttp2_hpack_compressor_set_max_table_size(
}
c->advertise_table_size_change = 1;
if (grpc_http_trace.enabled()) {
- gpr_log(GPR_DEBUG, "set max table size from encoder to %d", max_table_size);
+ gpr_log(GPR_INFO, "set max table size from encoder to %d", max_table_size);
}
}
diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.cc b/src/core/ext/transport/chttp2/transport/hpack_parser.cc
index fc96a8b3e4..907ba71178 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_parser.cc
+++ b/src/core/ext/transport/chttp2/transport/hpack_parser.cc
@@ -633,7 +633,7 @@ static grpc_error* on_hdr(grpc_chttp2_hpack_parser* p, grpc_mdelem md,
v = grpc_slice_to_c_string(GRPC_MDVALUE(md));
}
gpr_log(
- GPR_DEBUG,
+ GPR_INFO,
"Decode: '%s: %s', elem_interned=%d [%d], k_interned=%d, v_interned=%d",
k, v, GRPC_MDELEM_IS_INTERNED(md), GRPC_MDELEM_STORAGE(md),
grpc_slice_is_interned(GRPC_MDKEY(md)),
diff --git a/src/core/ext/transport/chttp2/transport/hpack_table.cc b/src/core/ext/transport/chttp2/transport/hpack_table.cc
index f050f502f5..7929258356 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_table.cc
+++ b/src/core/ext/transport/chttp2/transport/hpack_table.cc
@@ -247,7 +247,7 @@ void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl* tbl,
return;
}
if (grpc_http_trace.enabled()) {
- gpr_log(GPR_DEBUG, "Update hpack parser max size to %d", max_bytes);
+ gpr_log(GPR_INFO, "Update hpack parser max size to %d", max_bytes);
}
while (tbl->mem_used > max_bytes) {
evict1(tbl);
@@ -270,7 +270,7 @@ grpc_error* grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl* tbl,
return err;
}
if (grpc_http_trace.enabled()) {
- gpr_log(GPR_DEBUG, "Update hpack parser table size to %d", bytes);
+ gpr_log(GPR_INFO, "Update hpack parser table size to %d", bytes);
}
while (tbl->mem_used > bytes) {
evict1(tbl);
diff --git a/src/core/ext/transport/chttp2/transport/parsing.cc b/src/core/ext/transport/chttp2/transport/parsing.cc
index a10c9ada46..1e491d2ef8 100644
--- a/src/core/ext/transport/chttp2/transport/parsing.cc
+++ b/src/core/ext/transport/chttp2/transport/parsing.cc
@@ -422,7 +422,8 @@ static void on_initial_header(void* tp, grpc_mdelem md) {
if (cached_timeout != nullptr) {
timeout = *cached_timeout;
} else {
- if (!grpc_http2_decode_timeout(GRPC_MDVALUE(md), &timeout)) {
+ if (GPR_UNLIKELY(
+ !grpc_http2_decode_timeout(GRPC_MDVALUE(md), &timeout))) {
char* val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val);
gpr_free(val);
@@ -550,15 +551,15 @@ static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t,
/* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */
s = grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
if (s == nullptr) {
- if (is_continuation) {
+ if (GPR_UNLIKELY(is_continuation)) {
GRPC_CHTTP2_IF_TRACING(
gpr_log(GPR_ERROR,
"grpc_chttp2_stream disbanded before CONTINUATION received"));
return init_skip_frame_parser(t, 1);
}
if (t->is_client) {
- if ((t->incoming_stream_id & 1) &&
- t->incoming_stream_id < t->next_stream_id) {
+ if (GPR_LIKELY((t->incoming_stream_id & 1) &&
+ t->incoming_stream_id < t->next_stream_id)) {
/* this is an old (probably cancelled) grpc_chttp2_stream */
} else {
GRPC_CHTTP2_IF_TRACING(gpr_log(
@@ -569,7 +570,7 @@ static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t,
grpc_chttp2_hpack_parser_set_has_priority(&t->hpack_parser);
}
return err;
- } else if (t->last_new_stream_id >= t->incoming_stream_id) {
+ } else if (GPR_UNLIKELY(t->last_new_stream_id >= t->incoming_stream_id)) {
GRPC_CHTTP2_IF_TRACING(gpr_log(
GPR_ERROR,
"ignoring out of order new grpc_chttp2_stream request on server; "
@@ -577,21 +578,22 @@ static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t,
"id=%d, new grpc_chttp2_stream id=%d",
t->last_new_stream_id, t->incoming_stream_id));
return init_skip_frame_parser(t, 1);
- } else if ((t->incoming_stream_id & 1) == 0) {
+ } else if (GPR_UNLIKELY((t->incoming_stream_id & 1) == 0)) {
GRPC_CHTTP2_IF_TRACING(gpr_log(
GPR_ERROR,
"ignoring grpc_chttp2_stream with non-client generated index %d",
t->incoming_stream_id));
return init_skip_frame_parser(t, 1);
- } else if (grpc_chttp2_stream_map_size(&t->stream_map) >=
- t->settings[GRPC_ACKED_SETTINGS]
- [GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS]) {
+ } else if (GPR_UNLIKELY(
+ grpc_chttp2_stream_map_size(&t->stream_map) >=
+ t->settings[GRPC_ACKED_SETTINGS]
+ [GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS])) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Max stream count exceeded");
}
t->last_new_stream_id = t->incoming_stream_id;
s = t->incoming_stream =
grpc_chttp2_parsing_accept_stream(t, t->incoming_stream_id);
- if (s == nullptr) {
+ if (GPR_UNLIKELY(s == nullptr)) {
GRPC_CHTTP2_IF_TRACING(
gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted"));
return init_skip_frame_parser(t, 1);
@@ -601,7 +603,7 @@ static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t,
}
GPR_ASSERT(s != nullptr);
s->stats.incoming.framing_bytes += 9;
- if (s->read_closed) {
+ if (GPR_UNLIKELY(s->read_closed)) {
GRPC_CHTTP2_IF_TRACING(gpr_log(
GPR_ERROR, "skipping already closed grpc_chttp2_stream header"));
t->incoming_stream = nullptr;
@@ -723,7 +725,7 @@ static grpc_error* parse_frame_slice(grpc_chttp2_transport* t, grpc_slice slice,
int is_last) {
grpc_chttp2_stream* s = t->incoming_stream;
grpc_error* err = t->parser(t->parser_data, t, s, slice, is_last);
- if (err == GRPC_ERROR_NONE) {
+ if (GPR_LIKELY(err == GRPC_ERROR_NONE)) {
return err;
} else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, nullptr)) {
if (grpc_http_trace.enabled()) {
diff --git a/src/core/ext/transport/chttp2/transport/stream_lists.cc b/src/core/ext/transport/chttp2/transport/stream_lists.cc
index 5d3ec4b53b..6626170a7e 100644
--- a/src/core/ext/transport/chttp2/transport/stream_lists.cc
+++ b/src/core/ext/transport/chttp2/transport/stream_lists.cc
@@ -68,7 +68,7 @@ static bool stream_list_pop(grpc_chttp2_transport* t,
}
*stream = s;
if (s && grpc_trace_http2_stream_state.enabled()) {
- gpr_log(GPR_DEBUG, "%p[%d][%s]: pop from %s", t, s->id,
+ gpr_log(GPR_INFO, "%p[%d][%s]: pop from %s", t, s->id,
t->is_client ? "cli" : "svr", stream_list_id_string(id));
}
return s != nullptr;
@@ -90,7 +90,7 @@ static void stream_list_remove(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
t->lists[id].tail = s->links[id].prev;
}
if (grpc_trace_http2_stream_state.enabled()) {
- gpr_log(GPR_DEBUG, "%p[%d][%s]: remove from %s", t, s->id,
+ gpr_log(GPR_INFO, "%p[%d][%s]: remove from %s", t, s->id,
t->is_client ? "cli" : "svr", stream_list_id_string(id));
}
}
@@ -122,7 +122,7 @@ static void stream_list_add_tail(grpc_chttp2_transport* t,
t->lists[id].tail = s;
s->included[id] = 1;
if (grpc_trace_http2_stream_state.enabled()) {
- gpr_log(GPR_DEBUG, "%p[%d][%s]: add to %s", t, s->id,
+ gpr_log(GPR_INFO, "%p[%d][%s]: add to %s", t, s->id,
t->is_client ? "cli" : "svr", stream_list_id_string(id));
}
}
diff --git a/src/core/ext/transport/chttp2/transport/writing.cc b/src/core/ext/transport/chttp2/transport/writing.cc
index 6f32397a3a..34d5e6e218 100644
--- a/src/core/ext/transport/chttp2/transport/writing.cc
+++ b/src/core/ext/transport/chttp2/transport/writing.cc
@@ -52,7 +52,7 @@ static void maybe_initiate_ping(grpc_chttp2_transport* t) {
if (!grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_INFLIGHT])) {
/* ping already in-flight: wait */
if (grpc_http_trace.enabled() || grpc_bdp_estimator_trace.enabled()) {
- gpr_log(GPR_DEBUG, "%s: Ping delayed [%p]: already pinging",
+ gpr_log(GPR_INFO, "%s: Ping delayed [%p]: already pinging",
t->is_client ? "CLIENT" : "SERVER", t->peer_string);
}
return;
@@ -61,7 +61,7 @@ static void maybe_initiate_ping(grpc_chttp2_transport* t) {
t->ping_policy.max_pings_without_data != 0) {
/* need to receive something of substance before sending a ping again */
if (grpc_http_trace.enabled() || grpc_bdp_estimator_trace.enabled()) {
- gpr_log(GPR_DEBUG, "%s: Ping delayed [%p]: too many recent pings: %d/%d",
+ gpr_log(GPR_INFO, "%s: Ping delayed [%p]: too many recent pings: %d/%d",
t->is_client ? "CLIENT" : "SERVER", t->peer_string,
t->ping_state.pings_before_data_required,
t->ping_policy.max_pings_without_data);
@@ -81,7 +81,7 @@ static void maybe_initiate_ping(grpc_chttp2_transport* t) {
if (next_allowed_ping > now) {
/* not enough elapsed time between successive pings */
if (grpc_http_trace.enabled() || grpc_bdp_estimator_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"%s: Ping delayed [%p]: not enough time elapsed since last ping. "
" Last ping %f: Next ping %f: Now %f",
t->is_client ? "CLIENT" : "SERVER", t->peer_string,
@@ -107,7 +107,7 @@ static void maybe_initiate_ping(grpc_chttp2_transport* t) {
GRPC_STATS_INC_HTTP2_PINGS_SENT();
t->ping_state.last_ping_sent_time = now;
if (grpc_http_trace.enabled() || grpc_bdp_estimator_trace.enabled()) {
- gpr_log(GPR_DEBUG, "%s: Ping sent [%p]: %d/%d",
+ gpr_log(GPR_INFO, "%s: Ping sent [%p]: %d/%d",
t->is_client ? "CLIENT" : "SERVER", t->peer_string,
t->ping_state.pings_before_data_required,
t->ping_policy.max_pings_without_data);
@@ -337,10 +337,10 @@ class DataSendContext {
s_->fetching_send_message == nullptr);
if (is_last_data_frame && s_->send_trailing_metadata != nullptr &&
s_->stream_compression_ctx != nullptr) {
- if (!grpc_stream_compress(
+ if (GPR_UNLIKELY(!grpc_stream_compress(
s_->stream_compression_ctx, &s_->flow_controlled_buffer,
&s_->compressed_data_buffer, nullptr, MAX_SIZE_T,
- GRPC_STREAM_COMPRESSION_FLUSH_FINISH)) {
+ GRPC_STREAM_COMPRESSION_FLUSH_FINISH))) {
gpr_log(GPR_ERROR, "Stream compression failed.");
}
grpc_stream_compression_context_destroy(s_->stream_compression_ctx);
@@ -368,10 +368,10 @@ class DataSendContext {
grpc_stream_compression_context_create(s_->stream_compression_method);
}
s_->uncompressed_data_size = s_->flow_controlled_buffer.length;
- if (!grpc_stream_compress(s_->stream_compression_ctx,
- &s_->flow_controlled_buffer,
- &s_->compressed_data_buffer, nullptr, MAX_SIZE_T,
- GRPC_STREAM_COMPRESSION_FLUSH_SYNC)) {
+ if (GPR_UNLIKELY(!grpc_stream_compress(
+ s_->stream_compression_ctx, &s_->flow_controlled_buffer,
+ &s_->compressed_data_buffer, nullptr, MAX_SIZE_T,
+ GRPC_STREAM_COMPRESSION_FLUSH_SYNC))) {
gpr_log(GPR_ERROR, "Stream compression failed.");
}
}
@@ -401,7 +401,7 @@ class StreamWriteContext {
StreamWriteContext(WriteContext* write_context, grpc_chttp2_stream* s)
: write_context_(write_context), t_(write_context->transport()), s_(s) {
GRPC_CHTTP2_IF_TRACING(
- gpr_log(GPR_DEBUG, "W:%p %s[%d] im-(sent,send)=(%d,%d) announce=%d", t_,
+ gpr_log(GPR_INFO, "W:%p %s[%d] im-(sent,send)=(%d,%d) announce=%d", t_,
t_->is_client ? "CLIENT" : "SERVER", s->id,
s->sent_initial_metadata, s->send_initial_metadata != nullptr,
(int)(s->flow_control->local_window_delta() -
diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.cc b/src/core/ext/transport/cronet/transport/cronet_transport.cc
index 8e3ea05706..420c2d13e1 100644
--- a/src/core/ext/transport/cronet/transport/cronet_transport.cc
+++ b/src/core/ext/transport/cronet/transport/cronet_transport.cc
@@ -360,7 +360,7 @@ static void remove_from_storage(struct stream_obj* s,
s->storage.num_pending_ops);
gpr_free(oas);
break;
- } else if (curr->next == nullptr) {
+ } else if (GPR_UNLIKELY(curr->next == nullptr)) {
CRONET_LOG(GPR_ERROR, "Reached end of LL and did not find op to free");
}
}
@@ -736,7 +736,7 @@ static void convert_metadata_to_cronet_headers(
if (grpc_is_binary_header(GRPC_MDKEY(mdelem))) {
grpc_slice wire_value = grpc_chttp2_base64_encode(GRPC_MDVALUE(mdelem));
value = grpc_slice_to_c_string(wire_value);
- grpc_slice_unref(wire_value);
+ grpc_slice_unref_internal(wire_value);
} else {
value = grpc_slice_to_c_string(GRPC_MDVALUE(mdelem));
}
@@ -1054,7 +1054,7 @@ static enum e_op_result execute_stream_op(struct op_and_state* oas) {
GPR_ASSERT(false);
}
grpc_slice_buffer_add(&write_slice_buffer, slice);
- if (write_slice_buffer.count != 1) {
+ if (GPR_UNLIKELY(write_slice_buffer.count != 1)) {
/* Empty request not handled yet */
gpr_log(GPR_ERROR, "Empty request is not supported");
GPR_ASSERT(write_slice_buffer.count == 1);
@@ -1455,7 +1455,7 @@ grpc_transport* grpc_create_cronet_transport(void* engine, const char* target,
for (size_t i = 0; i < args->num_args; i++) {
if (0 ==
strcmp(args->args[i].key, GRPC_ARG_USE_CRONET_PACKET_COALESCING)) {
- if (args->args[i].type != GRPC_ARG_INTEGER) {
+ if (GPR_UNLIKELY(args->args[i].type != GRPC_ARG_INTEGER)) {
gpr_log(GPR_ERROR, "%s ignored: it must be an integer",
GRPC_ARG_USE_CRONET_PACKET_COALESCING);
} else {
diff --git a/src/core/ext/transport/inproc/inproc_transport.cc b/src/core/ext/transport/inproc/inproc_transport.cc
index 67a380077b..2c3bff5c1e 100644
--- a/src/core/ext/transport/inproc/inproc_transport.cc
+++ b/src/core/ext/transport/inproc/inproc_transport.cc
@@ -125,12 +125,12 @@ static bool cancel_stream_locked(inproc_stream* s, grpc_error* error);
static void op_state_machine(void* arg, grpc_error* error);
static void ref_transport(inproc_transport* t) {
- INPROC_LOG(GPR_DEBUG, "ref_transport %p", t);
+ INPROC_LOG(GPR_INFO, "ref_transport %p", t);
gpr_ref(&t->refs);
}
static void really_destroy_transport(inproc_transport* t) {
- INPROC_LOG(GPR_DEBUG, "really_destroy_transport %p", t);
+ INPROC_LOG(GPR_INFO, "really_destroy_transport %p", t);
grpc_connectivity_state_destroy(&t->connectivity);
if (gpr_unref(&t->mu->refs)) {
gpr_free(t->mu);
@@ -139,7 +139,7 @@ static void really_destroy_transport(inproc_transport* t) {
}
static void unref_transport(inproc_transport* t) {
- INPROC_LOG(GPR_DEBUG, "unref_transport %p", t);
+ INPROC_LOG(GPR_INFO, "unref_transport %p", t);
if (gpr_unref(&t->refs)) {
really_destroy_transport(t);
}
@@ -154,17 +154,17 @@ static void unref_transport(inproc_transport* t) {
#endif
static void ref_stream(inproc_stream* s, const char* reason) {
- INPROC_LOG(GPR_DEBUG, "ref_stream %p %s", s, reason);
+ INPROC_LOG(GPR_INFO, "ref_stream %p %s", s, reason);
STREAM_REF(s->refs, reason);
}
static void unref_stream(inproc_stream* s, const char* reason) {
- INPROC_LOG(GPR_DEBUG, "unref_stream %p %s", s, reason);
+ INPROC_LOG(GPR_INFO, "unref_stream %p %s", s, reason);
STREAM_UNREF(s->refs, reason);
}
static void really_destroy_stream(inproc_stream* s) {
- INPROC_LOG(GPR_DEBUG, "really_destroy_stream %p", s);
+ INPROC_LOG(GPR_INFO, "really_destroy_stream %p", s);
GRPC_ERROR_UNREF(s->write_buffer_cancel_error);
GRPC_ERROR_UNREF(s->cancel_self_error);
@@ -225,7 +225,7 @@ static grpc_error* fill_in_metadata(inproc_stream* s,
static int init_stream(grpc_transport* gt, grpc_stream* gs,
grpc_stream_refcount* refcount, const void* server_data,
gpr_arena* arena) {
- INPROC_LOG(GPR_DEBUG, "init_stream %p %p %p", gt, gs, server_data);
+ INPROC_LOG(GPR_INFO, "init_stream %p %p %p", gt, gs, server_data);
inproc_transport* t = reinterpret_cast<inproc_transport*>(gt);
inproc_stream* s = reinterpret_cast<inproc_stream*>(gs);
s->arena = arena;
@@ -282,8 +282,8 @@ static int init_stream(grpc_transport* gt, grpc_stream* gs,
// Pass the client-side stream address to the server-side for a ref
ref_stream(s, "inproc_init_stream:clt"); // ref it now on behalf of server
// side to avoid destruction
- INPROC_LOG(GPR_DEBUG, "calling accept stream cb %p %p",
- st->accept_stream_cb, st->accept_stream_data);
+ INPROC_LOG(GPR_INFO, "calling accept stream cb %p %p", st->accept_stream_cb,
+ st->accept_stream_data);
(*st->accept_stream_cb)(st->accept_stream_data, &st->base, (void*)s);
} else {
// This is the server-side and is being called through accept_stream_cb
@@ -378,7 +378,7 @@ static void complete_if_batch_end_locked(inproc_stream* s, grpc_error* error,
int is_rtm = static_cast<int>(op == s->recv_trailing_md_op);
if ((is_sm + is_stm + is_rim + is_rm + is_rtm) == 1) {
- INPROC_LOG(GPR_DEBUG, "%s %p %p %p", msg, s, op, error);
+ INPROC_LOG(GPR_INFO, "%s %p %p %p", msg, s, op, error);
GRPC_CLOSURE_SCHED(op->on_complete, GRPC_ERROR_REF(error));
}
}
@@ -393,7 +393,7 @@ static void maybe_schedule_op_closure_locked(inproc_stream* s,
}
static void fail_helper_locked(inproc_stream* s, grpc_error* error) {
- INPROC_LOG(GPR_DEBUG, "op_state_machine %p fail_helper", s);
+ INPROC_LOG(GPR_INFO, "op_state_machine %p fail_helper", s);
// If we're failing this side, we need to make sure that
// we also send or have already sent trailing metadata
if (!s->trailing_md_sent) {
@@ -458,7 +458,7 @@ static void fail_helper_locked(inproc_stream* s, grpc_error* error) {
*s->recv_initial_md_op->payload->recv_initial_metadata
.trailing_metadata_available = true;
}
- INPROC_LOG(GPR_DEBUG,
+ INPROC_LOG(GPR_INFO,
"fail_helper %p scheduling initial-metadata-ready %p %p", s,
error, err);
GRPC_CLOSURE_SCHED(s->recv_initial_md_op->payload->recv_initial_metadata
@@ -472,7 +472,7 @@ static void fail_helper_locked(inproc_stream* s, grpc_error* error) {
s->recv_initial_md_op = nullptr;
}
if (s->recv_message_op) {
- INPROC_LOG(GPR_DEBUG, "fail_helper %p scheduling message-ready %p", s,
+ INPROC_LOG(GPR_INFO, "fail_helper %p scheduling message-ready %p", s,
error);
GRPC_CLOSURE_SCHED(
s->recv_message_op->payload->recv_message.recv_message_ready,
@@ -496,9 +496,8 @@ static void fail_helper_locked(inproc_stream* s, grpc_error* error) {
s->send_trailing_md_op = nullptr;
}
if (s->recv_trailing_md_op) {
- INPROC_LOG(GPR_DEBUG,
- "fail_helper %p scheduling trailing-md-on-complete %p", s,
- error);
+ INPROC_LOG(GPR_INFO, "fail_helper %p scheduling trailing-md-on-complete %p",
+ s, error);
complete_if_batch_end_locked(
s, error, s->recv_trailing_md_op,
"fail_helper scheduling recv-trailing-metadata-on-complete");
@@ -549,7 +548,7 @@ static void message_transfer_locked(inproc_stream* sender,
receiver->recv_stream.Init(&receiver->recv_message, 0);
receiver->recv_message_op->payload->recv_message.recv_message->reset(
receiver->recv_stream.get());
- INPROC_LOG(GPR_DEBUG, "message_transfer_locked %p scheduling message-ready",
+ INPROC_LOG(GPR_INFO, "message_transfer_locked %p scheduling message-ready",
receiver);
GRPC_CLOSURE_SCHED(
receiver->recv_message_op->payload->recv_message.recv_message_ready,
@@ -577,7 +576,7 @@ static void op_state_machine(void* arg, grpc_error* error) {
bool needs_close = false;
- INPROC_LOG(GPR_DEBUG, "op_state_machine %p", arg);
+ INPROC_LOG(GPR_INFO, "op_state_machine %p", arg);
inproc_stream* s = static_cast<inproc_stream*>(arg);
gpr_mu* mu = &s->t->mu->mu; // keep aside in case s gets closed
gpr_mu_lock(mu);
@@ -626,7 +625,7 @@ static void op_state_machine(void* arg, grpc_error* error) {
: &other->to_read_trailing_md_filled;
if (*destfilled || s->trailing_md_sent) {
// The buffer is already in use; that's an error!
- INPROC_LOG(GPR_DEBUG, "Extra trailing metadata %p", s);
+ INPROC_LOG(GPR_INFO, "Extra trailing metadata %p", s);
new_err = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Extra trailing metadata");
fail_helper_locked(s, GRPC_ERROR_REF(new_err));
goto done;
@@ -639,7 +638,7 @@ static void op_state_machine(void* arg, grpc_error* error) {
}
s->trailing_md_sent = true;
if (!s->t->is_client && s->trailing_md_recvd && s->recv_trailing_md_op) {
- INPROC_LOG(GPR_DEBUG,
+ INPROC_LOG(GPR_INFO,
"op_state_machine %p scheduling trailing-md-on-complete", s);
GRPC_CLOSURE_SCHED(s->recv_trailing_md_op->on_complete,
GRPC_ERROR_NONE);
@@ -658,7 +657,7 @@ static void op_state_machine(void* arg, grpc_error* error) {
new_err =
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Already recvd initial md");
INPROC_LOG(
- GPR_DEBUG,
+ GPR_INFO,
"op_state_machine %p scheduling on_complete errors for already "
"recvd initial md %p",
s, new_err);
@@ -684,7 +683,7 @@ static void op_state_machine(void* arg, grpc_error* error) {
}
grpc_metadata_batch_clear(&s->to_read_initial_md);
s->to_read_initial_md_filled = false;
- INPROC_LOG(GPR_DEBUG,
+ INPROC_LOG(GPR_INFO,
"op_state_machine %p scheduling initial-metadata-ready %p", s,
new_err);
GRPC_CLOSURE_SCHED(s->recv_initial_md_op->payload->recv_initial_metadata
@@ -696,7 +695,7 @@ static void op_state_machine(void* arg, grpc_error* error) {
s->recv_initial_md_op = nullptr;
if (new_err != GRPC_ERROR_NONE) {
- INPROC_LOG(GPR_DEBUG,
+ INPROC_LOG(GPR_INFO,
"op_state_machine %p scheduling on_complete errors2 %p", s,
new_err);
fail_helper_locked(s, GRPC_ERROR_REF(new_err));
@@ -719,7 +718,7 @@ static void op_state_machine(void* arg, grpc_error* error) {
new_err =
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Already recvd trailing md");
INPROC_LOG(
- GPR_DEBUG,
+ GPR_INFO,
"op_state_machine %p scheduling on_complete errors for already "
"recvd trailing md %p",
s, new_err);
@@ -729,7 +728,7 @@ static void op_state_machine(void* arg, grpc_error* error) {
if (s->recv_message_op != nullptr) {
// This message needs to be wrapped up because it will never be
// satisfied
- INPROC_LOG(GPR_DEBUG, "op_state_machine %p scheduling message-ready", s);
+ INPROC_LOG(GPR_INFO, "op_state_machine %p scheduling message-ready", s);
GRPC_CLOSURE_SCHED(
s->recv_message_op->payload->recv_message.recv_message_ready,
GRPC_ERROR_NONE);
@@ -764,7 +763,7 @@ static void op_state_machine(void* arg, grpc_error* error) {
// (If the server hasn't already sent its trailing md, it doesn't have
// a final status, so don't mark this op complete)
if (s->t->is_client || s->trailing_md_sent) {
- INPROC_LOG(GPR_DEBUG,
+ INPROC_LOG(GPR_INFO,
"op_state_machine %p scheduling trailing-md-on-complete %p",
s, new_err);
GRPC_CLOSURE_SCHED(s->recv_trailing_md_op->on_complete,
@@ -772,21 +771,21 @@ static void op_state_machine(void* arg, grpc_error* error) {
s->recv_trailing_md_op = nullptr;
needs_close = true;
} else {
- INPROC_LOG(GPR_DEBUG,
+ INPROC_LOG(GPR_INFO,
"op_state_machine %p server needs to delay handling "
"trailing-md-on-complete %p",
s, new_err);
}
} else {
INPROC_LOG(
- GPR_DEBUG,
+ GPR_INFO,
"op_state_machine %p has trailing md but not yet waiting for it", s);
}
}
if (s->trailing_md_recvd && s->recv_message_op) {
// No further message will come on this stream, so finish off the
// recv_message_op
- INPROC_LOG(GPR_DEBUG, "op_state_machine %p scheduling message-ready", s);
+ INPROC_LOG(GPR_INFO, "op_state_machine %p scheduling message-ready", s);
GRPC_CLOSURE_SCHED(
s->recv_message_op->payload->recv_message.recv_message_ready,
GRPC_ERROR_NONE);
@@ -810,7 +809,7 @@ static void op_state_machine(void* arg, grpc_error* error) {
// Didn't get the item we wanted so we still need to get
// rescheduled
INPROC_LOG(
- GPR_DEBUG, "op_state_machine %p still needs closure %p %p %p %p %p", s,
+ GPR_INFO, "op_state_machine %p still needs closure %p %p %p %p %p", s,
s->send_message_op, s->send_trailing_md_op, s->recv_initial_md_op,
s->recv_message_op, s->recv_trailing_md_op);
s->ops_needed = true;
@@ -826,8 +825,7 @@ done:
static bool cancel_stream_locked(inproc_stream* s, grpc_error* error) {
bool ret = false; // was the cancel accepted
- INPROC_LOG(GPR_DEBUG, "cancel_stream %p with %s", s,
- grpc_error_string(error));
+ INPROC_LOG(GPR_INFO, "cancel_stream %p with %s", s, grpc_error_string(error));
if (s->cancel_self_error == GRPC_ERROR_NONE) {
ret = true;
s->cancel_self_error = GRPC_ERROR_REF(error);
@@ -877,7 +875,7 @@ static bool cancel_stream_locked(inproc_stream* s, grpc_error* error) {
static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
grpc_transport_stream_op_batch* op) {
- INPROC_LOG(GPR_DEBUG, "perform_stream_op %p %p %p", gt, gs, op);
+ INPROC_LOG(GPR_INFO, "perform_stream_op %p %p %p", gt, gs, op);
inproc_stream* s = reinterpret_cast<inproc_stream*>(gs);
gpr_mu* mu = &s->t->mu->mu; // save aside in case s gets closed
gpr_mu_lock(mu);
@@ -907,7 +905,7 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
// already self-canceled so still give it an error
error = GRPC_ERROR_REF(s->cancel_self_error);
} else {
- INPROC_LOG(GPR_DEBUG, "perform_stream_op %p %s%s%s%s%s%s%s", s,
+ INPROC_LOG(GPR_INFO, "perform_stream_op %p %s%s%s%s%s%s%s", s,
s->t->is_client ? "client" : "server",
op->send_initial_metadata ? " send_initial_metadata" : "",
op->send_message ? " send_message" : "",
@@ -936,7 +934,7 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
: &other->to_read_initial_md_filled;
if (*destfilled || s->initial_md_sent) {
// The buffer is already in use; that's an error!
- INPROC_LOG(GPR_DEBUG, "Extra initial metadata %p", s);
+ INPROC_LOG(GPR_INFO, "Extra initial metadata %p", s);
error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Extra initial metadata");
} else {
if (!other || !other->closed) {
@@ -1013,7 +1011,7 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
true;
}
INPROC_LOG(
- GPR_DEBUG,
+ GPR_INFO,
"perform_stream_op error %p scheduling initial-metadata-ready %p",
s, error);
GRPC_CLOSURE_SCHED(
@@ -1022,14 +1020,14 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
}
if (op->recv_message) {
INPROC_LOG(
- GPR_DEBUG,
+ GPR_INFO,
"perform_stream_op error %p scheduling recv message-ready %p", s,
error);
GRPC_CLOSURE_SCHED(op->payload->recv_message.recv_message_ready,
GRPC_ERROR_REF(error));
}
}
- INPROC_LOG(GPR_DEBUG, "perform_stream_op %p scheduling on_complete %p", s,
+ INPROC_LOG(GPR_INFO, "perform_stream_op %p scheduling on_complete %p", s,
error);
GRPC_CLOSURE_SCHED(on_complete, GRPC_ERROR_REF(error));
}
@@ -1042,7 +1040,7 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
}
static void close_transport_locked(inproc_transport* t) {
- INPROC_LOG(GPR_DEBUG, "close_transport %p %d", t, t->is_closed);
+ INPROC_LOG(GPR_INFO, "close_transport %p %d", t, t->is_closed);
grpc_connectivity_state_set(
&t->connectivity, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Closing transport."),
@@ -1063,7 +1061,7 @@ static void close_transport_locked(inproc_transport* t) {
static void perform_transport_op(grpc_transport* gt, grpc_transport_op* op) {
inproc_transport* t = reinterpret_cast<inproc_transport*>(gt);
- INPROC_LOG(GPR_DEBUG, "perform_transport_op %p %p", t, op);
+ INPROC_LOG(GPR_INFO, "perform_transport_op %p %p", t, op);
gpr_mu_lock(&t->mu->mu);
if (op->on_connectivity_state_change) {
grpc_connectivity_state_notify_on_state_change(
@@ -1096,7 +1094,7 @@ static void perform_transport_op(grpc_transport* gt, grpc_transport_op* op) {
static void destroy_stream(grpc_transport* gt, grpc_stream* gs,
grpc_closure* then_schedule_closure) {
- INPROC_LOG(GPR_DEBUG, "destroy_stream %p %p", gs, then_schedule_closure);
+ INPROC_LOG(GPR_INFO, "destroy_stream %p %p", gs, then_schedule_closure);
inproc_stream* s = reinterpret_cast<inproc_stream*>(gs);
s->closure_at_destroy = then_schedule_closure;
really_destroy_stream(s);
@@ -1104,7 +1102,7 @@ static void destroy_stream(grpc_transport* gt, grpc_stream* gs,
static void destroy_transport(grpc_transport* gt) {
inproc_transport* t = reinterpret_cast<inproc_transport*>(gt);
- INPROC_LOG(GPR_DEBUG, "destroy_transport %p", t);
+ INPROC_LOG(GPR_INFO, "destroy_transport %p", t);
gpr_mu_lock(&t->mu->mu);
close_transport_locked(t);
gpr_mu_unlock(&t->mu->mu);
@@ -1165,7 +1163,7 @@ static void inproc_transports_create(grpc_transport** server_transport,
const grpc_channel_args* server_args,
grpc_transport** client_transport,
const grpc_channel_args* client_args) {
- INPROC_LOG(GPR_DEBUG, "inproc_transports_create");
+ INPROC_LOG(GPR_INFO, "inproc_transports_create");
inproc_transport* st =
static_cast<inproc_transport*>(gpr_zalloc(sizeof(*st)));
inproc_transport* ct =
diff --git a/src/core/lib/channel/channel_stack.cc b/src/core/lib/channel/channel_stack.cc
index a9459b150d..ef6482cb7f 100644
--- a/src/core/lib/channel/channel_stack.cc
+++ b/src/core/lib/channel/channel_stack.cc
@@ -193,18 +193,13 @@ void grpc_call_stack_set_pollset_or_pollset_set(grpc_call_stack* call_stack,
grpc_polling_entity* pollent) {
size_t count = call_stack->count;
grpc_call_element* call_elems;
- char* user_data;
size_t i;
call_elems = CALL_ELEMS_FROM_STACK(call_stack);
- user_data = (reinterpret_cast<char*>(call_elems)) +
- ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element));
/* init per-filter data */
for (i = 0; i < count; i++) {
call_elems[i].filter->set_pollset_or_pollset_set(&call_elems[i], pollent);
- user_data +=
- ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data);
}
}
diff --git a/src/core/lib/channel/channel_stack_builder.cc b/src/core/lib/channel/channel_stack_builder.cc
index 8a72449034..df5a783631 100644
--- a/src/core/lib/channel/channel_stack_builder.cc
+++ b/src/core/lib/channel/channel_stack_builder.cc
@@ -25,9 +25,6 @@
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
-grpc_core::TraceFlag grpc_trace_channel_stack_builder(false,
- "channel_stack_builder");
-
typedef struct filter_node {
struct filter_node* next;
struct filter_node* prev;
diff --git a/src/core/lib/channel/channel_stack_builder.h b/src/core/lib/channel/channel_stack_builder.h
index c9a170bc88..9196de9378 100644
--- a/src/core/lib/channel/channel_stack_builder.h
+++ b/src/core/lib/channel/channel_stack_builder.h
@@ -155,6 +155,4 @@ grpc_error* grpc_channel_stack_builder_finish(
/// Destroy the builder without creating a channel stack
void grpc_channel_stack_builder_destroy(grpc_channel_stack_builder* builder);
-extern grpc_core::TraceFlag grpc_trace_channel_stack_builder;
-
#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_BUILDER_H */
diff --git a/src/core/lib/channel/channel_trace.cc b/src/core/lib/channel/channel_trace.cc
index 654300cd32..eb7214b355 100644
--- a/src/core/lib/channel/channel_trace.cc
+++ b/src/core/lib/channel/channel_trace.cc
@@ -28,7 +28,7 @@
#include <stdlib.h>
#include <string.h>
-#include "src/core/lib/channel/channel_trace_registry.h"
+#include "src/core/lib/channel/channelz_registry.h"
#include "src/core/lib/channel/status_util.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gpr/useful.h"
@@ -70,7 +70,7 @@ ChannelTrace::ChannelTrace(size_t max_events)
tail_trace_(nullptr) {
if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0
gpr_mu_init(&tracer_mu_);
- channel_uuid_ = grpc_channel_trace_registry_register_channel_trace(this);
+ channel_uuid_ = ChannelzRegistry::Register(this);
time_created_ = grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(),
GPR_CLOCK_REALTIME);
}
@@ -83,7 +83,7 @@ ChannelTrace::~ChannelTrace() {
it = it->next();
Delete<TraceEvent>(to_free);
}
- grpc_channel_trace_registry_unregister_channel_trace(channel_uuid_);
+ ChannelzRegistry::Unregister(channel_uuid_);
gpr_mu_destroy(&tracer_mu_);
}
diff --git a/src/core/lib/channel/channel_trace_registry.cc b/src/core/lib/channel/channel_trace_registry.cc
deleted file mode 100644
index 6c82431467..0000000000
--- a/src/core/lib/channel/channel_trace_registry.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- *
- * Copyright 2017 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <grpc/impl/codegen/port_platform.h>
-
-#include "src/core/lib/avl/avl.h"
-#include "src/core/lib/channel/channel_trace.h"
-#include "src/core/lib/channel/channel_trace_registry.h"
-#include "src/core/lib/gpr/useful.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-// file global lock and avl.
-static gpr_mu g_mu;
-static grpc_avl g_avl;
-static gpr_atm g_uuid = 0;
-
-// avl vtable for uuid (intptr_t) -> ChannelTrace
-// this table is only looking, it does not own anything.
-static void destroy_intptr(void* not_used, void* user_data) {}
-static void* copy_intptr(void* key, void* user_data) { return key; }
-static long compare_intptr(void* key1, void* key2, void* user_data) {
- return GPR_ICMP(key1, key2);
-}
-
-static void destroy_channel_trace(void* trace, void* user_data) {}
-static void* copy_channel_trace(void* trace, void* user_data) { return trace; }
-static const grpc_avl_vtable avl_vtable = {
- destroy_intptr, copy_intptr, compare_intptr, destroy_channel_trace,
- copy_channel_trace};
-
-void grpc_channel_trace_registry_init() {
- gpr_mu_init(&g_mu);
- g_avl = grpc_avl_create(&avl_vtable);
-}
-
-void grpc_channel_trace_registry_shutdown() {
- grpc_avl_unref(g_avl, nullptr);
- gpr_mu_destroy(&g_mu);
-}
-
-intptr_t grpc_channel_trace_registry_register_channel_trace(
- grpc_core::ChannelTrace* channel_trace) {
- intptr_t prior = gpr_atm_no_barrier_fetch_add(&g_uuid, 1);
- gpr_mu_lock(&g_mu);
- g_avl = grpc_avl_add(g_avl, (void*)prior, channel_trace, nullptr);
- gpr_mu_unlock(&g_mu);
- return prior;
-}
-
-void grpc_channel_trace_registry_unregister_channel_trace(intptr_t uuid) {
- gpr_mu_lock(&g_mu);
- g_avl = grpc_avl_remove(g_avl, (void*)uuid, nullptr);
- gpr_mu_unlock(&g_mu);
-}
-
-grpc_core::ChannelTrace* grpc_channel_trace_registry_get_channel_trace(
- intptr_t uuid) {
- gpr_mu_lock(&g_mu);
- grpc_core::ChannelTrace* ret = static_cast<grpc_core::ChannelTrace*>(
- grpc_avl_get(g_avl, (void*)uuid, nullptr));
- gpr_mu_unlock(&g_mu);
- return ret;
-}
diff --git a/src/core/lib/channel/channel_trace_registry.h b/src/core/lib/channel/channel_trace_registry.h
deleted file mode 100644
index 391ecba7de..0000000000
--- a/src/core/lib/channel/channel_trace_registry.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *
- * Copyright 2017 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_REGISTRY_H
-#define GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_REGISTRY_H
-
-#include <grpc/impl/codegen/port_platform.h>
-
-#include "src/core/lib/channel/channel_trace.h"
-
-#include <stdint.h>
-
-// TODO(ncteisen): convert this file to C++
-
-void grpc_channel_trace_registry_init();
-void grpc_channel_trace_registry_shutdown();
-
-// globally registers a ChannelTrace. Returns its unique uuid
-intptr_t grpc_channel_trace_registry_register_channel_trace(
- grpc_core::ChannelTrace* channel_trace);
-// globally unregisters the ChannelTrace that is associated to uuid.
-void grpc_channel_trace_registry_unregister_channel_trace(intptr_t uuid);
-// if object with uuid has previously been registered, returns the ChannelTrace
-// associated with that uuid. Else returns nullptr.
-grpc_core::ChannelTrace* grpc_channel_trace_registry_get_channel_trace(
- intptr_t uuid);
-
-#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_REGISTRY_H */
diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc
new file mode 100644
index 0000000000..31d66e847a
--- /dev/null
+++ b/src/core/lib/channel/channelz_registry.cc
@@ -0,0 +1,77 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <grpc/impl/codegen/port_platform.h>
+
+#include "src/core/lib/channel/channel_trace.h"
+#include "src/core/lib/channel/channelz_registry.h"
+#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/memory.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+namespace grpc_core {
+namespace {
+
+// singleton instance of the registry.
+ChannelzRegistry* g_channelz_registry = nullptr;
+
+// avl vtable for uuid (intptr_t) -> channelz_obj (void*)
+// this table is only looking, it does not own anything.
+void destroy_intptr(void* not_used, void* user_data) {}
+void* copy_intptr(void* key, void* user_data) { return key; }
+long compare_intptr(void* key1, void* key2, void* user_data) {
+ return GPR_ICMP(key1, key2);
+}
+
+void destroy_channelz_obj(void* channelz_obj, void* user_data) {}
+void* copy_channelz_obj(void* channelz_obj, void* user_data) {
+ return channelz_obj;
+}
+const grpc_avl_vtable avl_vtable = {destroy_intptr, copy_intptr, compare_intptr,
+ destroy_channelz_obj, copy_channelz_obj};
+
+} // anonymous namespace
+
+void ChannelzRegistry::Init() { g_channelz_registry = New<ChannelzRegistry>(); }
+
+void ChannelzRegistry::Shutdown() { Delete(g_channelz_registry); }
+
+ChannelzRegistry* ChannelzRegistry::Default() {
+ GPR_DEBUG_ASSERT(g_channelz_registry != nullptr);
+ return g_channelz_registry;
+}
+
+ChannelzRegistry::ChannelzRegistry() : uuid_(1) {
+ gpr_mu_init(&mu_);
+ avl_ = grpc_avl_create(&avl_vtable);
+}
+
+ChannelzRegistry::~ChannelzRegistry() {
+ grpc_avl_unref(avl_, nullptr);
+ gpr_mu_destroy(&mu_);
+}
+
+void ChannelzRegistry::InternalUnregister(intptr_t uuid) {
+ gpr_mu_lock(&mu_);
+ avl_ = grpc_avl_remove(avl_, (void*)uuid, nullptr);
+ gpr_mu_unlock(&mu_);
+}
+
+} // namespace grpc_core
diff --git a/src/core/lib/channel/channelz_registry.h b/src/core/lib/channel/channelz_registry.h
new file mode 100644
index 0000000000..4de7d478c5
--- /dev/null
+++ b/src/core/lib/channel/channelz_registry.h
@@ -0,0 +1,99 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_CHANNEL_CHANNELZ_REGISTRY_H
+#define GRPC_CORE_LIB_CHANNEL_CHANNELZ_REGISTRY_H
+
+#include <grpc/impl/codegen/port_platform.h>
+
+#include "src/core/lib/avl/avl.h"
+#include "src/core/lib/channel/channel_trace.h"
+
+#include <stdint.h>
+
+namespace grpc_core {
+
+// singleton registry object to track all objects that are needed to support
+// channelz bookkeeping. All objects share globally distributed uuids.
+class ChannelzRegistry {
+ public:
+ // To be called in grpc_init()
+ static void Init();
+
+ // To be callen in grpc_shutdown();
+ static void Shutdown();
+
+ // globally registers a channelz Object. Returns its unique uuid
+ template <typename Object>
+ static intptr_t Register(Object* object) {
+ return Default()->InternalRegister(object);
+ }
+
+ // globally unregisters the object that is associated to uuid.
+ static void Unregister(intptr_t uuid) { Default()->InternalUnregister(uuid); }
+
+ // if object with uuid has previously been registered, returns the
+ // Object associated with that uuid. Else returns nullptr.
+ template <typename Object>
+ static Object* Get(intptr_t uuid) {
+ return Default()->InternalGet<Object>(uuid);
+ }
+
+ private:
+ GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW
+ GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
+
+ ChannelzRegistry();
+ ~ChannelzRegistry();
+
+ // Returned the singleton instance of ChannelzRegistry;
+ static ChannelzRegistry* Default();
+
+ // globally registers a channelz Object. Returns its unique uuid
+ template <typename Object>
+ intptr_t InternalRegister(Object* object) {
+ intptr_t prior = gpr_atm_no_barrier_fetch_add(&uuid_, 1);
+ gpr_mu_lock(&mu_);
+ avl_ = grpc_avl_add(avl_, (void*)prior, object, nullptr);
+ gpr_mu_unlock(&mu_);
+ return prior;
+ }
+
+ // globally unregisters the object that is associated to uuid.
+ void InternalUnregister(intptr_t uuid);
+
+ // if object with uuid has previously been registered, returns the
+ // Object associated with that uuid. Else returns nullptr.
+ template <typename Object>
+ Object* InternalGet(intptr_t uuid) {
+ gpr_mu_lock(&mu_);
+ Object* ret =
+ static_cast<Object*>(grpc_avl_get(avl_, (void*)uuid, nullptr));
+ gpr_mu_unlock(&mu_);
+ return ret;
+ }
+
+ // private members
+ gpr_mu mu_;
+ grpc_avl avl_;
+ gpr_atm uuid_;
+};
+
+} // namespace grpc_core
+
+#endif /* GRPC_CORE_LIB_CHANNEL_CHANNELZ_REGISTRY_H */
diff --git a/src/core/lib/channel/handshaker.cc b/src/core/lib/channel/handshaker.cc
index 9cd97823d4..86f8699e04 100644
--- a/src/core/lib/channel/handshaker.cc
+++ b/src/core/lib/channel/handshaker.cc
@@ -28,6 +28,7 @@
#include "src/core/lib/channel/handshaker.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/slice/slice_internal.h"
grpc_core::TraceFlag grpc_handshaker_trace(false, "handshaker");
@@ -137,7 +138,7 @@ void grpc_handshake_manager_add(grpc_handshake_manager* mgr,
grpc_handshaker* handshaker) {
if (grpc_handshaker_trace.enabled()) {
gpr_log(
- GPR_DEBUG,
+ GPR_INFO,
"handshake_manager %p: adding handshaker %s [%p] at index %" PRIuPTR,
mgr, grpc_handshaker_name(handshaker), handshaker, mgr->count);
}
@@ -208,7 +209,7 @@ static bool call_next_handshaker_locked(grpc_handshake_manager* mgr,
grpc_error* error) {
if (grpc_handshaker_trace.enabled()) {
char* args_str = handshaker_args_string(&mgr->args);
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"handshake_manager %p: error=%s shutdown=%d index=%" PRIuPTR
", args=%s",
mgr, grpc_error_string(error), mgr->shutdown, mgr->index, args_str);
@@ -220,8 +221,26 @@ static bool call_next_handshaker_locked(grpc_handshake_manager* mgr,
// callback. Otherwise, call the next handshaker.
if (error != GRPC_ERROR_NONE || mgr->shutdown || mgr->args.exit_early ||
mgr->index == mgr->count) {
+ if (error == GRPC_ERROR_NONE && mgr->shutdown) {
+ error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("handshaker shutdown");
+ // TODO(roth): It is currently necessary to shutdown endpoints
+ // before destroying then, even when we know that there are no
+ // pending read/write callbacks. This should be fixed, at which
+ // point this can be removed.
+ grpc_endpoint_shutdown(mgr->args.endpoint, GRPC_ERROR_REF(error));
+ grpc_endpoint_destroy(mgr->args.endpoint);
+ mgr->args.endpoint = nullptr;
+ grpc_channel_args_destroy(mgr->args.args);
+ mgr->args.args = nullptr;
+ grpc_slice_buffer_destroy_internal(mgr->args.read_buffer);
+ gpr_free(mgr->args.read_buffer);
+ mgr->args.read_buffer = nullptr;
+ }
if (grpc_handshaker_trace.enabled()) {
- gpr_log(GPR_DEBUG, "handshake_manager %p: handshaking complete", mgr);
+ gpr_log(GPR_INFO,
+ "handshake_manager %p: handshaking complete -- scheduling "
+ "on_handshake_done with error=%s",
+ mgr, grpc_error_string(error));
}
// Cancel deadline timer, since we're invoking the on_handshake_done
// callback now.
@@ -231,7 +250,7 @@ static bool call_next_handshaker_locked(grpc_handshake_manager* mgr,
} else {
if (grpc_handshaker_trace.enabled()) {
gpr_log(
- GPR_DEBUG,
+ GPR_INFO,
"handshake_manager %p: calling handshaker %s [%p] at index %" PRIuPTR,
mgr, grpc_handshaker_name(mgr->handshakers[mgr->index]),
mgr->handshakers[mgr->index], mgr->index);
diff --git a/src/core/lib/debug/stats.h b/src/core/lib/debug/stats.h
index 749665262a..9e88ad7000 100644
--- a/src/core/lib/debug/stats.h
+++ b/src/core/lib/debug/stats.h
@@ -35,6 +35,9 @@ extern grpc_stats_data* grpc_stats_per_cpu_storage;
#define GRPC_THREAD_STATS_DATA() \
(&grpc_stats_per_cpu_storage[grpc_core::ExecCtx::Get()->starting_cpu()])
+/* Only collect stats if GRPC_COLLECT_STATS is defined or it is a debug build.
+ */
+#if defined(GRPC_COLLECT_STATS) || !defined(NDEBUG)
#define GRPC_STATS_INC_COUNTER(ctr) \
(gpr_atm_no_barrier_fetch_add(&GRPC_THREAD_STATS_DATA()->counters[(ctr)], 1))
@@ -42,6 +45,10 @@ extern grpc_stats_data* grpc_stats_per_cpu_storage;
(gpr_atm_no_barrier_fetch_add( \
&GRPC_THREAD_STATS_DATA()->histograms[histogram##_FIRST_SLOT + (index)], \
1))
+#else /* defined(GRPC_COLLECT_STATS) || !defined(NDEBUG) */
+#define GRPC_STATS_INC_COUNTER(ctr)
+#define GRPC_STATS_INC_HISTOGRAM(histogram, index)
+#endif /* defined(GRPC_COLLECT_STATS) || !defined(NDEBUG) */
void grpc_stats_init(void);
void grpc_stats_shutdown(void);
diff --git a/src/core/lib/debug/stats_data.cc b/src/core/lib/debug/stats_data.cc
index 309ece94bb..f8c27db0a8 100644
--- a/src/core/lib/debug/stats_data.cc
+++ b/src/core/lib/debug/stats_data.cc
@@ -40,6 +40,8 @@ const char* grpc_stats_counter_name[GRPC_STATS_COUNTER_COUNT] = {
"pollset_kick_wakeup_fd",
"pollset_kick_wakeup_cv",
"pollset_kick_own_thread",
+ "syscall_epoll_ctl",
+ "pollset_fd_cache_hits",
"histogram_slow_lookups",
"syscall_write",
"syscall_read",
@@ -144,6 +146,9 @@ const char* grpc_stats_counter_doc[GRPC_STATS_COUNTER_COUNT] = {
"polling wakeup (only valid for epoll1 right now)",
"How many times could a polling wakeup be satisfied by keeping the waking "
"thread awake? (only valid for epoll1 right now)",
+ "Number of epoll_ctl calls made (only valid for epollex right now)",
+ "Number of epoll_ctl calls skipped because the fd was cached as already "
+ "being added. (only valid for epollex right now)",
"Number of times histogram increments went through the slow (binary "
"search) path",
"Number of write syscalls (or equivalent - eg sendmsg) made by this "
diff --git a/src/core/lib/debug/stats_data.h b/src/core/lib/debug/stats_data.h
index da1266ad73..1f3861f494 100644
--- a/src/core/lib/debug/stats_data.h
+++ b/src/core/lib/debug/stats_data.h
@@ -41,6 +41,8 @@ typedef enum {
GRPC_STATS_COUNTER_POLLSET_KICK_WAKEUP_FD,
GRPC_STATS_COUNTER_POLLSET_KICK_WAKEUP_CV,
GRPC_STATS_COUNTER_POLLSET_KICK_OWN_THREAD,
+ GRPC_STATS_COUNTER_SYSCALL_EPOLL_CTL,
+ GRPC_STATS_COUNTER_POLLSET_FD_CACHE_HITS,
GRPC_STATS_COUNTER_HISTOGRAM_SLOW_LOOKUPS,
GRPC_STATS_COUNTER_SYSCALL_WRITE,
GRPC_STATS_COUNTER_SYSCALL_READ,
@@ -174,6 +176,7 @@ typedef enum {
GRPC_STATS_HISTOGRAM_SERVER_CQS_CHECKED_BUCKETS = 8,
GRPC_STATS_HISTOGRAM_BUCKETS = 840
} grpc_stats_histogram_constants;
+#if defined(GRPC_COLLECT_STATS) || !defined(NDEBUG)
#define GRPC_STATS_INC_CLIENT_CALLS_CREATED() \
GRPC_STATS_INC_COUNTER(GRPC_STATS_COUNTER_CLIENT_CALLS_CREATED)
#define GRPC_STATS_INC_SERVER_CALLS_CREATED() \
@@ -202,6 +205,10 @@ typedef enum {
GRPC_STATS_INC_COUNTER(GRPC_STATS_COUNTER_POLLSET_KICK_WAKEUP_CV)
#define GRPC_STATS_INC_POLLSET_KICK_OWN_THREAD() \
GRPC_STATS_INC_COUNTER(GRPC_STATS_COUNTER_POLLSET_KICK_OWN_THREAD)
+#define GRPC_STATS_INC_SYSCALL_EPOLL_CTL() \
+ GRPC_STATS_INC_COUNTER(GRPC_STATS_COUNTER_SYSCALL_EPOLL_CTL)
+#define GRPC_STATS_INC_POLLSET_FD_CACHE_HITS() \
+ GRPC_STATS_INC_COUNTER(GRPC_STATS_COUNTER_POLLSET_FD_CACHE_HITS)
#define GRPC_STATS_INC_HISTOGRAM_SLOW_LOOKUPS() \
GRPC_STATS_INC_COUNTER(GRPC_STATS_COUNTER_HISTOGRAM_SLOW_LOOKUPS)
#define GRPC_STATS_INC_SYSCALL_WRITE() \
@@ -427,6 +434,119 @@ void grpc_stats_inc_http2_send_flowctl_per_write(int x);
#define GRPC_STATS_INC_SERVER_CQS_CHECKED(value) \
grpc_stats_inc_server_cqs_checked((int)(value))
void grpc_stats_inc_server_cqs_checked(int x);
+#else
+#define GRPC_STATS_INC_CLIENT_CALLS_CREATED()
+#define GRPC_STATS_INC_SERVER_CALLS_CREATED()
+#define GRPC_STATS_INC_CQS_CREATED()
+#define GRPC_STATS_INC_CLIENT_CHANNELS_CREATED()
+#define GRPC_STATS_INC_CLIENT_SUBCHANNELS_CREATED()
+#define GRPC_STATS_INC_SERVER_CHANNELS_CREATED()
+#define GRPC_STATS_INC_SYSCALL_POLL()
+#define GRPC_STATS_INC_SYSCALL_WAIT()
+#define GRPC_STATS_INC_POLLSET_KICK()
+#define GRPC_STATS_INC_POLLSET_KICKED_WITHOUT_POLLER()
+#define GRPC_STATS_INC_POLLSET_KICKED_AGAIN()
+#define GRPC_STATS_INC_POLLSET_KICK_WAKEUP_FD()
+#define GRPC_STATS_INC_POLLSET_KICK_WAKEUP_CV()
+#define GRPC_STATS_INC_POLLSET_KICK_OWN_THREAD()
+#define GRPC_STATS_INC_SYSCALL_EPOLL_CTL()
+#define GRPC_STATS_INC_POLLSET_FD_CACHE_HITS()
+#define GRPC_STATS_INC_HISTOGRAM_SLOW_LOOKUPS()
+#define GRPC_STATS_INC_SYSCALL_WRITE()
+#define GRPC_STATS_INC_SYSCALL_READ()
+#define GRPC_STATS_INC_TCP_BACKUP_POLLERS_CREATED()
+#define GRPC_STATS_INC_TCP_BACKUP_POLLER_POLLS()
+#define GRPC_STATS_INC_HTTP2_OP_BATCHES()
+#define GRPC_STATS_INC_HTTP2_OP_CANCEL()
+#define GRPC_STATS_INC_HTTP2_OP_SEND_INITIAL_METADATA()
+#define GRPC_STATS_INC_HTTP2_OP_SEND_MESSAGE()
+#define GRPC_STATS_INC_HTTP2_OP_SEND_TRAILING_METADATA()
+#define GRPC_STATS_INC_HTTP2_OP_RECV_INITIAL_METADATA()
+#define GRPC_STATS_INC_HTTP2_OP_RECV_MESSAGE()
+#define GRPC_STATS_INC_HTTP2_OP_RECV_TRAILING_METADATA()
+#define GRPC_STATS_INC_HTTP2_SETTINGS_WRITES()
+#define GRPC_STATS_INC_HTTP2_PINGS_SENT()
+#define GRPC_STATS_INC_HTTP2_WRITES_BEGUN()
+#define GRPC_STATS_INC_HTTP2_WRITES_OFFLOADED()
+#define GRPC_STATS_INC_HTTP2_WRITES_CONTINUED()
+#define GRPC_STATS_INC_HTTP2_PARTIAL_WRITES()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_INITIAL_WRITE()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_START_NEW_STREAM()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_MESSAGE()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_INITIAL_METADATA()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_TRAILING_METADATA()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_RETRY_SEND_PING()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_CONTINUE_PINGS()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_GOAWAY_SENT()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_RST_STREAM()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_CLOSE_FROM_API()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_STREAM_FLOW_CONTROL()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_TRANSPORT_FLOW_CONTROL()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_SETTINGS()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_BDP_ESTIMATOR_PING()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_FLOW_CONTROL_UNSTALLED_BY_SETTING()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_FLOW_CONTROL_UNSTALLED_BY_UPDATE()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_APPLICATION_PING()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_KEEPALIVE_PING()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_TRANSPORT_FLOW_CONTROL_UNSTALLED()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_PING_RESPONSE()
+#define GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_FORCE_RST_STREAM()
+#define GRPC_STATS_INC_HTTP2_SPURIOUS_WRITES_BEGUN()
+#define GRPC_STATS_INC_HPACK_RECV_INDEXED()
+#define GRPC_STATS_INC_HPACK_RECV_LITHDR_INCIDX()
+#define GRPC_STATS_INC_HPACK_RECV_LITHDR_INCIDX_V()
+#define GRPC_STATS_INC_HPACK_RECV_LITHDR_NOTIDX()
+#define GRPC_STATS_INC_HPACK_RECV_LITHDR_NOTIDX_V()
+#define GRPC_STATS_INC_HPACK_RECV_LITHDR_NVRIDX()
+#define GRPC_STATS_INC_HPACK_RECV_LITHDR_NVRIDX_V()
+#define GRPC_STATS_INC_HPACK_RECV_UNCOMPRESSED()
+#define GRPC_STATS_INC_HPACK_RECV_HUFFMAN()
+#define GRPC_STATS_INC_HPACK_RECV_BINARY()
+#define GRPC_STATS_INC_HPACK_RECV_BINARY_BASE64()
+#define GRPC_STATS_INC_HPACK_SEND_INDEXED()
+#define GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX()
+#define GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX_V()
+#define GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX()
+#define GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX_V()
+#define GRPC_STATS_INC_HPACK_SEND_LITHDR_NVRIDX()
+#define GRPC_STATS_INC_HPACK_SEND_LITHDR_NVRIDX_V()
+#define GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED()
+#define GRPC_STATS_INC_HPACK_SEND_HUFFMAN()
+#define GRPC_STATS_INC_HPACK_SEND_BINARY()
+#define GRPC_STATS_INC_HPACK_SEND_BINARY_BASE64()
+#define GRPC_STATS_INC_COMBINER_LOCKS_INITIATED()
+#define GRPC_STATS_INC_COMBINER_LOCKS_SCHEDULED_ITEMS()
+#define GRPC_STATS_INC_COMBINER_LOCKS_SCHEDULED_FINAL_ITEMS()
+#define GRPC_STATS_INC_COMBINER_LOCKS_OFFLOADED()
+#define GRPC_STATS_INC_CALL_COMBINER_LOCKS_INITIATED()
+#define GRPC_STATS_INC_CALL_COMBINER_LOCKS_SCHEDULED_ITEMS()
+#define GRPC_STATS_INC_CALL_COMBINER_SET_NOTIFY_ON_CANCEL()
+#define GRPC_STATS_INC_CALL_COMBINER_CANCELLED()
+#define GRPC_STATS_INC_EXECUTOR_SCHEDULED_SHORT_ITEMS()
+#define GRPC_STATS_INC_EXECUTOR_SCHEDULED_LONG_ITEMS()
+#define GRPC_STATS_INC_EXECUTOR_SCHEDULED_TO_SELF()
+#define GRPC_STATS_INC_EXECUTOR_WAKEUP_INITIATED()
+#define GRPC_STATS_INC_EXECUTOR_QUEUE_DRAINED()
+#define GRPC_STATS_INC_EXECUTOR_PUSH_RETRIES()
+#define GRPC_STATS_INC_SERVER_REQUESTED_CALLS()
+#define GRPC_STATS_INC_SERVER_SLOWPATH_REQUESTS_QUEUED()
+#define GRPC_STATS_INC_CQ_EV_QUEUE_TRYLOCK_FAILURES()
+#define GRPC_STATS_INC_CQ_EV_QUEUE_TRYLOCK_SUCCESSES()
+#define GRPC_STATS_INC_CQ_EV_QUEUE_TRANSIENT_POP_FAILURES()
+#define GRPC_STATS_INC_CALL_INITIAL_SIZE(value)
+#define GRPC_STATS_INC_POLL_EVENTS_RETURNED(value)
+#define GRPC_STATS_INC_TCP_WRITE_SIZE(value)
+#define GRPC_STATS_INC_TCP_WRITE_IOV_SIZE(value)
+#define GRPC_STATS_INC_TCP_READ_SIZE(value)
+#define GRPC_STATS_INC_TCP_READ_OFFER(value)
+#define GRPC_STATS_INC_TCP_READ_OFFER_IOV_SIZE(value)
+#define GRPC_STATS_INC_HTTP2_SEND_MESSAGE_SIZE(value)
+#define GRPC_STATS_INC_HTTP2_SEND_INITIAL_METADATA_PER_WRITE(value)
+#define GRPC_STATS_INC_HTTP2_SEND_MESSAGE_PER_WRITE(value)
+#define GRPC_STATS_INC_HTTP2_SEND_TRAILING_METADATA_PER_WRITE(value)
+#define GRPC_STATS_INC_HTTP2_SEND_FLOWCTL_PER_WRITE(value)
+#define GRPC_STATS_INC_SERVER_CQS_CHECKED(value)
+#endif /* defined(GRPC_COLLECT_STATS) || !defined(NDEBUG) */
extern const int grpc_stats_histo_buckets[13];
extern const int grpc_stats_histo_start[13];
extern const int* const grpc_stats_histo_bucket_boundaries[13];
diff --git a/src/core/lib/debug/stats_data.yaml b/src/core/lib/debug/stats_data.yaml
index af4553028e..775b09df74 100644
--- a/src/core/lib/debug/stats_data.yaml
+++ b/src/core/lib/debug/stats_data.yaml
@@ -63,6 +63,12 @@
doc: How many times could a polling wakeup be satisfied by keeping the waking
thread awake?
(only valid for epoll1 right now)
+# polling
+- counter: syscall_epoll_ctl
+ doc: Number of epoll_ctl calls made (only valid for epollex right now)
+- counter: pollset_fd_cache_hits
+ doc: Number of epoll_ctl calls skipped because the fd was cached as
+ already being added. (only valid for epollex right now)
# stats system
- counter: histogram_slow_lookups
doc: Number of times histogram increments went through the slow
diff --git a/src/core/lib/debug/stats_data_bq_schema.sql b/src/core/lib/debug/stats_data_bq_schema.sql
index 04b6d471f6..7d1ab1dae9 100644
--- a/src/core/lib/debug/stats_data_bq_schema.sql
+++ b/src/core/lib/debug/stats_data_bq_schema.sql
@@ -12,6 +12,8 @@ pollset_kicked_again_per_iteration:FLOAT,
pollset_kick_wakeup_fd_per_iteration:FLOAT,
pollset_kick_wakeup_cv_per_iteration:FLOAT,
pollset_kick_own_thread_per_iteration:FLOAT,
+syscall_epoll_ctl_per_iteration:FLOAT,
+pollset_fd_cache_hits_per_iteration:FLOAT,
histogram_slow_lookups_per_iteration:FLOAT,
syscall_write_per_iteration:FLOAT,
syscall_read_per_iteration:FLOAT,
diff --git a/src/core/lib/debug/trace.h b/src/core/lib/debug/trace.h
index bfec92c529..28157c6383 100644
--- a/src/core/lib/debug/trace.h
+++ b/src/core/lib/debug/trace.h
@@ -57,13 +57,22 @@ class TraceFlag {
const char* name() const { return name_; }
+// This following define may be commented out to ensure that the compiler
+// deletes any "if (tracer.enabled()) {...}" codeblocks. This is useful to
+// test the performance impact tracers have on the system.
+//
+// #define COMPILE_OUT_ALL_TRACERS_IN_OPT_BUILD
+#ifdef COMPILE_OUT_ALL_TRACERS_IN_OPT_BUILD
+ bool enabled() { return false; }
+#else
bool enabled() {
#ifdef GRPC_THREADSAFE_TRACER
return gpr_atm_no_barrier_load(&value_) != 0;
#else
return value_;
-#endif
+#endif // GRPC_THREADSAFE_TRACER
}
+#endif // COMPILE_OUT_ALL_TRACERS_IN_OPT_BUILD
private:
friend void grpc_core::testing::grpc_tracer_enable_flag(TraceFlag* flag);
diff --git a/src/core/lib/gpr/fork.cc b/src/core/lib/gpr/fork.cc
deleted file mode 100644
index 812522b058..0000000000
--- a/src/core/lib/gpr/fork.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- *
- * Copyright 2017 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/lib/gpr/fork.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-
-#include "src/core/lib/gpr/env.h"
-#include "src/core/lib/gpr/useful.h"
-
-/*
- * NOTE: FORKING IS NOT GENERALLY SUPPORTED, THIS IS ONLY INTENDED TO WORK
- * AROUND VERY SPECIFIC USE CASES.
- */
-
-static int override_fork_support_enabled = -1;
-static int fork_support_enabled;
-
-void grpc_fork_support_init() {
-#ifdef GRPC_ENABLE_FORK_SUPPORT
- fork_support_enabled = 1;
-#else
- fork_support_enabled = 0;
-#endif
- bool env_var_set = false;
- char* env = gpr_getenv("GRPC_ENABLE_FORK_SUPPORT");
- if (env != nullptr) {
- static const char* truthy[] = {"yes", "Yes", "YES", "true",
- "True", "TRUE", "1"};
- static const char* falsey[] = {"no", "No", "NO", "false",
- "False", "FALSE", "0"};
- for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) {
- if (0 == strcmp(env, truthy[i])) {
- fork_support_enabled = 1;
- env_var_set = true;
- break;
- }
- }
- if (!env_var_set) {
- for (size_t i = 0; i < GPR_ARRAY_SIZE(falsey); i++) {
- if (0 == strcmp(env, falsey[i])) {
- fork_support_enabled = 0;
- env_var_set = true;
- break;
- }
- }
- }
- gpr_free(env);
- }
- if (override_fork_support_enabled != -1) {
- fork_support_enabled = override_fork_support_enabled;
- }
-}
-
-int grpc_fork_support_enabled() { return fork_support_enabled; }
-
-void grpc_enable_fork_support(int enable) {
- override_fork_support_enabled = enable;
-}
diff --git a/src/core/lib/gpr/fork.h b/src/core/lib/gpr/fork.h
deleted file mode 100644
index 94c61bb836..0000000000
--- a/src/core/lib/gpr/fork.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *
- * Copyright 2017 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef GRPC_CORE_LIB_GPR_FORK_H
-#define GRPC_CORE_LIB_GPR_FORK_H
-
-/*
- * NOTE: FORKING IS NOT GENERALLY SUPPORTED, THIS IS ONLY INTENDED TO WORK
- * AROUND VERY SPECIFIC USE CASES.
- */
-
-void grpc_fork_support_init(void);
-
-int grpc_fork_support_enabled(void);
-
-// Test only: Must be called before grpc_init(), and overrides
-// environment variables/compile flags
-void grpc_enable_fork_support(int enable);
-
-#endif /* GRPC_CORE_LIB_GPR_FORK_H */
diff --git a/src/core/lib/gprpp/fork.cc b/src/core/lib/gprpp/fork.cc
new file mode 100644
index 0000000000..f6d9a87d2c
--- /dev/null
+++ b/src/core/lib/gprpp/fork.cc
@@ -0,0 +1,260 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/lib/gprpp/fork.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/time.h>
+
+#include "src/core/lib/gpr/env.h"
+#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/memory.h"
+
+/*
+ * NOTE: FORKING IS NOT GENERALLY SUPPORTED, THIS IS ONLY INTENDED TO WORK
+ * AROUND VERY SPECIFIC USE CASES.
+ */
+
+namespace grpc_core {
+namespace internal {
+// The exec_ctx_count has 2 modes, blocked and unblocked.
+// When unblocked, the count is 2-indexed; exec_ctx_count=2 indicates
+// 0 active ExecCtxs, exex_ctx_count=3 indicates 1 active ExecCtxs...
+
+// When blocked, the exec_ctx_count is 0-indexed. Note that ExecCtx
+// creation can only be blocked if there is exactly 1 outstanding ExecCtx,
+// meaning that BLOCKED and UNBLOCKED counts partition the integers
+#define UNBLOCKED(n) (n + 2)
+#define BLOCKED(n) (n)
+
+class ExecCtxState {
+ public:
+ ExecCtxState() : fork_complete_(true) {
+ gpr_mu_init(&mu_);
+ gpr_cv_init(&cv_);
+ gpr_atm_no_barrier_store(&count_, UNBLOCKED(0));
+ }
+
+ void IncExecCtxCount() {
+ gpr_atm count = gpr_atm_no_barrier_load(&count_);
+ while (true) {
+ if (count <= BLOCKED(1)) {
+ // This only occurs if we are trying to fork. Wait until the fork()
+ // operation completes before allowing new ExecCtxs.
+ gpr_mu_lock(&mu_);
+ if (gpr_atm_no_barrier_load(&count_) <= BLOCKED(1)) {
+ while (!fork_complete_) {
+ gpr_cv_wait(&cv_, &mu_, gpr_inf_future(GPR_CLOCK_REALTIME));
+ }
+ }
+ gpr_mu_unlock(&mu_);
+ } else if (gpr_atm_no_barrier_cas(&count_, count, count + 1)) {
+ break;
+ }
+ count = gpr_atm_no_barrier_load(&count_);
+ }
+ }
+
+ void DecExecCtxCount() { gpr_atm_no_barrier_fetch_add(&count_, -1); }
+
+ bool BlockExecCtx() {
+ // Assumes there is an active ExecCtx when this function is called
+ if (gpr_atm_no_barrier_cas(&count_, UNBLOCKED(1), BLOCKED(1))) {
+ gpr_mu_lock(&mu_);
+ fork_complete_ = false;
+ gpr_mu_unlock(&mu_);
+ return true;
+ }
+ return false;
+ }
+
+ void AllowExecCtx() {
+ gpr_mu_lock(&mu_);
+ gpr_atm_no_barrier_store(&count_, UNBLOCKED(0));
+ fork_complete_ = true;
+ gpr_cv_broadcast(&cv_);
+ gpr_mu_unlock(&mu_);
+ }
+
+ ~ExecCtxState() {
+ gpr_mu_destroy(&mu_);
+ gpr_cv_destroy(&cv_);
+ }
+
+ private:
+ bool fork_complete_;
+ gpr_mu mu_;
+ gpr_cv cv_;
+ gpr_atm count_;
+};
+
+class ThreadState {
+ public:
+ ThreadState() : awaiting_threads_(false), threads_done_(false), count_(0) {
+ gpr_mu_init(&mu_);
+ gpr_cv_init(&cv_);
+ }
+
+ void IncThreadCount() {
+ gpr_mu_lock(&mu_);
+ count_++;
+ gpr_mu_unlock(&mu_);
+ }
+
+ void DecThreadCount() {
+ gpr_mu_lock(&mu_);
+ count_--;
+ if (awaiting_threads_ && count_ == 0) {
+ threads_done_ = true;
+ gpr_cv_signal(&cv_);
+ }
+ gpr_mu_unlock(&mu_);
+ }
+ void AwaitThreads() {
+ gpr_mu_lock(&mu_);
+ awaiting_threads_ = true;
+ threads_done_ = (count_ == 0);
+ while (!threads_done_) {
+ gpr_cv_wait(&cv_, &mu_, gpr_inf_future(GPR_CLOCK_REALTIME));
+ }
+ awaiting_threads_ = true;
+ gpr_mu_unlock(&mu_);
+ }
+
+ ~ThreadState() {
+ gpr_mu_destroy(&mu_);
+ gpr_cv_destroy(&cv_);
+ }
+
+ private:
+ bool awaiting_threads_;
+ bool threads_done_;
+ gpr_mu mu_;
+ gpr_cv cv_;
+ int count_;
+};
+
+} // namespace
+
+void Fork::GlobalInit() {
+ if (!overrideEnabled_) {
+#ifdef GRPC_ENABLE_FORK_SUPPORT
+ supportEnabled_ = true;
+#else
+ supportEnabled_ = false;
+#endif
+ bool env_var_set = false;
+ char* env = gpr_getenv("GRPC_ENABLE_FORK_SUPPORT");
+ if (env != nullptr) {
+ static const char* truthy[] = {"yes", "Yes", "YES", "true",
+ "True", "TRUE", "1"};
+ static const char* falsey[] = {"no", "No", "NO", "false",
+ "False", "FALSE", "0"};
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) {
+ if (0 == strcmp(env, truthy[i])) {
+ supportEnabled_ = true;
+ env_var_set = true;
+ break;
+ }
+ }
+ if (!env_var_set) {
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(falsey); i++) {
+ if (0 == strcmp(env, falsey[i])) {
+ supportEnabled_ = false;
+ env_var_set = true;
+ break;
+ }
+ }
+ }
+ gpr_free(env);
+ }
+ }
+ if (supportEnabled_) {
+ execCtxState_ = grpc_core::New<internal::ExecCtxState>();
+ threadState_ = grpc_core::New<internal::ThreadState>();
+ }
+}
+
+void Fork::GlobalShutdown() {
+ if (supportEnabled_) {
+ grpc_core::Delete(execCtxState_);
+ grpc_core::Delete(threadState_);
+ }
+}
+
+bool Fork::Enabled() { return supportEnabled_; }
+
+// Testing Only
+void Fork::Enable(bool enable) {
+ overrideEnabled_ = true;
+ supportEnabled_ = enable;
+}
+
+void Fork::IncExecCtxCount() {
+ if (supportEnabled_) {
+ execCtxState_->IncExecCtxCount();
+ }
+}
+
+void Fork::DecExecCtxCount() {
+ if (supportEnabled_) {
+ execCtxState_->DecExecCtxCount();
+ }
+}
+
+bool Fork::BlockExecCtx() {
+ if (supportEnabled_) {
+ return execCtxState_->BlockExecCtx();
+ }
+ return false;
+}
+
+void Fork::AllowExecCtx() {
+ if (supportEnabled_) {
+ execCtxState_->AllowExecCtx();
+ }
+}
+
+void Fork::IncThreadCount() {
+ if (supportEnabled_) {
+ threadState_->IncThreadCount();
+ }
+}
+
+void Fork::DecThreadCount() {
+ if (supportEnabled_) {
+ threadState_->DecThreadCount();
+ }
+}
+void Fork::AwaitThreads() {
+ if (supportEnabled_) {
+ threadState_->AwaitThreads();
+ }
+}
+
+internal::ExecCtxState* Fork::execCtxState_ = nullptr;
+internal::ThreadState* Fork::threadState_ = nullptr;
+bool Fork::supportEnabled_ = false;
+bool Fork::overrideEnabled_ = false;
+
+} // namespace grpc_core
diff --git a/src/core/lib/gprpp/fork.h b/src/core/lib/gprpp/fork.h
new file mode 100644
index 0000000000..123e22c4c6
--- /dev/null
+++ b/src/core/lib/gprpp/fork.h
@@ -0,0 +1,79 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_GPRPP_FORK_H
+#define GRPC_CORE_LIB_GPRPP_FORK_H
+
+/*
+ * NOTE: FORKING IS NOT GENERALLY SUPPORTED, THIS IS ONLY INTENDED TO WORK
+ * AROUND VERY SPECIFIC USE CASES.
+ */
+
+namespace grpc_core {
+
+namespace internal {
+class ExecCtxState;
+class ThreadState;
+} // namespace internal
+
+class Fork {
+ public:
+ static void GlobalInit();
+ static void GlobalShutdown();
+
+ // Returns true if fork suppport is enabled, false otherwise
+ static bool Enabled();
+
+ // Increment the count of active ExecCtxs.
+ // Will block until a pending fork is complete if one is in progress.
+ static void IncExecCtxCount();
+
+ // Decrement the count of active ExecCtxs
+ static void DecExecCtxCount();
+
+ // Check if there is a single active ExecCtx
+ // (the one used to invoke this function). If there are more,
+ // return false. Otherwise, return true and block creation of
+ // more ExecCtx s until AlloWExecCtx() is called
+ //
+ static bool BlockExecCtx();
+ static void AllowExecCtx();
+
+ // Increment the count of active threads.
+ static void IncThreadCount();
+
+ // Decrement the count of active threads.
+ static void DecThreadCount();
+
+ // Await all core threads to be joined.
+ static void AwaitThreads();
+
+ // Test only: overrides environment variables/compile flags
+ // Must be called before grpc_init()
+ static void Enable(bool enable);
+
+ private:
+ static internal::ExecCtxState* execCtxState_;
+ static internal::ThreadState* threadState_;
+ static bool supportEnabled_;
+ static bool overrideEnabled_;
+};
+
+} // namespace grpc_core
+
+#endif /* GRPC_CORE_LIB_GPRPP_FORK_H */
diff --git a/src/core/lib/gprpp/memory.h b/src/core/lib/gprpp/memory.h
index ba2f546675..28fcdf1779 100644
--- a/src/core/lib/gprpp/memory.h
+++ b/src/core/lib/gprpp/memory.h
@@ -27,6 +27,17 @@
#include <memory>
#include <utility>
+// Add this to a class that want to use Delete(), but has a private or
+// protected destructor.
+#define GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE \
+ template <typename T> \
+ friend void Delete(T*);
+// Add this to a class that want to use New(), but has a private or
+// protected constructor.
+#define GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW \
+ template <typename T, typename... Args> \
+ friend T* New(Args&&...);
+
namespace grpc_core {
// The alignment of memory returned by gpr_malloc().
@@ -44,6 +55,7 @@ inline T* New(Args&&... args) {
// Alternative to delete, since we cannot use it (for fear of libstdc++)
template <typename T>
inline void Delete(T* p) {
+ if (p == nullptr) return;
p->~T();
if (alignof(T) > kAlignmentForDefaultAllocationInBytes) {
gpr_free_aligned(p);
diff --git a/src/core/lib/gprpp/orphanable.h b/src/core/lib/gprpp/orphanable.h
index a5bc8d8efc..d0ec9b6461 100644
--- a/src/core/lib/gprpp/orphanable.h
+++ b/src/core/lib/gprpp/orphanable.h
@@ -83,9 +83,7 @@ class InternallyRefCounted : public Orphanable {
GRPC_ABSTRACT_BASE_CLASS
protected:
- // Allow Delete() to access destructor.
- template <typename T>
- friend void Delete(T*);
+ GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
// Allow RefCountedPtr<> to access Unref() and IncrementRefCount().
friend class RefCountedPtr<Child>;
@@ -100,7 +98,7 @@ class InternallyRefCounted : public Orphanable {
void Unref() {
if (gpr_unref(&refs_)) {
- Delete(this);
+ Delete(static_cast<Child*>(this));
}
}
@@ -128,9 +126,7 @@ class InternallyRefCountedWithTracing : public Orphanable {
GRPC_ABSTRACT_BASE_CLASS
protected:
- // Allow Delete() to access destructor.
- template <typename T>
- friend void Delete(T*);
+ GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
// Allow RefCountedPtr<> to access Unref() and IncrementRefCount().
friend class RefCountedPtr<Child>;
@@ -159,7 +155,7 @@ class InternallyRefCountedWithTracing : public Orphanable {
const char* reason) GRPC_MUST_USE_RESULT {
if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) {
gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count);
- gpr_log(GPR_DEBUG, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s",
+ gpr_log(GPR_INFO, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s",
trace_flag_->name(), this, location.file(), location.line(),
old_refs, old_refs + 1, reason);
}
@@ -173,14 +169,14 @@ class InternallyRefCountedWithTracing : public Orphanable {
void Unref() {
if (gpr_unref(&refs_)) {
- Delete(this);
+ Delete(static_cast<Child*>(this));
}
}
void Unref(const DebugLocation& location, const char* reason) {
if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) {
gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count);
- gpr_log(GPR_DEBUG, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s",
+ gpr_log(GPR_INFO, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s",
trace_flag_->name(), this, location.file(), location.line(),
old_refs, old_refs - 1, reason);
}
diff --git a/src/core/lib/gprpp/ref_counted.h b/src/core/lib/gprpp/ref_counted.h
index 46bfaf7fb8..ddac5bd475 100644
--- a/src/core/lib/gprpp/ref_counted.h
+++ b/src/core/lib/gprpp/ref_counted.h
@@ -54,7 +54,7 @@ class RefCounted {
// friend of this class.
void Unref() {
if (gpr_unref(&refs_)) {
- Delete(this);
+ Delete(static_cast<Child*>(this));
}
}
@@ -65,9 +65,7 @@ class RefCounted {
GRPC_ABSTRACT_BASE_CLASS
protected:
- // Allow Delete() to access destructor.
- template <typename T>
- friend void Delete(T*);
+ GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
RefCounted() { gpr_ref_init(&refs_, 1); }
@@ -100,7 +98,7 @@ class RefCountedWithTracing {
const char* reason) GRPC_MUST_USE_RESULT {
if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) {
gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count);
- gpr_log(GPR_DEBUG, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s",
+ gpr_log(GPR_INFO, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s",
trace_flag_->name(), this, location.file(), location.line(),
old_refs, old_refs + 1, reason);
}
@@ -114,14 +112,14 @@ class RefCountedWithTracing {
void Unref() {
if (gpr_unref(&refs_)) {
- Delete(this);
+ Delete(static_cast<Child*>(this));
}
}
void Unref(const DebugLocation& location, const char* reason) {
if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) {
gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count);
- gpr_log(GPR_DEBUG, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s",
+ gpr_log(GPR_INFO, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s",
trace_flag_->name(), this, location.file(), location.line(),
old_refs, old_refs - 1, reason);
}
@@ -135,9 +133,7 @@ class RefCountedWithTracing {
GRPC_ABSTRACT_BASE_CLASS
protected:
- // Allow Delete() to access destructor.
- template <typename T>
- friend void Delete(T*);
+ GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
RefCountedWithTracing()
: RefCountedWithTracing(static_cast<TraceFlag*>(nullptr)) {}
diff --git a/src/core/lib/gprpp/thd.h b/src/core/lib/gprpp/thd.h
index 05c7ded45f..caf0652c1a 100644
--- a/src/core/lib/gprpp/thd.h
+++ b/src/core/lib/gprpp/thd.h
@@ -111,9 +111,6 @@ class Thread {
}
};
- static void Init();
- static bool AwaitAll(gpr_timespec deadline);
-
private:
Thread(const Thread&) = delete;
Thread& operator=(const Thread&) = delete;
diff --git a/src/core/lib/gprpp/thd_posix.cc b/src/core/lib/gprpp/thd_posix.cc
index 2f6c2edcae..533c07e7d8 100644
--- a/src/core/lib/gprpp/thd_posix.cc
+++ b/src/core/lib/gprpp/thd_posix.cc
@@ -32,17 +32,12 @@
#include <stdlib.h>
#include <string.h>
-#include "src/core/lib/gpr/fork.h"
#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/fork.h"
#include "src/core/lib/gprpp/memory.h"
namespace grpc_core {
namespace {
-gpr_mu g_mu;
-gpr_cv g_cv;
-int g_thread_count;
-int g_awaiting_threads;
-
class ThreadInternalsPosix;
struct thd_arg {
ThreadInternalsPosix* thread;
@@ -68,7 +63,7 @@ class ThreadInternalsPosix
info->body = thd_body;
info->arg = arg;
info->name = thd_name;
- inc_thd_count();
+ grpc_core::Fork::IncThreadCount();
GPR_ASSERT(pthread_attr_init(&attr) == 0);
GPR_ASSERT(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE) ==
@@ -103,7 +98,7 @@ class ThreadInternalsPosix
gpr_mu_unlock(&arg.thread->mu_);
(*arg.body)(arg.arg);
- dec_thd_count();
+ grpc_core::Fork::DecThreadCount();
return nullptr;
},
info) == 0);
@@ -113,7 +108,7 @@ class ThreadInternalsPosix
if (!success) {
/* don't use gpr_free, as this was allocated using malloc (see above) */
free(info);
- dec_thd_count();
+ grpc_core::Fork::DecThreadCount();
}
};
@@ -132,29 +127,6 @@ class ThreadInternalsPosix
void Join() override { pthread_join(pthread_id_, nullptr); }
private:
- /*****************************************
- * Only used when fork support is enabled
- */
-
- static void inc_thd_count() {
- if (grpc_fork_support_enabled()) {
- gpr_mu_lock(&g_mu);
- g_thread_count++;
- gpr_mu_unlock(&g_mu);
- }
- }
-
- static void dec_thd_count() {
- if (grpc_fork_support_enabled()) {
- gpr_mu_lock(&g_mu);
- g_thread_count--;
- if (g_awaiting_threads && g_thread_count == 0) {
- gpr_cv_signal(&g_cv);
- }
- gpr_mu_unlock(&g_mu);
- }
- }
-
gpr_mu mu_;
gpr_cv ready_;
bool started_;
@@ -180,27 +152,6 @@ Thread::Thread(const char* thd_name, void (*thd_body)(void* arg), void* arg,
*success = outcome;
}
}
-
-void Thread::Init() {
- gpr_mu_init(&g_mu);
- gpr_cv_init(&g_cv);
- g_thread_count = 0;
- g_awaiting_threads = 0;
-}
-
-bool Thread::AwaitAll(gpr_timespec deadline) {
- gpr_mu_lock(&g_mu);
- g_awaiting_threads = 1;
- int res = 0;
- while ((g_thread_count > 0) &&
- (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0)) {
- res = gpr_cv_wait(&g_cv, &g_mu, deadline);
- }
- g_awaiting_threads = 0;
- gpr_mu_unlock(&g_mu);
- return res == 0;
-}
-
} // namespace grpc_core
// The following is in the external namespace as it is exposed as C89 API
diff --git a/src/core/lib/gprpp/thd_windows.cc b/src/core/lib/gprpp/thd_windows.cc
index 59ea02f3d2..71584fd358 100644
--- a/src/core/lib/gprpp/thd_windows.cc
+++ b/src/core/lib/gprpp/thd_windows.cc
@@ -131,13 +131,6 @@ class ThreadInternalsWindows
namespace grpc_core {
-void Thread::Init() {}
-
-bool Thread::AwaitAll(gpr_timespec deadline) {
- // TODO: Consider adding this if needed
- return false;
-}
-
Thread::Thread(const char* thd_name, void (*thd_body)(void* arg), void* arg,
bool* success) {
bool outcome = false;
diff --git a/src/core/lib/http/httpcli_security_connector.cc b/src/core/lib/http/httpcli_security_connector.cc
index 0b53d63e77..50078c37a1 100644
--- a/src/core/lib/http/httpcli_security_connector.cc
+++ b/src/core/lib/http/httpcli_security_connector.cc
@@ -32,7 +32,6 @@
#include "src/core/lib/security/transport/security_handshaker.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/tsi/ssl_transport_security.h"
-#include "src/core/tsi/transport_security_adapter.h"
typedef struct {
grpc_channel_security_connector base;
@@ -65,8 +64,7 @@ static void httpcli_ssl_add_handshakers(grpc_channel_security_connector* sc,
}
}
grpc_handshake_manager_add(
- handshake_mgr, grpc_security_handshaker_create(
- tsi_create_adapter_handshaker(handshaker), &sc->base));
+ handshake_mgr, grpc_security_handshaker_create(handshaker, &sc->base));
}
static void httpcli_ssl_check_peer(grpc_security_connector* sc, tsi_peer peer,
diff --git a/src/core/lib/iomgr/call_combiner.cc b/src/core/lib/iomgr/call_combiner.cc
index 24e11b687b..00a839b64c 100644
--- a/src/core/lib/iomgr/call_combiner.cc
+++ b/src/core/lib/iomgr/call_combiner.cc
@@ -64,7 +64,7 @@ void grpc_call_combiner_start(grpc_call_combiner* call_combiner,
const char* reason) {
GPR_TIMER_SCOPE("call_combiner_start", 0);
if (grpc_call_combiner_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"==> grpc_call_combiner_start() [%p] closure=%p [" DEBUG_FMT_STR
"%s] error=%s",
call_combiner, closure DEBUG_FMT_ARGS, reason,
@@ -73,7 +73,7 @@ void grpc_call_combiner_start(grpc_call_combiner* call_combiner,
size_t prev_size = static_cast<size_t>(
gpr_atm_full_fetch_add(&call_combiner->size, (gpr_atm)1));
if (grpc_call_combiner_trace.enabled()) {
- gpr_log(GPR_DEBUG, " size: %" PRIdPTR " -> %" PRIdPTR, prev_size,
+ gpr_log(GPR_INFO, " size: %" PRIdPTR " -> %" PRIdPTR, prev_size,
prev_size + 1);
}
GRPC_STATS_INC_CALL_COMBINER_LOCKS_SCHEDULED_ITEMS();
@@ -82,7 +82,7 @@ void grpc_call_combiner_start(grpc_call_combiner* call_combiner,
GPR_TIMER_MARK("call_combiner_initiate", 0);
if (grpc_call_combiner_trace.enabled()) {
- gpr_log(GPR_DEBUG, " EXECUTING IMMEDIATELY");
+ gpr_log(GPR_INFO, " EXECUTING IMMEDIATELY");
}
// Queue was empty, so execute this closure immediately.
GRPC_CLOSURE_SCHED(closure, error);
@@ -101,21 +101,21 @@ void grpc_call_combiner_stop(grpc_call_combiner* call_combiner DEBUG_ARGS,
const char* reason) {
GPR_TIMER_SCOPE("call_combiner_stop", 0);
if (grpc_call_combiner_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"==> grpc_call_combiner_stop() [%p] [" DEBUG_FMT_STR "%s]",
call_combiner DEBUG_FMT_ARGS, reason);
}
size_t prev_size = static_cast<size_t>(
gpr_atm_full_fetch_add(&call_combiner->size, (gpr_atm)-1));
if (grpc_call_combiner_trace.enabled()) {
- gpr_log(GPR_DEBUG, " size: %" PRIdPTR " -> %" PRIdPTR, prev_size,
+ gpr_log(GPR_INFO, " size: %" PRIdPTR " -> %" PRIdPTR, prev_size,
prev_size - 1);
}
GPR_ASSERT(prev_size >= 1);
if (prev_size > 1) {
while (true) {
if (grpc_call_combiner_trace.enabled()) {
- gpr_log(GPR_DEBUG, " checking queue");
+ gpr_log(GPR_INFO, " checking queue");
}
bool empty;
grpc_closure* closure = reinterpret_cast<grpc_closure*>(
@@ -124,19 +124,19 @@ void grpc_call_combiner_stop(grpc_call_combiner* call_combiner DEBUG_ARGS,
// This can happen either due to a race condition within the mpscq
// code or because of a race with grpc_call_combiner_start().
if (grpc_call_combiner_trace.enabled()) {
- gpr_log(GPR_DEBUG, " queue returned no result; checking again");
+ gpr_log(GPR_INFO, " queue returned no result; checking again");
}
continue;
}
if (grpc_call_combiner_trace.enabled()) {
- gpr_log(GPR_DEBUG, " EXECUTING FROM QUEUE: closure=%p error=%s",
+ gpr_log(GPR_INFO, " EXECUTING FROM QUEUE: closure=%p error=%s",
closure, grpc_error_string(closure->error_data.error));
}
GRPC_CLOSURE_SCHED(closure, closure->error_data.error);
break;
}
} else if (grpc_call_combiner_trace.enabled()) {
- gpr_log(GPR_DEBUG, " queue empty");
+ gpr_log(GPR_INFO, " queue empty");
}
}
@@ -151,7 +151,7 @@ void grpc_call_combiner_set_notify_on_cancel(grpc_call_combiner* call_combiner,
// Otherwise, store the new closure.
if (original_error != GRPC_ERROR_NONE) {
if (grpc_call_combiner_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"call_combiner=%p: scheduling notify_on_cancel callback=%p "
"for pre-existing cancellation",
call_combiner, closure);
@@ -162,7 +162,7 @@ void grpc_call_combiner_set_notify_on_cancel(grpc_call_combiner* call_combiner,
if (gpr_atm_full_cas(&call_combiner->cancel_state, original_state,
(gpr_atm)closure)) {
if (grpc_call_combiner_trace.enabled()) {
- gpr_log(GPR_DEBUG, "call_combiner=%p: setting notify_on_cancel=%p",
+ gpr_log(GPR_INFO, "call_combiner=%p: setting notify_on_cancel=%p",
call_combiner, closure);
}
// If we replaced an earlier closure, invoke the original
@@ -171,7 +171,7 @@ void grpc_call_combiner_set_notify_on_cancel(grpc_call_combiner* call_combiner,
if (original_state != 0) {
closure = (grpc_closure*)original_state;
if (grpc_call_combiner_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"call_combiner=%p: scheduling old cancel callback=%p",
call_combiner, closure);
}
@@ -199,7 +199,7 @@ void grpc_call_combiner_cancel(grpc_call_combiner* call_combiner,
if (original_state != 0) {
grpc_closure* notify_on_cancel = (grpc_closure*)original_state;
if (grpc_call_combiner_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"call_combiner=%p: scheduling notify_on_cancel callback=%p",
call_combiner, notify_on_cancel);
}
diff --git a/src/core/lib/iomgr/closure.h b/src/core/lib/iomgr/closure.h
index 64527d6bb1..34a494485d 100644
--- a/src/core/lib/iomgr/closure.h
+++ b/src/core/lib/iomgr/closure.h
@@ -253,8 +253,8 @@ inline void grpc_closure_run(grpc_closure* c, grpc_error* error) {
c->file_initiated = file;
c->line_initiated = line;
c->run = true;
+ GPR_ASSERT(c->cb != nullptr);
#endif
- assert(c->cb);
c->scheduler->vtable->run(c, error);
} else {
GRPC_ERROR_UNREF(error);
@@ -292,8 +292,8 @@ inline void grpc_closure_sched(grpc_closure* c, grpc_error* error) {
c->file_initiated = file;
c->line_initiated = line;
c->run = false;
+ GPR_ASSERT(c->cb != nullptr);
#endif
- assert(c->cb);
c->scheduler->vtable->sched(c, error);
} else {
GRPC_ERROR_UNREF(error);
@@ -330,8 +330,8 @@ inline void grpc_closure_list_sched(grpc_closure_list* list) {
c->file_initiated = file;
c->line_initiated = line;
c->run = false;
+ GPR_ASSERT(c->cb != nullptr);
#endif
- assert(c->cb);
c->scheduler->vtable->sched(c, c->error_data.error);
c = next;
}
diff --git a/src/core/lib/iomgr/combiner.cc b/src/core/lib/iomgr/combiner.cc
index e66df03182..6789e4d12d 100644
--- a/src/core/lib/iomgr/combiner.cc
+++ b/src/core/lib/iomgr/combiner.cc
@@ -63,11 +63,12 @@ struct grpc_combiner {
gpr_refcount refs;
};
+static void combiner_run(grpc_closure* closure, grpc_error* error);
static void combiner_exec(grpc_closure* closure, grpc_error* error);
static void combiner_finally_exec(grpc_closure* closure, grpc_error* error);
static const grpc_closure_scheduler_vtable scheduler = {
- combiner_exec, combiner_exec, "combiner:immediately"};
+ combiner_run, combiner_exec, "combiner:immediately"};
static const grpc_closure_scheduler_vtable finally_scheduler = {
combiner_finally_exec, combiner_finally_exec, "combiner:finally"};
@@ -83,12 +84,12 @@ grpc_combiner* grpc_combiner_create(void) {
grpc_closure_list_init(&lock->final_list);
GRPC_CLOSURE_INIT(&lock->offload, offload, lock,
grpc_executor_scheduler(GRPC_EXECUTOR_SHORT));
- GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, "C:%p create", lock));
+ GRPC_COMBINER_TRACE(gpr_log(GPR_INFO, "C:%p create", lock));
return lock;
}
static void really_destroy(grpc_combiner* lock) {
- GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, "C:%p really_destroy", lock));
+ GRPC_COMBINER_TRACE(gpr_log(GPR_INFO, "C:%p really_destroy", lock));
GPR_ASSERT(gpr_atm_no_barrier_load(&lock->state) == 0);
gpr_mpscq_destroy(&lock->queue);
gpr_free(lock);
@@ -97,7 +98,7 @@ static void really_destroy(grpc_combiner* lock) {
static void start_destroy(grpc_combiner* lock) {
gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -STATE_UNORPHANED);
GRPC_COMBINER_TRACE(gpr_log(
- GPR_DEBUG, "C:%p really_destroy old_state=%" PRIdPTR, lock, old_state));
+ GPR_INFO, "C:%p really_destroy old_state=%" PRIdPTR, lock, old_state));
if (old_state == 1) {
really_destroy(lock);
}
@@ -159,7 +160,7 @@ static void combiner_exec(grpc_closure* cl, grpc_error* error) {
GRPC_STATS_INC_COMBINER_LOCKS_SCHEDULED_ITEMS();
grpc_combiner* lock = COMBINER_FROM_CLOSURE_SCHEDULER(cl, scheduler);
gpr_atm last = gpr_atm_full_fetch_add(&lock->state, STATE_ELEM_COUNT_LOW_BIT);
- GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG,
+ GRPC_COMBINER_TRACE(gpr_log(GPR_INFO,
"C:%p grpc_combiner_execute c=%p last=%" PRIdPTR,
lock, cl, last));
if (last == 1) {
@@ -203,7 +204,7 @@ static void offload(void* arg, grpc_error* error) {
static void queue_offload(grpc_combiner* lock) {
GRPC_STATS_INC_COMBINER_LOCKS_OFFLOADED();
move_next();
- GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, "C:%p queue_offload", lock));
+ GRPC_COMBINER_TRACE(gpr_log(GPR_INFO, "C:%p queue_offload", lock));
GRPC_CLOSURE_SCHED(&lock->offload, GRPC_ERROR_NONE);
}
@@ -218,7 +219,7 @@ bool grpc_combiner_continue_exec_ctx() {
bool contended =
gpr_atm_no_barrier_load(&lock->initiating_exec_ctx_or_null) == 0;
- GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG,
+ GRPC_COMBINER_TRACE(gpr_log(GPR_INFO,
"C:%p grpc_combiner_continue_exec_ctx "
"contended=%d "
"exec_ctx_ready_to_finish=%d "
@@ -242,7 +243,7 @@ bool grpc_combiner_continue_exec_ctx() {
(gpr_atm_acq_load(&lock->state) >> 1) > 1) {
gpr_mpscq_node* n = gpr_mpscq_pop(&lock->queue);
GRPC_COMBINER_TRACE(
- gpr_log(GPR_DEBUG, "C:%p maybe_finish_one n=%p", lock, n));
+ gpr_log(GPR_INFO, "C:%p maybe_finish_one n=%p", lock, n));
if (n == nullptr) {
// queue is in an inconsistent state: use this as a cue that we should
// go off and do something else for a while (and come back later)
@@ -266,7 +267,7 @@ bool grpc_combiner_continue_exec_ctx() {
while (c != nullptr) {
GPR_TIMER_SCOPE("combiner.exec_1final", 0);
GRPC_COMBINER_TRACE(
- gpr_log(GPR_DEBUG, "C:%p execute_final[%d] c=%p", lock, loops, c));
+ gpr_log(GPR_INFO, "C:%p execute_final[%d] c=%p", lock, loops, c));
grpc_closure* next = c->next_data.next;
grpc_error* error = c->error_data.error;
#ifndef NDEBUG
@@ -284,7 +285,7 @@ bool grpc_combiner_continue_exec_ctx() {
gpr_atm old_state =
gpr_atm_full_fetch_add(&lock->state, -STATE_ELEM_COUNT_LOW_BIT);
GRPC_COMBINER_TRACE(
- gpr_log(GPR_DEBUG, "C:%p finish old_state=%" PRIdPTR, lock, old_state));
+ gpr_log(GPR_INFO, "C:%p finish old_state=%" PRIdPTR, lock, old_state));
// Define a macro to ease readability of the following switch statement.
#define OLD_STATE_WAS(orphaned, elem_count) \
(((orphaned) ? 0 : STATE_UNORPHANED) | \
@@ -327,8 +328,8 @@ static void combiner_finally_exec(grpc_closure* closure, grpc_error* error) {
grpc_combiner* lock =
COMBINER_FROM_CLOSURE_SCHEDULER(closure, finally_scheduler);
GRPC_COMBINER_TRACE(gpr_log(
- GPR_DEBUG, "C:%p grpc_combiner_execute_finally c=%p; ac=%p", lock,
- closure, grpc_core::ExecCtx::Get()->combiner_data()->active_combiner));
+ GPR_INFO, "C:%p grpc_combiner_execute_finally c=%p; ac=%p", lock, closure,
+ grpc_core::ExecCtx::Get()->combiner_data()->active_combiner));
if (grpc_core::ExecCtx::Get()->combiner_data()->active_combiner != lock) {
GPR_TIMER_MARK("slowpath", 0);
GRPC_CLOSURE_SCHED(GRPC_CLOSURE_CREATE(enqueue_finally, closure,
@@ -343,6 +344,22 @@ static void combiner_finally_exec(grpc_closure* closure, grpc_error* error) {
grpc_closure_list_append(&lock->final_list, closure, error);
}
+static void combiner_run(grpc_closure* closure, grpc_error* error) {
+ grpc_combiner* lock = COMBINER_FROM_CLOSURE_SCHEDULER(closure, scheduler);
+#ifndef NDEBUG
+ closure->scheduled = false;
+ GRPC_COMBINER_TRACE(gpr_log(
+ GPR_DEBUG,
+ "Combiner:%p grpc_combiner_run closure:%p created [%s:%d] run [%s:%d]",
+ lock, closure, closure->file_created, closure->line_created,
+ closure->file_initiated, closure->line_initiated));
+#endif
+ GPR_ASSERT(grpc_core::ExecCtx::Get()->combiner_data()->active_combiner ==
+ lock);
+ closure->cb(closure->cb_arg, error);
+ GRPC_ERROR_UNREF(error);
+}
+
static void enqueue_finally(void* closure, grpc_error* error) {
combiner_finally_exec(static_cast<grpc_closure*>(closure),
GRPC_ERROR_REF(error));
diff --git a/src/core/lib/iomgr/ev_epoll1_linux.cc b/src/core/lib/iomgr/ev_epoll1_linux.cc
index 3573a121e2..cf839619cd 100644
--- a/src/core/lib/iomgr/ev_epoll1_linux.cc
+++ b/src/core/lib/iomgr/ev_epoll1_linux.cc
@@ -658,7 +658,7 @@ static grpc_error* do_epoll_wait(grpc_pollset* ps, grpc_millis deadline) {
GRPC_STATS_INC_POLL_EVENTS_RETURNED(r);
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "ps: %p poll got %d events", ps, r);
+ gpr_log(GPR_INFO, "ps: %p poll got %d events", ps, r);
}
gpr_atm_rel_store(&g_epoll_set.num_events, r);
@@ -678,7 +678,7 @@ static bool begin_worker(grpc_pollset* pollset, grpc_pollset_worker* worker,
pollset->begin_refs++;
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PS:%p BEGIN_STARTS:%p", pollset, worker);
+ gpr_log(GPR_INFO, "PS:%p BEGIN_STARTS:%p", pollset, worker);
}
if (pollset->seen_inactive) {
@@ -697,7 +697,7 @@ static bool begin_worker(grpc_pollset* pollset, grpc_pollset_worker* worker,
gpr_mu_lock(&neighborhood->mu);
gpr_mu_lock(&pollset->mu);
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PS:%p BEGIN_REORG:%p kick_state=%s is_reassigning=%d",
+ gpr_log(GPR_INFO, "PS:%p BEGIN_REORG:%p kick_state=%s is_reassigning=%d",
pollset, worker, kick_state_string(worker->state),
is_reassigning);
}
@@ -749,7 +749,7 @@ static bool begin_worker(grpc_pollset* pollset, grpc_pollset_worker* worker,
gpr_cv_init(&worker->cv);
while (worker->state == UNKICKED && !pollset->shutting_down) {
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PS:%p BEGIN_WAIT:%p kick_state=%s shutdown=%d",
+ gpr_log(GPR_INFO, "PS:%p BEGIN_WAIT:%p kick_state=%s shutdown=%d",
pollset, worker, kick_state_string(worker->state),
pollset->shutting_down);
}
@@ -766,7 +766,7 @@ static bool begin_worker(grpc_pollset* pollset, grpc_pollset_worker* worker,
}
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"PS:%p BEGIN_DONE:%p kick_state=%s shutdown=%d "
"kicked_without_poller: %d",
pollset, worker, kick_state_string(worker->state),
@@ -809,7 +809,7 @@ static bool check_neighborhood_for_available_poller(
if (gpr_atm_no_barrier_cas(&g_active_poller, 0,
(gpr_atm)inspect_worker)) {
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. choose next poller to be %p",
+ gpr_log(GPR_INFO, " .. choose next poller to be %p",
inspect_worker);
}
SET_KICK_STATE(inspect_worker, DESIGNATED_POLLER);
@@ -820,7 +820,7 @@ static bool check_neighborhood_for_available_poller(
}
} else {
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. beaten to choose next poller");
+ gpr_log(GPR_INFO, " .. beaten to choose next poller");
}
}
// even if we didn't win the cas, there's a worker, we can stop
@@ -838,7 +838,7 @@ static bool check_neighborhood_for_available_poller(
}
if (!found_worker) {
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. mark pollset %p inactive", inspect);
+ gpr_log(GPR_INFO, " .. mark pollset %p inactive", inspect);
}
inspect->seen_inactive = true;
if (inspect == neighborhood->active_root) {
@@ -858,7 +858,7 @@ static void end_worker(grpc_pollset* pollset, grpc_pollset_worker* worker,
grpc_pollset_worker** worker_hdl) {
GPR_TIMER_SCOPE("end_worker", 0);
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PS:%p END_WORKER:%p", pollset, worker);
+ gpr_log(GPR_INFO, "PS:%p END_WORKER:%p", pollset, worker);
}
if (worker_hdl != nullptr) *worker_hdl = nullptr;
/* Make sure we appear kicked */
@@ -868,7 +868,7 @@ static void end_worker(grpc_pollset* pollset, grpc_pollset_worker* worker,
if (gpr_atm_no_barrier_load(&g_active_poller) == (gpr_atm)worker) {
if (worker->next != worker && worker->next->state == UNKICKED) {
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. choose next poller to be peer %p", worker);
+ gpr_log(GPR_INFO, " .. choose next poller to be peer %p", worker);
}
GPR_ASSERT(worker->next->initialized_cv);
gpr_atm_no_barrier_store(&g_active_poller, (gpr_atm)worker->next);
@@ -920,7 +920,7 @@ static void end_worker(grpc_pollset* pollset, grpc_pollset_worker* worker,
gpr_cv_destroy(&worker->cv);
}
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. remove worker");
+ gpr_log(GPR_INFO, " .. remove worker");
}
if (EMPTIED == worker_remove(pollset, worker)) {
pollset_maybe_finish_shutdown(pollset);
@@ -1022,7 +1022,7 @@ static grpc_error* pollset_kick(grpc_pollset* pollset,
GRPC_STATS_INC_POLLSET_KICKED_WITHOUT_POLLER();
pollset->kicked_without_poller = true;
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. kicked_without_poller");
+ gpr_log(GPR_INFO, " .. kicked_without_poller");
}
goto done;
}
@@ -1030,14 +1030,14 @@ static grpc_error* pollset_kick(grpc_pollset* pollset,
if (root_worker->state == KICKED) {
GRPC_STATS_INC_POLLSET_KICKED_AGAIN();
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. already kicked %p", root_worker);
+ gpr_log(GPR_INFO, " .. already kicked %p", root_worker);
}
SET_KICK_STATE(root_worker, KICKED);
goto done;
} else if (next_worker->state == KICKED) {
GRPC_STATS_INC_POLLSET_KICKED_AGAIN();
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. already kicked %p", next_worker);
+ gpr_log(GPR_INFO, " .. already kicked %p", next_worker);
}
SET_KICK_STATE(next_worker, KICKED);
goto done;
@@ -1048,7 +1048,7 @@ static grpc_error* pollset_kick(grpc_pollset* pollset,
&g_active_poller)) {
GRPC_STATS_INC_POLLSET_KICK_WAKEUP_FD();
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. kicked %p", root_worker);
+ gpr_log(GPR_INFO, " .. kicked %p", root_worker);
}
SET_KICK_STATE(root_worker, KICKED);
ret_err = grpc_wakeup_fd_wakeup(&global_wakeup_fd);
@@ -1056,7 +1056,7 @@ static grpc_error* pollset_kick(grpc_pollset* pollset,
} else if (next_worker->state == UNKICKED) {
GRPC_STATS_INC_POLLSET_KICK_WAKEUP_CV();
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. kicked %p", next_worker);
+ gpr_log(GPR_INFO, " .. kicked %p", next_worker);
}
GPR_ASSERT(next_worker->initialized_cv);
SET_KICK_STATE(next_worker, KICKED);
@@ -1066,7 +1066,7 @@ static grpc_error* pollset_kick(grpc_pollset* pollset,
if (root_worker->state != DESIGNATED_POLLER) {
if (grpc_polling_trace.enabled()) {
gpr_log(
- GPR_DEBUG,
+ GPR_INFO,
" .. kicked root non-poller %p (initialized_cv=%d) (poller=%p)",
root_worker, root_worker->initialized_cv, next_worker);
}
@@ -1079,7 +1079,7 @@ static grpc_error* pollset_kick(grpc_pollset* pollset,
} else {
GRPC_STATS_INC_POLLSET_KICK_WAKEUP_FD();
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. non-root poller %p (root=%p)", next_worker,
+ gpr_log(GPR_INFO, " .. non-root poller %p (root=%p)", next_worker,
root_worker);
}
SET_KICK_STATE(next_worker, KICKED);
@@ -1095,7 +1095,7 @@ static grpc_error* pollset_kick(grpc_pollset* pollset,
} else {
GRPC_STATS_INC_POLLSET_KICK_OWN_THREAD();
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. kicked while waking up");
+ gpr_log(GPR_INFO, " .. kicked while waking up");
}
goto done;
}
@@ -1105,14 +1105,14 @@ static grpc_error* pollset_kick(grpc_pollset* pollset,
if (specific_worker->state == KICKED) {
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. specific worker already kicked");
+ gpr_log(GPR_INFO, " .. specific worker already kicked");
}
goto done;
} else if (gpr_tls_get(&g_current_thread_worker) ==
(intptr_t)specific_worker) {
GRPC_STATS_INC_POLLSET_KICK_OWN_THREAD();
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. mark %p kicked", specific_worker);
+ gpr_log(GPR_INFO, " .. mark %p kicked", specific_worker);
}
SET_KICK_STATE(specific_worker, KICKED);
goto done;
@@ -1120,7 +1120,7 @@ static grpc_error* pollset_kick(grpc_pollset* pollset,
(grpc_pollset_worker*)gpr_atm_no_barrier_load(&g_active_poller)) {
GRPC_STATS_INC_POLLSET_KICK_WAKEUP_FD();
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. kick active poller");
+ gpr_log(GPR_INFO, " .. kick active poller");
}
SET_KICK_STATE(specific_worker, KICKED);
ret_err = grpc_wakeup_fd_wakeup(&global_wakeup_fd);
@@ -1128,7 +1128,7 @@ static grpc_error* pollset_kick(grpc_pollset* pollset,
} else if (specific_worker->initialized_cv) {
GRPC_STATS_INC_POLLSET_KICK_WAKEUP_CV();
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. kick waiting worker");
+ gpr_log(GPR_INFO, " .. kick waiting worker");
}
SET_KICK_STATE(specific_worker, KICKED);
gpr_cv_signal(&specific_worker->cv);
@@ -1136,7 +1136,7 @@ static grpc_error* pollset_kick(grpc_pollset* pollset,
} else {
GRPC_STATS_INC_POLLSET_KICKED_AGAIN();
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. kick non-waiting worker");
+ gpr_log(GPR_INFO, " .. kick non-waiting worker");
}
SET_KICK_STATE(specific_worker, KICKED);
goto done;
diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc
index efa31b9206..c86ed1e6c9 100644
--- a/src/core/lib/iomgr/ev_epollex_linux.cc
+++ b/src/core/lib/iomgr/ev_epollex_linux.cc
@@ -63,6 +63,7 @@
// a keepalive ping timeout issue. We may want to revert https://github
// .com/grpc/grpc/pull/14943 once we figure out the root cause.
#define MAX_EPOLL_EVENTS_HANDLED_EACH_POLL_CALL 16
+#define MAX_PROBE_EPOLL_FDS 32
grpc_core::DebugOnlyTraceFlag grpc_trace_pollable_refcount(false,
"pollable_refcount");
@@ -75,6 +76,12 @@ typedef enum { PO_MULTI, PO_FD, PO_EMPTY } pollable_type;
typedef struct pollable pollable;
+typedef struct cached_fd {
+ intptr_t salt;
+ int fd;
+ uint64_t last_used;
+} cached_fd;
+
/// A pollable is something that can be polled: it has an epoll set to poll on,
/// and a wakeup fd for kicks
/// There are three broad types:
@@ -103,6 +110,11 @@ struct pollable {
int event_cursor;
int event_count;
struct epoll_event events[MAX_EPOLL_EVENTS];
+
+ // Maintain a LRU-eviction cache of fds in this pollable
+ cached_fd fd_cache[MAX_PROBE_EPOLL_FDS];
+ int fd_cache_size;
+ uint64_t fd_cache_counter;
};
static const char* pollable_type_string(pollable_type t) {
@@ -145,8 +157,11 @@ static void pollable_unref(pollable* p, int line, const char* reason);
* Fd Declarations
*/
+static gpr_atm g_fd_salt;
+
struct grpc_fd {
int fd;
+ intptr_t salt;
/* refst format:
bit 0 : 1=Active / 0=Orphaned
bits 1-n : refcount
@@ -354,6 +369,7 @@ static grpc_fd* fd_create(int fd, const char* name) {
new_fd->pollable_obj = nullptr;
gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1);
new_fd->fd = fd;
+ new_fd->salt = gpr_atm_no_barrier_fetch_add(&g_fd_salt, 1);
new_fd->read_closure->InitEvent();
new_fd->write_closure->InitEvent();
gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL);
@@ -447,9 +463,13 @@ static grpc_error* pollable_create(pollable_type type, pollable** p) {
if (epfd == -1) {
return GRPC_OS_ERROR(errno, "epoll_create1");
}
+ GRPC_FD_TRACE("Pollable_create: created epfd: %d (type: %d)", epfd, type);
*p = static_cast<pollable*>(gpr_malloc(sizeof(**p)));
grpc_error* err = grpc_wakeup_fd_init(&(*p)->wakeup);
if (err != GRPC_ERROR_NONE) {
+ GRPC_FD_TRACE(
+ "Pollable_create: closed epfd: %d (type: %d). wakeupfd_init error",
+ epfd, type);
close(epfd);
gpr_free(*p);
*p = nullptr;
@@ -460,6 +480,9 @@ static grpc_error* pollable_create(pollable_type type, pollable** p) {
ev.data.ptr = (void*)(1 | (intptr_t) & (*p)->wakeup);
if (epoll_ctl(epfd, EPOLL_CTL_ADD, (*p)->wakeup.read_fd, &ev) != 0) {
err = GRPC_OS_ERROR(errno, "epoll_ctl");
+ GRPC_FD_TRACE(
+ "Pollable_create: closed epfd: %d (type: %d). epoll_ctl error", epfd,
+ type);
close(epfd);
grpc_wakeup_fd_destroy(&(*p)->wakeup);
gpr_free(*p);
@@ -477,6 +500,8 @@ static grpc_error* pollable_create(pollable_type type, pollable** p) {
(*p)->root_worker = nullptr;
(*p)->event_cursor = 0;
(*p)->event_count = 0;
+ (*p)->fd_cache_size = 0;
+ (*p)->fd_cache_counter = 0;
return GRPC_ERROR_NONE;
}
@@ -506,6 +531,7 @@ static void pollable_unref(pollable* p, int line, const char* reason) {
}
#endif
if (p != nullptr && gpr_unref(&p->refs)) {
+ GRPC_FD_TRACE("pollable_unref: Closing epfd: %d", p->epfd);
close(p->epfd);
grpc_wakeup_fd_destroy(&p->wakeup);
gpr_free(p);
@@ -516,15 +542,45 @@ static grpc_error* pollable_add_fd(pollable* p, grpc_fd* fd) {
grpc_error* error = GRPC_ERROR_NONE;
static const char* err_desc = "pollable_add_fd";
const int epfd = p->epfd;
+ gpr_mu_lock(&p->mu);
+ p->fd_cache_counter++;
+ // Handle the case of overflow for our cache counter by
+ // reseting the recency-counter on all cache objects
+ if (p->fd_cache_counter == 0) {
+ for (int i = 0; i < p->fd_cache_size; i++) {
+ p->fd_cache[i].last_used = 0;
+ }
+ }
+ int lru_idx = 0;
+ for (int i = 0; i < p->fd_cache_size; i++) {
+ if (p->fd_cache[i].fd == fd->fd && p->fd_cache[i].salt == fd->salt) {
+ GRPC_STATS_INC_POLLSET_FD_CACHE_HITS();
+ p->fd_cache[i].last_used = p->fd_cache_counter;
+ gpr_mu_unlock(&p->mu);
+ return GRPC_ERROR_NONE;
+ } else if (p->fd_cache[i].last_used < p->fd_cache[lru_idx].last_used) {
+ lru_idx = i;
+ }
+ }
+ // Add to cache
+ if (p->fd_cache_size < MAX_PROBE_EPOLL_FDS) {
+ lru_idx = p->fd_cache_size;
+ p->fd_cache_size++;
+ }
+ p->fd_cache[lru_idx].fd = fd->fd;
+ p->fd_cache[lru_idx].salt = fd->salt;
+ p->fd_cache[lru_idx].last_used = p->fd_cache_counter;
+ gpr_mu_unlock(&p->mu);
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "add fd %p (%d) to pollable %p", fd, fd->fd, p);
+ gpr_log(GPR_INFO, "add fd %p (%d) to pollable %p", fd, fd->fd, p);
}
struct epoll_event ev_fd;
ev_fd.events =
static_cast<uint32_t>(EPOLLET | EPOLLIN | EPOLLOUT | EPOLLEXCLUSIVE);
ev_fd.data.ptr = fd;
+ GRPC_STATS_INC_SYSCALL_EPOLL_CTL();
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd->fd, &ev_fd) != 0) {
switch (errno) {
case EEXIST:
@@ -560,7 +616,7 @@ static void pollset_global_shutdown(void) {
/* pollset->mu must be held while calling this function */
static void pollset_maybe_finish_shutdown(grpc_pollset* pollset) {
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"PS:%p (pollable:%p) maybe_finish_shutdown sc=%p (target:!NULL) "
"rw=%p (target:NULL) cpsc=%d (target:0)",
pollset, pollset->active_pollable, pollset->shutdown_closure,
@@ -585,14 +641,14 @@ static grpc_error* kick_one_worker(grpc_pollset_worker* specific_worker) {
GPR_ASSERT(specific_worker != nullptr);
if (specific_worker->kicked) {
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PS:%p kicked_specific_but_already_kicked", p);
+ gpr_log(GPR_INFO, "PS:%p kicked_specific_but_already_kicked", p);
}
GRPC_STATS_INC_POLLSET_KICKED_AGAIN();
return GRPC_ERROR_NONE;
}
if (gpr_tls_get(&g_current_thread_worker) == (intptr_t)specific_worker) {
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PS:%p kicked_specific_but_awake", p);
+ gpr_log(GPR_INFO, "PS:%p kicked_specific_but_awake", p);
}
GRPC_STATS_INC_POLLSET_KICK_OWN_THREAD();
specific_worker->kicked = true;
@@ -601,7 +657,7 @@ static grpc_error* kick_one_worker(grpc_pollset_worker* specific_worker) {
if (specific_worker == p->root_worker) {
GRPC_STATS_INC_POLLSET_KICK_WAKEUP_FD();
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PS:%p kicked_specific_via_wakeup_fd", p);
+ gpr_log(GPR_INFO, "PS:%p kicked_specific_via_wakeup_fd", p);
}
specific_worker->kicked = true;
grpc_error* error = grpc_wakeup_fd_wakeup(&p->wakeup);
@@ -610,7 +666,7 @@ static grpc_error* kick_one_worker(grpc_pollset_worker* specific_worker) {
if (specific_worker->initialized_cv) {
GRPC_STATS_INC_POLLSET_KICK_WAKEUP_CV();
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PS:%p kicked_specific_via_cv", p);
+ gpr_log(GPR_INFO, "PS:%p kicked_specific_via_cv", p);
}
specific_worker->kicked = true;
gpr_cv_signal(&specific_worker->cv);
@@ -626,7 +682,7 @@ static grpc_error* pollset_kick(grpc_pollset* pollset,
GPR_TIMER_SCOPE("pollset_kick", 0);
GRPC_STATS_INC_POLLSET_KICK();
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"PS:%p kick %p tls_pollset=%p tls_worker=%p pollset.root_worker=%p",
pollset, specific_worker,
(void*)gpr_tls_get(&g_current_thread_pollset),
@@ -636,7 +692,7 @@ static grpc_error* pollset_kick(grpc_pollset* pollset,
if (gpr_tls_get(&g_current_thread_pollset) != (intptr_t)pollset) {
if (pollset->root_worker == nullptr) {
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PS:%p kicked_any_without_poller", pollset);
+ gpr_log(GPR_INFO, "PS:%p kicked_any_without_poller", pollset);
}
GRPC_STATS_INC_POLLSET_KICKED_WITHOUT_POLLER();
pollset->kicked_without_poller = true;
@@ -662,7 +718,7 @@ static grpc_error* pollset_kick(grpc_pollset* pollset,
}
} else {
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PS:%p kicked_any_but_awake", pollset);
+ gpr_log(GPR_INFO, "PS:%p kicked_any_but_awake", pollset);
}
GRPC_STATS_INC_POLLSET_KICK_OWN_THREAD();
return GRPC_ERROR_NONE;
@@ -784,7 +840,7 @@ static grpc_error* pollable_process_events(grpc_pollset* pollset,
void* data_ptr = ev->data.ptr;
if (1 & (intptr_t)data_ptr) {
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PS:%p got pollset_wakeup %p", pollset, data_ptr);
+ gpr_log(GPR_INFO, "PS:%p got pollset_wakeup %p", pollset, data_ptr);
}
append_error(&error,
grpc_wakeup_fd_consume_wakeup(
@@ -797,7 +853,7 @@ static grpc_error* pollable_process_events(grpc_pollset* pollset,
bool read_ev = (ev->events & (EPOLLIN | EPOLLPRI)) != 0;
bool write_ev = (ev->events & EPOLLOUT) != 0;
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"PS:%p got fd %p: cancel=%d read=%d "
"write=%d",
pollset, fd, cancel, read_ev, write_ev);
@@ -827,7 +883,7 @@ static grpc_error* pollable_epoll(pollable* p, grpc_millis deadline) {
if (grpc_polling_trace.enabled()) {
char* desc = pollable_desc(p);
- gpr_log(GPR_DEBUG, "POLLABLE:%p[%s] poll for %dms", p, desc, timeout);
+ gpr_log(GPR_INFO, "POLLABLE:%p[%s] poll for %dms", p, desc, timeout);
gpr_free(desc);
}
@@ -846,7 +902,7 @@ static grpc_error* pollable_epoll(pollable* p, grpc_millis deadline) {
if (r < 0) return GRPC_OS_ERROR(errno, "epoll_wait");
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "POLLABLE:%p got %d events", p, r);
+ gpr_log(GPR_INFO, "POLLABLE:%p got %d events", p, r);
}
p->event_cursor = 0;
@@ -917,7 +973,7 @@ static bool begin_worker(grpc_pollset* pollset, grpc_pollset_worker* worker,
gpr_mu_unlock(&pollset->mu);
if (grpc_polling_trace.enabled() &&
worker->pollable_obj->root_worker != worker) {
- gpr_log(GPR_DEBUG, "PS:%p wait %p w=%p for %dms", pollset,
+ gpr_log(GPR_INFO, "PS:%p wait %p w=%p for %dms", pollset,
worker->pollable_obj, worker,
poll_deadline_to_millis_timeout(deadline));
}
@@ -925,19 +981,19 @@ static bool begin_worker(grpc_pollset* pollset, grpc_pollset_worker* worker,
if (gpr_cv_wait(&worker->cv, &worker->pollable_obj->mu,
grpc_millis_to_timespec(deadline, GPR_CLOCK_REALTIME))) {
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PS:%p timeout_wait %p w=%p", pollset,
+ gpr_log(GPR_INFO, "PS:%p timeout_wait %p w=%p", pollset,
worker->pollable_obj, worker);
}
do_poll = false;
} else if (worker->kicked) {
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PS:%p wakeup %p w=%p", pollset,
+ gpr_log(GPR_INFO, "PS:%p wakeup %p w=%p", pollset,
worker->pollable_obj, worker);
}
do_poll = false;
} else if (grpc_polling_trace.enabled() &&
worker->pollable_obj->root_worker != worker) {
- gpr_log(GPR_DEBUG, "PS:%p spurious_wakeup %p w=%p", pollset,
+ gpr_log(GPR_INFO, "PS:%p spurious_wakeup %p w=%p", pollset,
worker->pollable_obj, worker);
}
}
@@ -1009,7 +1065,7 @@ static grpc_error* pollset_work(grpc_pollset* pollset,
WORKER_PTR->originator = gettid();
#endif
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"PS:%p work hdl=%p worker=%p now=%" PRIdPTR " deadline=%" PRIdPTR
" kwp=%d pollable=%p",
pollset, worker_hdl, WORKER_PTR, grpc_core::ExecCtx::Get()->Now(),
@@ -1050,7 +1106,7 @@ static grpc_error* pollset_transition_pollable_from_empty_to_fd_locked(
static const char* err_desc = "pollset_transition_pollable_from_empty_to_fd";
grpc_error* error = GRPC_ERROR_NONE;
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"PS:%p add fd %p (%d); transition pollable from empty to fd",
pollset, fd, fd->fd);
}
@@ -1067,7 +1123,7 @@ static grpc_error* pollset_transition_pollable_from_fd_to_multi_locked(
grpc_error* error = GRPC_ERROR_NONE;
if (grpc_polling_trace.enabled()) {
gpr_log(
- GPR_DEBUG,
+ GPR_INFO,
"PS:%p add fd %p (%d); transition pollable from fd %p to multipoller",
pollset, and_add_fd, and_add_fd ? and_add_fd->fd : -1,
pollset->active_pollable->owner_fd);
@@ -1137,7 +1193,7 @@ static grpc_error* pollset_as_multipollable_locked(grpc_pollset* pollset,
/* Any workers currently polling on this pollset must now be woked up so
* that they can pick up the new active_pollable */
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"PS:%p active pollable transition from empty to multi",
pollset);
}
@@ -1224,7 +1280,7 @@ static void pollset_set_unref(grpc_pollset_set* pss) {
static void pollset_set_add_fd(grpc_pollset_set* pss, grpc_fd* fd) {
GPR_TIMER_SCOPE("pollset_set_add_fd", 0);
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PSS:%p: add fd %p (%d)", pss, fd, fd->fd);
+ gpr_log(GPR_INFO, "PSS:%p: add fd %p (%d)", pss, fd, fd->fd);
}
grpc_error* error = GRPC_ERROR_NONE;
static const char* err_desc = "pollset_set_add_fd";
@@ -1248,7 +1304,7 @@ static void pollset_set_add_fd(grpc_pollset_set* pss, grpc_fd* fd) {
static void pollset_set_del_fd(grpc_pollset_set* pss, grpc_fd* fd) {
GPR_TIMER_SCOPE("pollset_set_del_fd", 0);
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PSS:%p: del fd %p", pss, fd);
+ gpr_log(GPR_INFO, "PSS:%p: del fd %p", pss, fd);
}
pss = pss_lock_adam(pss);
size_t i;
@@ -1269,7 +1325,7 @@ static void pollset_set_del_fd(grpc_pollset_set* pss, grpc_fd* fd) {
static void pollset_set_del_pollset(grpc_pollset_set* pss, grpc_pollset* ps) {
GPR_TIMER_SCOPE("pollset_set_del_pollset", 0);
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PSS:%p: del pollset %p", pss, ps);
+ gpr_log(GPR_INFO, "PSS:%p: del pollset %p", pss, ps);
}
pss = pss_lock_adam(pss);
size_t i;
@@ -1321,7 +1377,7 @@ static grpc_error* add_fds_to_pollsets(grpc_fd** fds, size_t fd_count,
static void pollset_set_add_pollset(grpc_pollset_set* pss, grpc_pollset* ps) {
GPR_TIMER_SCOPE("pollset_set_add_pollset", 0);
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PSS:%p: add pollset %p", pss, ps);
+ gpr_log(GPR_INFO, "PSS:%p: add pollset %p", pss, ps);
}
grpc_error* error = GRPC_ERROR_NONE;
static const char* err_desc = "pollset_set_add_pollset";
@@ -1358,7 +1414,7 @@ static void pollset_set_add_pollset_set(grpc_pollset_set* a,
grpc_pollset_set* b) {
GPR_TIMER_SCOPE("pollset_set_add_pollset_set", 0);
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PSS: merge (%p, %p)", a, b);
+ gpr_log(GPR_INFO, "PSS: merge (%p, %p)", a, b);
}
grpc_error* error = GRPC_ERROR_NONE;
static const char* err_desc = "pollset_set_add_fd";
@@ -1392,7 +1448,7 @@ static void pollset_set_add_pollset_set(grpc_pollset_set* a,
GPR_SWAP(grpc_pollset_set*, a, b);
}
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "PSS: parent %p to %p", b, a);
+ gpr_log(GPR_INFO, "PSS: parent %p to %p", b, a);
}
gpr_ref(&a->refs);
b->parent = a;
diff --git a/src/core/lib/iomgr/ev_epollsig_linux.cc b/src/core/lib/iomgr/ev_epollsig_linux.cc
index 4991f468eb..a144817a83 100644
--- a/src/core/lib/iomgr/ev_epollsig_linux.cc
+++ b/src/core/lib/iomgr/ev_epollsig_linux.cc
@@ -292,7 +292,7 @@ static void pi_add_ref_dbg(polling_island* pi, const char* reason,
const char* file, int line) {
if (grpc_polling_trace.enabled()) {
gpr_atm old_cnt = gpr_atm_acq_load(&pi->ref_count);
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"Add ref pi: %p, old:%" PRIdPTR " -> new:%" PRIdPTR
" (%s) - (%s, %d)",
pi, old_cnt, old_cnt + 1, reason, file, line);
@@ -304,7 +304,7 @@ static void pi_unref_dbg(polling_island* pi, const char* reason,
const char* file, int line) {
if (grpc_polling_trace.enabled()) {
gpr_atm old_cnt = gpr_atm_acq_load(&pi->ref_count);
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"Unref pi: %p, old:%" PRIdPTR " -> new:%" PRIdPTR
" (%s) - (%s, %d)",
pi, old_cnt, (old_cnt - 1), reason, file, line);
diff --git a/src/core/lib/iomgr/ev_poll_posix.cc b/src/core/lib/iomgr/ev_poll_posix.cc
index a3a079bbe3..70958ed562 100644
--- a/src/core/lib/iomgr/ev_poll_posix.cc
+++ b/src/core/lib/iomgr/ev_poll_posix.cc
@@ -983,7 +983,7 @@ static grpc_error* pollset_work(grpc_pollset* pollset,
GRPC_SCHEDULING_END_BLOCKING_REGION;
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "%p poll=%d", pollset, r);
+ gpr_log(GPR_INFO, "%p poll=%d", pollset, r);
}
if (r < 0) {
@@ -1007,7 +1007,7 @@ static grpc_error* pollset_work(grpc_pollset* pollset,
} else {
if (pfds[0].revents & POLLIN_CHECK) {
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "%p: got_wakeup", pollset);
+ gpr_log(GPR_INFO, "%p: got_wakeup", pollset);
}
work_combine_error(
&error, grpc_wakeup_fd_consume_wakeup(&worker.wakeup_fd->fd));
@@ -1017,7 +1017,7 @@ static grpc_error* pollset_work(grpc_pollset* pollset,
fd_end_poll(&watchers[i], 0, 0, nullptr);
} else {
if (grpc_polling_trace.enabled()) {
- gpr_log(GPR_DEBUG, "%p got_event: %d r:%d w:%d [%d]", pollset,
+ gpr_log(GPR_INFO, "%p got_event: %d r:%d w:%d [%d]", pollset,
pfds[i].fd, (pfds[i].revents & POLLIN_CHECK) != 0,
(pfds[i].revents & POLLOUT_CHECK) != 0, pfds[i].revents);
}
diff --git a/src/core/lib/iomgr/ev_posix.cc b/src/core/lib/iomgr/ev_posix.cc
index 20b1f8df1a..dd3556ea40 100644
--- a/src/core/lib/iomgr/ev_posix.cc
+++ b/src/core/lib/iomgr/ev_posix.cc
@@ -40,15 +40,18 @@
grpc_core::TraceFlag grpc_polling_trace(false,
"polling"); /* Disabled by default */
+
+/* Traces fd create/close operations */
+grpc_core::TraceFlag grpc_fd_trace(false, "fd_trace");
grpc_core::DebugOnlyTraceFlag grpc_trace_fd_refcount(false, "fd_refcount");
grpc_core::DebugOnlyTraceFlag grpc_polling_api_trace(false, "polling_api");
#ifndef NDEBUG
// Polling API trace only enabled in debug builds
-#define GRPC_POLLING_API_TRACE(format, ...) \
- if (grpc_polling_api_trace.enabled()) { \
- gpr_log(GPR_DEBUG, "(polling-api) " format, __VA_ARGS__); \
+#define GRPC_POLLING_API_TRACE(format, ...) \
+ if (grpc_polling_api_trace.enabled()) { \
+ gpr_log(GPR_INFO, "(polling-api) " format, __VA_ARGS__); \
}
#else
#define GRPC_POLLING_API_TRACE(...)
@@ -192,6 +195,7 @@ void grpc_event_engine_shutdown(void) {
grpc_fd* grpc_fd_create(int fd, const char* name) {
GRPC_POLLING_API_TRACE("fd_create(%d, %s)", fd, name);
+ GRPC_FD_TRACE("fd_create(%d, %s)", fd, name);
return g_event_engine->fd_create(fd, name);
}
@@ -204,11 +208,14 @@ void grpc_fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd,
GRPC_POLLING_API_TRACE("fd_orphan(%d, %p, %p, %d, %s)",
grpc_fd_wrapped_fd(fd), on_done, release_fd,
already_closed, reason);
+ GRPC_FD_TRACE("grpc_fd_orphan, fd:%d closed", grpc_fd_wrapped_fd(fd));
+
g_event_engine->fd_orphan(fd, on_done, release_fd, already_closed, reason);
}
void grpc_fd_shutdown(grpc_fd* fd, grpc_error* why) {
GRPC_POLLING_API_TRACE("fd_shutdown(%d)", grpc_fd_wrapped_fd(fd));
+ GRPC_FD_TRACE("fd_shutdown(%d)", grpc_fd_wrapped_fd(fd));
g_event_engine->fd_shutdown(fd, why);
}
diff --git a/src/core/lib/iomgr/ev_posix.h b/src/core/lib/iomgr/ev_posix.h
index 6a5129a74d..82cbce9a7b 100644
--- a/src/core/lib/iomgr/ev_posix.h
+++ b/src/core/lib/iomgr/ev_posix.h
@@ -29,8 +29,14 @@
#include "src/core/lib/iomgr/pollset_set.h"
#include "src/core/lib/iomgr/wakeup_fd_posix.h"
+extern grpc_core::TraceFlag grpc_fd_trace; /* Disabled by default */
extern grpc_core::TraceFlag grpc_polling_trace; /* Disabled by default */
+#define GRPC_FD_TRACE(format, ...) \
+ if (grpc_fd_trace.enabled()) { \
+ gpr_log(GPR_INFO, "(fd-trace) " format, __VA_ARGS__); \
+ }
+
typedef struct grpc_fd grpc_fd;
typedef struct grpc_event_engine_vtable {
diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h
index 72d0ae58c1..8823dc4b51 100644
--- a/src/core/lib/iomgr/exec_ctx.h
+++ b/src/core/lib/iomgr/exec_ctx.h
@@ -26,6 +26,7 @@
#include <grpc/support/log.h>
#include "src/core/lib/gpr/tls.h"
+#include "src/core/lib/gprpp/fork.h"
#include "src/core/lib/iomgr/closure.h"
typedef gpr_atm grpc_millis;
@@ -79,30 +80,41 @@ namespace grpc_core {
* - Exactly one instance of ExecCtx must be created per thread. Instances must
* always be called exec_ctx.
* - Do not pass exec_ctx as a parameter to a function. Always access it using
- * grpc_core::ExecCtx::Get()
+ * grpc_core::ExecCtx::Get().
*/
class ExecCtx {
public:
/** Default Constructor */
- ExecCtx() : flags_(GRPC_EXEC_CTX_FLAG_IS_FINISHED) { Set(this); }
+ ExecCtx() : flags_(GRPC_EXEC_CTX_FLAG_IS_FINISHED) {
+ grpc_core::Fork::IncExecCtxCount();
+ Set(this);
+ }
/** Parameterised Constructor */
- ExecCtx(uintptr_t fl) : flags_(fl) { Set(this); }
+ ExecCtx(uintptr_t fl) : flags_(fl) {
+ grpc_core::Fork::IncExecCtxCount();
+ Set(this);
+ }
/** Destructor */
virtual ~ExecCtx() {
flags_ |= GRPC_EXEC_CTX_FLAG_IS_FINISHED;
Flush();
Set(last_exec_ctx_);
+ grpc_core::Fork::DecExecCtxCount();
}
/** Disallow copy and assignment operators */
ExecCtx(const ExecCtx&) = delete;
ExecCtx& operator=(const ExecCtx&) = delete;
- /** Return starting_cpu */
+ /** Return starting_cpu. This is only required for stats collection and is
+ * hence only defined if GRPC_COLLECT_STATS is enabled.
+ */
+#if defined(GRPC_COLLECT_STATS) || !defined(NDEBUG)
unsigned starting_cpu() const { return starting_cpu_; }
+#endif /* defined(GRPC_COLLECT_STATS) || !defined(NDEBUG) */
struct CombinerData {
/* currently active combiner: updated only via combiner.c */
@@ -128,12 +140,14 @@ class ExecCtx {
/** Flush any work that has been enqueued onto this grpc_exec_ctx.
* Caller must guarantee that no interfering locks are held.
- * Returns true if work was performed, false otherwise. */
+ * Returns true if work was performed, false otherwise.
+ */
bool Flush();
/** Returns true if we'd like to leave this execution context as soon as
-possible: useful for deciding whether to do something more or not depending
-on outside context */
+ * possible: useful for deciding whether to do something more or not
+ * depending on outside context.
+ */
bool IsReadyToFinish() {
if ((flags_ & GRPC_EXEC_CTX_FLAG_IS_FINISHED) == 0) {
if (CheckReadyToFinish()) {
@@ -147,12 +161,14 @@ on outside context */
}
/** Returns the stored current time relative to start if valid,
- * otherwise refreshes the stored time, sets it valid and returns the new
- * value */
+ * otherwise refreshes the stored time, sets it valid and returns the new
+ * value.
+ */
grpc_millis Now();
/** Invalidates the stored time value. A new time value will be set on calling
- * Now() */
+ * Now().
+ */
void InvalidateNow() { now_is_valid_ = false; }
/** To be used only by shutdown code in iomgr */
@@ -162,20 +178,20 @@ on outside context */
}
/** To be used only for testing.
- * Sets the now value
+ * Sets the now value.
*/
void TestOnlySetNow(grpc_millis new_val) {
now_ = new_val;
now_is_valid_ = true;
}
- /** Global initialization for ExecCtx. Called by iomgr */
+ /** Global initialization for ExecCtx. Called by iomgr. */
static void GlobalInit(void);
- /** Global shutdown for ExecCtx. Called by iomgr */
+ /** Global shutdown for ExecCtx. Called by iomgr. */
static void GlobalShutdown(void) { gpr_tls_destroy(&exec_ctx_); }
- /** Gets pointer to current exec_ctx */
+ /** Gets pointer to current exec_ctx. */
static ExecCtx* Get() {
return reinterpret_cast<ExecCtx*>(gpr_tls_get(&exec_ctx_));
}
@@ -185,19 +201,22 @@ on outside context */
}
protected:
- /** Check if ready to finish */
+ /** Check if ready to finish. */
virtual bool CheckReadyToFinish() { return false; }
- /** Disallow delete on ExecCtx */
+ /** Disallow delete on ExecCtx. */
static void operator delete(void* p) { abort(); }
private:
- /** Set exec_ctx_ to exec_ctx */
+ /** Set exec_ctx_ to exec_ctx. */
grpc_closure_list closure_list_ = GRPC_CLOSURE_LIST_INIT;
CombinerData combiner_data_ = {nullptr, nullptr};
uintptr_t flags_;
+
+#if defined(GRPC_COLLECT_STATS) || !defined(NDEBUG)
unsigned starting_cpu_ = gpr_cpu_current_cpu();
+#endif /* defined(GRPC_COLLECT_STATS) || !defined(NDEBUG) */
bool now_is_valid_ = false;
grpc_millis now_ = 0;
diff --git a/src/core/lib/iomgr/executor.cc b/src/core/lib/iomgr/executor.cc
index b017db53f8..f19f8cf20d 100644
--- a/src/core/lib/iomgr/executor.cc
+++ b/src/core/lib/iomgr/executor.cc
@@ -69,7 +69,7 @@ static size_t run_closures(grpc_closure_list list) {
gpr_log(GPR_DEBUG, "EXECUTOR: run %p [created by %s:%d]", c,
c->file_created, c->line_created);
#else
- gpr_log(GPR_DEBUG, "EXECUTOR: run %p", c);
+ gpr_log(GPR_INFO, "EXECUTOR: run %p", c);
#endif
}
#ifndef NDEBUG
@@ -150,7 +150,7 @@ static void executor_thread(void* arg) {
size_t subtract_depth = 0;
for (;;) {
if (executor_trace.enabled()) {
- gpr_log(GPR_DEBUG, "EXECUTOR[%d]: step (sub_depth=%" PRIdPTR ")",
+ gpr_log(GPR_INFO, "EXECUTOR[%d]: step (sub_depth=%" PRIdPTR ")",
static_cast<int>(ts - g_thread_state), subtract_depth);
}
gpr_mu_lock(&ts->mu);
@@ -161,7 +161,7 @@ static void executor_thread(void* arg) {
}
if (ts->shutdown) {
if (executor_trace.enabled()) {
- gpr_log(GPR_DEBUG, "EXECUTOR[%d]: shutdown",
+ gpr_log(GPR_INFO, "EXECUTOR[%d]: shutdown",
static_cast<int>(ts - g_thread_state));
}
gpr_mu_unlock(&ts->mu);
@@ -172,7 +172,7 @@ static void executor_thread(void* arg) {
ts->elems = GRPC_CLOSURE_LIST_INIT;
gpr_mu_unlock(&ts->mu);
if (executor_trace.enabled()) {
- gpr_log(GPR_DEBUG, "EXECUTOR[%d]: execute",
+ gpr_log(GPR_INFO, "EXECUTOR[%d]: execute",
static_cast<int>(ts - g_thread_state));
}
@@ -199,7 +199,7 @@ static void executor_push(grpc_closure* closure, grpc_error* error,
gpr_log(GPR_DEBUG, "EXECUTOR: schedule %p (created %s:%d) inline",
closure, closure->file_created, closure->line_created);
#else
- gpr_log(GPR_DEBUG, "EXECUTOR: schedule %p inline", closure);
+ gpr_log(GPR_INFO, "EXECUTOR: schedule %p inline", closure);
#endif
}
grpc_closure_list_append(grpc_core::ExecCtx::Get()->closure_list(),
@@ -225,7 +225,7 @@ static void executor_push(grpc_closure* closure, grpc_error* error,
closure, is_short ? "short" : "long", closure->file_created,
closure->line_created, static_cast<int>(ts - g_thread_state));
#else
- gpr_log(GPR_DEBUG, "EXECUTOR: try to schedule %p (%s) to thread %d",
+ gpr_log(GPR_INFO, "EXECUTOR: try to schedule %p (%s) to thread %d",
closure, is_short ? "short" : "long",
(int)(ts - g_thread_state));
#endif
diff --git a/src/core/lib/iomgr/fork_posix.cc b/src/core/lib/iomgr/fork_posix.cc
index f8645ab157..b37384b8db 100644
--- a/src/core/lib/iomgr/fork_posix.cc
+++ b/src/core/lib/iomgr/fork_posix.cc
@@ -28,7 +28,7 @@
#include <grpc/support/log.h>
#include "src/core/lib/gpr/env.h"
-#include "src/core/lib/gpr/fork.h"
+#include "src/core/lib/gprpp/fork.h"
#include "src/core/lib/gprpp/thd.h"
#include "src/core/lib/iomgr/ev_posix.h"
#include "src/core/lib/iomgr/executor.h"
@@ -41,47 +41,59 @@
* AROUND VERY SPECIFIC USE CASES.
*/
+namespace {
+bool skipped_handler = true;
+bool registered_handlers = false;
+} // namespace
+
void grpc_prefork() {
- if (!grpc_fork_support_enabled()) {
+ grpc_core::ExecCtx exec_ctx;
+ skipped_handler = true;
+ if (!grpc_is_initialized()) {
+ return;
+ }
+ if (!grpc_core::Fork::Enabled()) {
gpr_log(GPR_ERROR,
"Fork support not enabled; try running with the "
"environment variable GRPC_ENABLE_FORK_SUPPORT=1");
return;
}
- if (grpc_is_initialized()) {
- grpc_core::ExecCtx exec_ctx;
- grpc_timer_manager_set_threading(false);
- grpc_executor_set_threading(false);
- grpc_core::ExecCtx::Get()->Flush();
- if (!grpc_core::Thread::AwaitAll(
- gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
- gpr_time_from_seconds(3, GPR_TIMESPAN)))) {
- gpr_log(GPR_ERROR, "gRPC thread still active! Cannot fork!");
- }
+ if (!grpc_core::Fork::BlockExecCtx()) {
+ gpr_log(GPR_INFO,
+ "Other threads are currently calling into gRPC, skipping fork() "
+ "handlers");
+ return;
}
+ grpc_timer_manager_set_threading(false);
+ grpc_executor_set_threading(false);
+ grpc_core::ExecCtx::Get()->Flush();
+ grpc_core::Fork::AwaitThreads();
+ skipped_handler = false;
}
void grpc_postfork_parent() {
- if (grpc_is_initialized()) {
- grpc_timer_manager_set_threading(true);
+ if (!skipped_handler) {
+ grpc_core::Fork::AllowExecCtx();
grpc_core::ExecCtx exec_ctx;
+ grpc_timer_manager_set_threading(true);
grpc_executor_set_threading(true);
}
}
void grpc_postfork_child() {
- if (grpc_is_initialized()) {
- grpc_timer_manager_set_threading(true);
+ if (!skipped_handler) {
+ grpc_core::Fork::AllowExecCtx();
grpc_core::ExecCtx exec_ctx;
+ grpc_timer_manager_set_threading(true);
grpc_executor_set_threading(true);
- grpc_core::ExecCtx::Get()->Flush();
}
}
void grpc_fork_handlers_auto_register() {
- if (grpc_fork_support_enabled()) {
+ if (grpc_core::Fork::Enabled() & !registered_handlers) {
#ifdef GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK
pthread_atfork(grpc_prefork, grpc_postfork_parent, grpc_postfork_child);
+ registered_handlers = true;
#endif // GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK
}
}
diff --git a/src/core/lib/iomgr/resource_quota.cc b/src/core/lib/iomgr/resource_quota.cc
index 8c42dd78cf..539bc120ce 100644
--- a/src/core/lib/iomgr/resource_quota.cc
+++ b/src/core/lib/iomgr/resource_quota.cc
@@ -289,7 +289,7 @@ static bool rq_alloc(grpc_resource_quota* resource_quota) {
GRPC_RULIST_AWAITING_ALLOCATION))) {
gpr_mu_lock(&resource_user->mu);
if (grpc_resource_quota_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"RQ: check allocation for user %p shutdown=%" PRIdPTR
" free_pool=%" PRId64,
resource_user, gpr_atm_no_barrier_load(&resource_user->shutdown),
@@ -315,7 +315,7 @@ static bool rq_alloc(grpc_resource_quota* resource_quota) {
resource_quota->free_pool -= amt;
rq_update_estimate(resource_quota);
if (grpc_resource_quota_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"RQ %s %s: grant alloc %" PRId64
" bytes; rq_free_pool -> %" PRId64,
resource_quota->name, resource_user->name, amt,
@@ -323,7 +323,7 @@ static bool rq_alloc(grpc_resource_quota* resource_quota) {
}
} else if (grpc_resource_quota_trace.enabled() &&
resource_user->free_pool >= 0) {
- gpr_log(GPR_DEBUG, "RQ %s %s: discard already satisfied alloc request",
+ gpr_log(GPR_INFO, "RQ %s %s: discard already satisfied alloc request",
resource_quota->name, resource_user->name);
}
if (resource_user->free_pool >= 0) {
@@ -353,7 +353,7 @@ static bool rq_reclaim_from_per_user_free_pool(
resource_quota->free_pool += amt;
rq_update_estimate(resource_quota);
if (grpc_resource_quota_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"RQ %s %s: reclaim_from_per_user_free_pool %" PRId64
" bytes; rq_free_pool -> %" PRId64,
resource_quota->name, resource_user->name, amt,
@@ -376,9 +376,8 @@ static bool rq_reclaim(grpc_resource_quota* resource_quota, bool destructive) {
grpc_resource_user* resource_user = rulist_pop_head(resource_quota, list);
if (resource_user == nullptr) return false;
if (grpc_resource_quota_trace.enabled()) {
- gpr_log(GPR_DEBUG, "RQ %s %s: initiate %s reclamation",
- resource_quota->name, resource_user->name,
- destructive ? "destructive" : "benign");
+ gpr_log(GPR_INFO, "RQ %s %s: initiate %s reclamation", resource_quota->name,
+ resource_user->name, destructive ? "destructive" : "benign");
}
resource_quota->reclaiming = true;
grpc_resource_quota_ref_internal(resource_quota);
@@ -387,7 +386,7 @@ static bool rq_reclaim(grpc_resource_quota* resource_quota, bool destructive) {
resource_quota->debug_only_last_reclaimer_resource_user = resource_user;
resource_quota->debug_only_last_initiated_reclaimer = c;
resource_user->reclaimers[destructive] = nullptr;
- GRPC_CLOSURE_RUN(c, GRPC_ERROR_NONE);
+ GRPC_CLOSURE_SCHED(c, GRPC_ERROR_NONE);
return true;
}
@@ -506,7 +505,7 @@ static void ru_post_destructive_reclaimer(void* ru, grpc_error* error) {
static void ru_shutdown(void* ru, grpc_error* error) {
if (grpc_resource_quota_trace.enabled()) {
- gpr_log(GPR_DEBUG, "RU shutdown %p", ru);
+ gpr_log(GPR_INFO, "RU shutdown %p", ru);
}
grpc_resource_user* resource_user = static_cast<grpc_resource_user*>(ru);
gpr_mu_lock(&resource_user->mu);
@@ -793,7 +792,7 @@ void grpc_resource_user_alloc(grpc_resource_user* resource_user, size_t size,
resource_user->free_pool -= static_cast<int64_t>(size);
resource_user->outstanding_allocations += static_cast<int64_t>(size);
if (grpc_resource_quota_trace.enabled()) {
- gpr_log(GPR_DEBUG, "RQ %s %s: alloc %" PRIdPTR "; free_pool -> %" PRId64,
+ gpr_log(GPR_INFO, "RQ %s %s: alloc %" PRIdPTR "; free_pool -> %" PRId64,
resource_user->resource_quota->name, resource_user->name, size,
resource_user->free_pool);
}
@@ -816,7 +815,7 @@ void grpc_resource_user_free(grpc_resource_user* resource_user, size_t size) {
bool was_zero_or_negative = resource_user->free_pool <= 0;
resource_user->free_pool += static_cast<int64_t>(size);
if (grpc_resource_quota_trace.enabled()) {
- gpr_log(GPR_DEBUG, "RQ %s %s: free %" PRIdPTR "; free_pool -> %" PRId64,
+ gpr_log(GPR_INFO, "RQ %s %s: free %" PRIdPTR "; free_pool -> %" PRId64,
resource_user->resource_quota->name, resource_user->name, size,
resource_user->free_pool);
}
@@ -842,7 +841,7 @@ void grpc_resource_user_post_reclaimer(grpc_resource_user* resource_user,
void grpc_resource_user_finish_reclamation(grpc_resource_user* resource_user) {
if (grpc_resource_quota_trace.enabled()) {
- gpr_log(GPR_DEBUG, "RQ %s %s: reclamation complete",
+ gpr_log(GPR_INFO, "RQ %s %s: reclamation complete",
resource_user->resource_quota->name, resource_user->name);
}
GRPC_CLOSURE_SCHED(
diff --git a/src/core/lib/iomgr/tcp_client_custom.cc b/src/core/lib/iomgr/tcp_client_custom.cc
index 55632a55a1..932c79ea0b 100644
--- a/src/core/lib/iomgr/tcp_client_custom.cc
+++ b/src/core/lib/iomgr/tcp_client_custom.cc
@@ -66,7 +66,7 @@ static void on_alarm(void* acp, grpc_error* error) {
grpc_custom_tcp_connect* connect = socket->connector;
if (grpc_tcp_trace.enabled()) {
const char* str = grpc_error_string(error);
- gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s",
+ gpr_log(GPR_INFO, "CLIENT_CONNECT: %s: on_alarm: error=%s",
connect->addr_name, str);
}
if (error == GRPC_ERROR_NONE) {
@@ -136,7 +136,7 @@ static void tcp_connect(grpc_closure* closure, grpc_endpoint** ep,
connect->refs = 2;
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %p %s: asynchronously connecting",
+ gpr_log(GPR_INFO, "CLIENT_CONNECT: %p %s: asynchronously connecting",
socket, connect->addr_name);
}
diff --git a/src/core/lib/iomgr/tcp_client_posix.cc b/src/core/lib/iomgr/tcp_client_posix.cc
index 8d4c84880d..39da7f1637 100644
--- a/src/core/lib/iomgr/tcp_client_posix.cc
+++ b/src/core/lib/iomgr/tcp_client_posix.cc
@@ -45,6 +45,7 @@
#include "src/core/lib/iomgr/tcp_posix.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/unix_sockets_posix.h"
+#include "src/core/lib/slice/slice_internal.h"
extern grpc_core::TraceFlag grpc_tcp_trace;
@@ -104,7 +105,7 @@ static void tc_on_alarm(void* acp, grpc_error* error) {
async_connect* ac = static_cast<async_connect*>(acp);
if (grpc_tcp_trace.enabled()) {
const char* str = grpc_error_string(error);
- gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s", ac->addr_str,
+ gpr_log(GPR_INFO, "CLIENT_CONNECT: %s: on_alarm: error=%s", ac->addr_str,
str);
}
gpr_mu_lock(&ac->mu);
@@ -141,8 +142,8 @@ static void on_writable(void* acp, grpc_error* error) {
if (grpc_tcp_trace.enabled()) {
const char* str = grpc_error_string(error);
- gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: error=%s",
- ac->addr_str, str);
+ gpr_log(GPR_INFO, "CLIENT_CONNECT: %s: on_writable: error=%s", ac->addr_str,
+ str);
}
gpr_mu_lock(&ac->mu);
@@ -233,7 +234,7 @@ finish:
error = grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS,
addr_str_slice /* takes ownership */);
} else {
- grpc_slice_unref(addr_str_slice);
+ grpc_slice_unref_internal(addr_str_slice);
}
if (done) {
// This is safe even outside the lock, because "done", the sentinel, is
@@ -325,7 +326,7 @@ void grpc_tcp_client_create_from_prepared_fd(
ac->channel_args = grpc_channel_args_copy(channel_args);
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting fd %p",
+ gpr_log(GPR_INFO, "CLIENT_CONNECT: %s: asynchronously connecting fd %p",
ac->addr_str, fdobj);
}
diff --git a/src/core/lib/iomgr/tcp_custom.cc b/src/core/lib/iomgr/tcp_custom.cc
index 2b1fc93028..990e8d632b 100644
--- a/src/core/lib/iomgr/tcp_custom.cc
+++ b/src/core/lib/iomgr/tcp_custom.cc
@@ -125,23 +125,23 @@ static void tcp_ref(custom_tcp_endpoint* tcp) { gpr_ref(&tcp->refcount); }
static void call_read_cb(custom_tcp_endpoint* tcp, grpc_error* error) {
grpc_closure* cb = tcp->read_cb;
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "TCP:%p call_cb %p %p:%p", tcp->socket, cb, cb->cb,
+ gpr_log(GPR_INFO, "TCP:%p call_cb %p %p:%p", tcp->socket, cb, cb->cb,
cb->cb_arg);
size_t i;
const char* str = grpc_error_string(error);
- gpr_log(GPR_DEBUG, "read: error=%s", str);
+ gpr_log(GPR_INFO, "read: error=%s", str);
for (i = 0; i < tcp->read_slices->count; i++) {
char* dump = grpc_dump_slice(tcp->read_slices->slices[i],
GPR_DUMP_HEX | GPR_DUMP_ASCII);
- gpr_log(GPR_DEBUG, "READ %p (peer=%s): %s", tcp, tcp->peer_string, dump);
+ gpr_log(GPR_INFO, "READ %p (peer=%s): %s", tcp, tcp->peer_string, dump);
gpr_free(dump);
}
}
TCP_UNREF(tcp, "read");
tcp->read_slices = nullptr;
tcp->read_cb = nullptr;
- GRPC_CLOSURE_RUN(cb, error);
+ GRPC_CLOSURE_SCHED(cb, error);
}
static void custom_read_callback(grpc_custom_socket* socket, size_t nread,
@@ -171,7 +171,7 @@ static void custom_read_callback(grpc_custom_socket* socket, size_t nread,
static void tcp_read_allocation_done(void* tcpp, grpc_error* error) {
custom_tcp_endpoint* tcp = (custom_tcp_endpoint*)tcpp;
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "TCP:%p read_allocation_done: %s", tcp->socket,
+ gpr_log(GPR_INFO, "TCP:%p read_allocation_done: %s", tcp->socket,
grpc_error_string(error));
}
if (error == GRPC_ERROR_NONE) {
@@ -188,7 +188,7 @@ static void tcp_read_allocation_done(void* tcpp, grpc_error* error) {
}
if (grpc_tcp_trace.enabled()) {
const char* str = grpc_error_string(error);
- gpr_log(GPR_DEBUG, "Initiating read on %p: error=%s", tcp->socket, str);
+ gpr_log(GPR_INFO, "Initiating read on %p: error=%s", tcp->socket, str);
}
}
@@ -214,7 +214,7 @@ static void custom_write_callback(grpc_custom_socket* socket,
tcp->write_cb = nullptr;
if (grpc_tcp_trace.enabled()) {
const char* str = grpc_error_string(error);
- gpr_log(GPR_DEBUG, "write complete on %p: error=%s", tcp->socket, str);
+ gpr_log(GPR_INFO, "write complete on %p: error=%s", tcp->socket, str);
}
TCP_UNREF(tcp, "write");
GRPC_CLOSURE_SCHED(cb, error);
@@ -231,8 +231,8 @@ static void endpoint_write(grpc_endpoint* ep, grpc_slice_buffer* write_slices,
for (j = 0; j < write_slices->count; j++) {
char* data = grpc_dump_slice(write_slices->slices[j],
GPR_DUMP_HEX | GPR_DUMP_ASCII);
- gpr_log(GPR_DEBUG, "WRITE %p (peer=%s): %s", tcp->socket,
- tcp->peer_string, data);
+ gpr_log(GPR_INFO, "WRITE %p (peer=%s): %s", tcp->socket, tcp->peer_string,
+ data);
gpr_free(data);
}
}
@@ -283,7 +283,7 @@ static void endpoint_shutdown(grpc_endpoint* ep, grpc_error* why) {
if (!tcp->shutting_down) {
if (grpc_tcp_trace.enabled()) {
const char* str = grpc_error_string(why);
- gpr_log(GPR_DEBUG, "TCP %p shutdown why=%s", tcp->socket, str);
+ gpr_log(GPR_INFO, "TCP %p shutdown why=%s", tcp->socket, str);
}
tcp->shutting_down = true;
// GRPC_CLOSURE_SCHED(tcp->read_cb, GRPC_ERROR_REF(why));
@@ -345,7 +345,7 @@ grpc_endpoint* custom_tcp_endpoint_create(grpc_custom_socket* socket,
grpc_core::ExecCtx exec_ctx;
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "Creating TCP endpoint %p", socket);
+ gpr_log(GPR_INFO, "Creating TCP endpoint %p", socket);
}
memset(tcp, 0, sizeof(custom_tcp_endpoint));
socket->refs++;
diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc
index 6fdf9b93fe..a713d86633 100644
--- a/src/core/lib/iomgr/tcp_posix.cc
+++ b/src/core/lib/iomgr/tcp_posix.cc
@@ -120,7 +120,7 @@ static void tcp_drop_uncovered_then_handle_write(void* arg /* grpc_tcp */,
static void done_poller(void* bp, grpc_error* error_ignored) {
backup_poller* p = static_cast<backup_poller*>(bp);
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "BACKUP_POLLER:%p destroy", p);
+ gpr_log(GPR_INFO, "BACKUP_POLLER:%p destroy", p);
}
grpc_pollset_destroy(BACKUP_POLLER_POLLSET(p));
gpr_free(p);
@@ -129,7 +129,7 @@ static void done_poller(void* bp, grpc_error* error_ignored) {
static void run_poller(void* bp, grpc_error* error_ignored) {
backup_poller* p = static_cast<backup_poller*>(bp);
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "BACKUP_POLLER:%p run", p);
+ gpr_log(GPR_INFO, "BACKUP_POLLER:%p run", p);
}
gpr_mu_lock(p->pollset_mu);
grpc_millis deadline = grpc_core::ExecCtx::Get()->Now() + 10 * GPR_MS_PER_SEC;
@@ -145,18 +145,18 @@ static void run_poller(void* bp, grpc_error* error_ignored) {
gpr_mu_lock(p->pollset_mu);
bool cas_ok = gpr_atm_full_cas(&g_backup_poller, (gpr_atm)p, 0);
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "BACKUP_POLLER:%p done cas_ok=%d", p, cas_ok);
+ gpr_log(GPR_INFO, "BACKUP_POLLER:%p done cas_ok=%d", p, cas_ok);
}
gpr_mu_unlock(p->pollset_mu);
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "BACKUP_POLLER:%p shutdown", p);
+ gpr_log(GPR_INFO, "BACKUP_POLLER:%p shutdown", p);
}
grpc_pollset_shutdown(BACKUP_POLLER_POLLSET(p),
GRPC_CLOSURE_INIT(&p->run_poller, done_poller, p,
grpc_schedule_on_exec_ctx));
} else {
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "BACKUP_POLLER:%p reschedule", p);
+ gpr_log(GPR_INFO, "BACKUP_POLLER:%p reschedule", p);
}
GRPC_CLOSURE_SCHED(&p->run_poller, GRPC_ERROR_NONE);
}
@@ -167,7 +167,7 @@ static void drop_uncovered(grpc_tcp* tcp) {
gpr_atm old_count =
gpr_atm_no_barrier_fetch_add(&g_uncovered_notifications_pending, -1);
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "BACKUP_POLLER:%p uncover cnt %d->%d", p,
+ gpr_log(GPR_INFO, "BACKUP_POLLER:%p uncover cnt %d->%d", p,
static_cast<int>(old_count), static_cast<int>(old_count) - 1);
}
GPR_ASSERT(old_count != 1);
@@ -178,7 +178,7 @@ static void cover_self(grpc_tcp* tcp) {
gpr_atm old_count =
gpr_atm_no_barrier_fetch_add(&g_uncovered_notifications_pending, 2);
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "BACKUP_POLLER: cover cnt %d->%d",
+ gpr_log(GPR_INFO, "BACKUP_POLLER: cover cnt %d->%d",
static_cast<int>(old_count), 2 + static_cast<int>(old_count));
}
if (old_count == 0) {
@@ -186,7 +186,7 @@ static void cover_self(grpc_tcp* tcp) {
p = static_cast<backup_poller*>(
gpr_zalloc(sizeof(*p) + grpc_pollset_size()));
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "BACKUP_POLLER:%p create", p);
+ gpr_log(GPR_INFO, "BACKUP_POLLER:%p create", p);
}
grpc_pollset_init(BACKUP_POLLER_POLLSET(p), &p->pollset_mu);
gpr_atm_rel_store(&g_backup_poller, (gpr_atm)p);
@@ -201,7 +201,7 @@ static void cover_self(grpc_tcp* tcp) {
}
}
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "BACKUP_POLLER:%p add %p", p, tcp);
+ gpr_log(GPR_INFO, "BACKUP_POLLER:%p add %p", p, tcp);
}
grpc_pollset_add_fd(BACKUP_POLLER_POLLSET(p), tcp->em_fd);
if (old_count != 0) {
@@ -211,7 +211,7 @@ static void cover_self(grpc_tcp* tcp) {
static void notify_on_read(grpc_tcp* tcp) {
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "TCP:%p notify_on_read", tcp);
+ gpr_log(GPR_INFO, "TCP:%p notify_on_read", tcp);
}
GRPC_CLOSURE_INIT(&tcp->read_done_closure, tcp_handle_read, tcp,
grpc_schedule_on_exec_ctx);
@@ -220,7 +220,7 @@ static void notify_on_read(grpc_tcp* tcp) {
static void notify_on_write(grpc_tcp* tcp) {
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "TCP:%p notify_on_write", tcp);
+ gpr_log(GPR_INFO, "TCP:%p notify_on_write", tcp);
}
cover_self(tcp);
GRPC_CLOSURE_INIT(&tcp->write_done_closure,
@@ -231,7 +231,7 @@ static void notify_on_write(grpc_tcp* tcp) {
static void tcp_drop_uncovered_then_handle_write(void* arg, grpc_error* error) {
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "TCP:%p got_write: %s", arg, grpc_error_string(error));
+ gpr_log(GPR_INFO, "TCP:%p got_write: %s", arg, grpc_error_string(error));
}
drop_uncovered(static_cast<grpc_tcp*>(arg));
tcp_handle_write(arg, error);
@@ -351,27 +351,27 @@ static void call_read_cb(grpc_tcp* tcp, grpc_error* error) {
grpc_closure* cb = tcp->read_cb;
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "TCP:%p call_cb %p %p:%p", tcp, cb, cb->cb, cb->cb_arg);
+ gpr_log(GPR_INFO, "TCP:%p call_cb %p %p:%p", tcp, cb, cb->cb, cb->cb_arg);
size_t i;
const char* str = grpc_error_string(error);
- gpr_log(GPR_DEBUG, "read: error=%s", str);
+ gpr_log(GPR_INFO, "read: error=%s", str);
for (i = 0; i < tcp->incoming_buffer->count; i++) {
char* dump = grpc_dump_slice(tcp->incoming_buffer->slices[i],
GPR_DUMP_HEX | GPR_DUMP_ASCII);
- gpr_log(GPR_DEBUG, "READ %p (peer=%s): %s", tcp, tcp->peer_string, dump);
+ gpr_log(GPR_INFO, "READ %p (peer=%s): %s", tcp, tcp->peer_string, dump);
gpr_free(dump);
}
}
tcp->read_cb = nullptr;
tcp->incoming_buffer = nullptr;
- GRPC_CLOSURE_RUN(cb, error);
+ GRPC_CLOSURE_SCHED(cb, error);
}
#define MAX_READ_IOVEC 4
static void tcp_do_read(grpc_tcp* tcp) {
- GPR_TIMER_SCOPE("tcp_continue_read", 0);
+ GPR_TIMER_SCOPE("tcp_do_read", 0);
struct msghdr msg;
struct iovec iov[MAX_READ_IOVEC];
ssize_t read_bytes;
@@ -441,7 +441,7 @@ static void tcp_do_read(grpc_tcp* tcp) {
static void tcp_read_allocation_done(void* tcpp, grpc_error* error) {
grpc_tcp* tcp = static_cast<grpc_tcp*>(tcpp);
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "TCP:%p read_allocation_done: %s", tcp,
+ gpr_log(GPR_INFO, "TCP:%p read_allocation_done: %s", tcp,
grpc_error_string(error));
}
if (error != GRPC_ERROR_NONE) {
@@ -459,13 +459,13 @@ static void tcp_continue_read(grpc_tcp* tcp) {
if (tcp->incoming_buffer->length < target_read_size &&
tcp->incoming_buffer->count < MAX_READ_IOVEC) {
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "TCP:%p alloc_slices", tcp);
+ gpr_log(GPR_INFO, "TCP:%p alloc_slices", tcp);
}
grpc_resource_user_alloc_slices(&tcp->slice_allocator, target_read_size, 1,
tcp->incoming_buffer);
} else {
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "TCP:%p do_read", tcp);
+ gpr_log(GPR_INFO, "TCP:%p do_read", tcp);
}
tcp_do_read(tcp);
}
@@ -475,7 +475,7 @@ static void tcp_handle_read(void* arg /* grpc_tcp */, grpc_error* error) {
grpc_tcp* tcp = static_cast<grpc_tcp*>(arg);
GPR_ASSERT(!tcp->finished_edge);
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "TCP:%p got_read: %s", tcp, grpc_error_string(error));
+ gpr_log(GPR_INFO, "TCP:%p got_read: %s", tcp, grpc_error_string(error));
}
if (error != GRPC_ERROR_NONE) {
@@ -618,7 +618,7 @@ static void tcp_handle_write(void* arg /* grpc_tcp */, grpc_error* error) {
if (!tcp_flush(tcp, &error)) {
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "write: delayed");
+ gpr_log(GPR_INFO, "write: delayed");
}
notify_on_write(tcp);
} else {
@@ -626,10 +626,10 @@ static void tcp_handle_write(void* arg /* grpc_tcp */, grpc_error* error) {
tcp->write_cb = nullptr;
if (grpc_tcp_trace.enabled()) {
const char* str = grpc_error_string(error);
- gpr_log(GPR_DEBUG, "write: %s", str);
+ gpr_log(GPR_INFO, "write: %s", str);
}
- GRPC_CLOSURE_RUN(cb, error);
+ GRPC_CLOSURE_SCHED(cb, error);
TCP_UNREF(tcp, "write");
}
}
@@ -646,7 +646,7 @@ static void tcp_write(grpc_endpoint* ep, grpc_slice_buffer* buf,
for (i = 0; i < buf->count; i++) {
char* data =
grpc_dump_slice(buf->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
- gpr_log(GPR_DEBUG, "WRITE %p (peer=%s): %s", tcp, tcp->peer_string, data);
+ gpr_log(GPR_INFO, "WRITE %p (peer=%s): %s", tcp, tcp->peer_string, data);
gpr_free(data);
}
}
@@ -668,13 +668,13 @@ static void tcp_write(grpc_endpoint* ep, grpc_slice_buffer* buf,
TCP_REF(tcp, "write");
tcp->write_cb = cb;
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "write: delayed");
+ gpr_log(GPR_INFO, "write: delayed");
}
notify_on_write(tcp);
} else {
if (grpc_tcp_trace.enabled()) {
const char* str = grpc_error_string(error);
- gpr_log(GPR_DEBUG, "write: %s", str);
+ gpr_log(GPR_INFO, "write: %s", str);
}
GRPC_CLOSURE_SCHED(cb, error);
}
diff --git a/src/core/lib/iomgr/tcp_server_custom.cc b/src/core/lib/iomgr/tcp_server_custom.cc
index 79ba5c39ee..019b354473 100644
--- a/src/core/lib/iomgr/tcp_server_custom.cc
+++ b/src/core/lib/iomgr/tcp_server_custom.cc
@@ -222,10 +222,10 @@ static void finish_accept(grpc_tcp_listener* sp, grpc_custom_socket* socket) {
}
if (grpc_tcp_trace.enabled()) {
if (peer_name_string) {
- gpr_log(GPR_DEBUG, "SERVER_CONNECT: %p accepted connection: %s",
+ gpr_log(GPR_INFO, "SERVER_CONNECT: %p accepted connection: %s",
sp->server, peer_name_string);
} else {
- gpr_log(GPR_DEBUG, "SERVER_CONNECT: %p accepted connection", sp->server);
+ gpr_log(GPR_INFO, "SERVER_CONNECT: %p accepted connection", sp->server);
}
}
ep = custom_tcp_endpoint_create(socket, sp->server->resource_quota,
@@ -377,10 +377,10 @@ static grpc_error* tcp_server_add_port(grpc_tcp_server* s,
grpc_sockaddr_to_string(&port_string, addr, 0);
const char* str = grpc_error_string(error);
if (port_string) {
- gpr_log(GPR_DEBUG, "SERVER %p add_port %s error=%s", s, port_string, str);
+ gpr_log(GPR_INFO, "SERVER %p add_port %s error=%s", s, port_string, str);
gpr_free(port_string);
} else {
- gpr_log(GPR_DEBUG, "SERVER %p add_port error=%s", s, str);
+ gpr_log(GPR_INFO, "SERVER %p add_port error=%s", s, str);
}
}
@@ -419,7 +419,7 @@ static void tcp_server_start(grpc_tcp_server* server, grpc_pollset** pollsets,
(void)pollset_count;
GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD();
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "SERVER_START %p", server);
+ gpr_log(GPR_INFO, "SERVER_START %p", server);
}
GPR_ASSERT(on_accept_cb);
GPR_ASSERT(!server->on_accept_cb);
diff --git a/src/core/lib/iomgr/tcp_server_posix.cc b/src/core/lib/iomgr/tcp_server_posix.cc
index 7c338d5462..0a5caca906 100644
--- a/src/core/lib/iomgr/tcp_server_posix.cc
+++ b/src/core/lib/iomgr/tcp_server_posix.cc
@@ -187,11 +187,6 @@ static void on_read(void* arg, grpc_error* err) {
goto error;
}
- read_notifier_pollset =
- sp->server->pollsets[static_cast<size_t>(gpr_atm_no_barrier_fetch_add(
- &sp->server->next_pollset_to_assign, 1)) %
- sp->server->pollset_count];
-
/* loop until accept4 returns EAGAIN, and then re-arm notification */
for (;;) {
grpc_resolved_address addr;
@@ -228,11 +223,16 @@ static void on_read(void* arg, grpc_error* err) {
gpr_asprintf(&name, "tcp-server-connection:%s", addr_str);
if (grpc_tcp_trace.enabled()) {
- gpr_log(GPR_DEBUG, "SERVER_CONNECT: incoming connection: %s", addr_str);
+ gpr_log(GPR_INFO, "SERVER_CONNECT: incoming connection: %s", addr_str);
}
grpc_fd* fdobj = grpc_fd_create(fd, name);
+ read_notifier_pollset =
+ sp->server->pollsets[static_cast<size_t>(gpr_atm_no_barrier_fetch_add(
+ &sp->server->next_pollset_to_assign, 1)) %
+ sp->server->pollset_count];
+
grpc_pollset_add_fd(read_notifier_pollset, fdobj);
// Create acceptor.
@@ -346,7 +346,8 @@ static grpc_error* clone_port(grpc_tcp_listener* listener, unsigned count) {
err = grpc_create_dualstack_socket(&listener->addr, SOCK_STREAM, 0, &dsmode,
&fd);
if (err != GRPC_ERROR_NONE) return err;
- err = grpc_tcp_server_prepare_socket(fd, &listener->addr, true, &port);
+ err = grpc_tcp_server_prepare_socket(listener->server, fd, &listener->addr,
+ true, &port);
if (err != GRPC_ERROR_NONE) return err;
listener->server->nports++;
grpc_sockaddr_to_string(&addr_str, &listener->addr, 1);
diff --git a/src/core/lib/iomgr/tcp_server_utils_posix.h b/src/core/lib/iomgr/tcp_server_utils_posix.h
index 34d68130c9..dd199097b2 100644
--- a/src/core/lib/iomgr/tcp_server_utils_posix.h
+++ b/src/core/lib/iomgr/tcp_server_utils_posix.h
@@ -113,7 +113,7 @@ grpc_error* grpc_tcp_server_add_all_local_addrs(grpc_tcp_server* s,
int* out_port);
/* Prepare a recently-created socket for listening. */
-grpc_error* grpc_tcp_server_prepare_socket(int fd,
+grpc_error* grpc_tcp_server_prepare_socket(grpc_tcp_server*, int fd,
const grpc_resolved_address* addr,
bool so_reuseport, int* port);
/* Ruturn true if the platform supports ifaddrs */
diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc
index 3669d7b687..73afa15e65 100644
--- a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc
+++ b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc
@@ -87,7 +87,7 @@ static grpc_error* add_socket_to_server(grpc_tcp_server* s, int fd,
char* name;
grpc_error* err =
- grpc_tcp_server_prepare_socket(fd, addr, s->so_reuseport, &port);
+ grpc_tcp_server_prepare_socket(s, fd, addr, s->so_reuseport, &port);
if (err == GRPC_ERROR_NONE) {
GPR_ASSERT(port > 0);
grpc_sockaddr_to_string(&addr_str, addr, 1);
@@ -144,7 +144,7 @@ grpc_error* grpc_tcp_server_add_addr(grpc_tcp_server* s,
}
/* Prepare a recently-created socket for listening. */
-grpc_error* grpc_tcp_server_prepare_socket(int fd,
+grpc_error* grpc_tcp_server_prepare_socket(grpc_tcp_server* s, int fd,
const grpc_resolved_address* addr,
bool so_reuseport, int* port) {
grpc_resolved_address sockname_temp;
@@ -170,6 +170,18 @@ grpc_error* grpc_tcp_server_prepare_socket(int fd,
err = grpc_set_socket_no_sigpipe_if_possible(fd);
if (err != GRPC_ERROR_NONE) goto error;
+ if (s->channel_args) {
+ for (size_t i = 0; i < s->channel_args->num_args; i++) {
+ if (0 == strcmp(s->channel_args->args[i].key, GRPC_ARG_SOCKET_MUTATOR)) {
+ GPR_ASSERT(s->channel_args->args[i].type == GRPC_ARG_POINTER);
+ grpc_socket_mutator* mutator = static_cast<grpc_socket_mutator*>(
+ s->channel_args->args[i].value.pointer.p);
+ err = grpc_set_socket_with_mutator(fd, mutator);
+ if (err != GRPC_ERROR_NONE) goto error;
+ }
+ }
+ }
+
if (bind(fd, reinterpret_cast<grpc_sockaddr*>(const_cast<char*>(addr->addr)),
addr->len) < 0) {
err = GRPC_OS_ERROR(errno, "bind");
diff --git a/src/core/lib/iomgr/tcp_windows.cc b/src/core/lib/iomgr/tcp_windows.cc
index 04e6f11eee..5d316d477b 100644
--- a/src/core/lib/iomgr/tcp_windows.cc
+++ b/src/core/lib/iomgr/tcp_windows.cc
@@ -74,12 +74,28 @@ static grpc_error* set_dualstack(SOCKET sock) {
: GRPC_WSA_ERROR(WSAGetLastError(), "setsockopt(IPV6_V6ONLY)");
}
+static grpc_error* enable_loopback_fast_path(SOCKET sock) {
+ int status;
+ uint32_t param = 1;
+ DWORD ret;
+ status = WSAIoctl(sock, /*SIO_LOOPBACK_FAST_PATH==*/_WSAIOW(IOC_VENDOR, 16),
+ &param, sizeof(param), NULL, 0, &ret, 0, 0);
+ if (status == SOCKET_ERROR) {
+ status = WSAGetLastError();
+ }
+ return status == 0 || status == WSAEOPNOTSUPP
+ ? GRPC_ERROR_NONE
+ : GRPC_WSA_ERROR(status, "WSAIoctl(SIO_LOOPBACK_FAST_PATH)");
+}
+
grpc_error* grpc_tcp_prepare_socket(SOCKET sock) {
grpc_error* err;
err = set_non_block(sock);
if (err != GRPC_ERROR_NONE) return err;
err = set_dualstack(sock);
if (err != GRPC_ERROR_NONE) return err;
+ err = enable_loopback_fast_path(sock);
+ if (err != GRPC_ERROR_NONE) return err;
return GRPC_ERROR_NONE;
}
diff --git a/src/core/lib/iomgr/timer_generic.cc b/src/core/lib/iomgr/timer_generic.cc
index 0c6f236f83..de2256f7cb 100644
--- a/src/core/lib/iomgr/timer_generic.cc
+++ b/src/core/lib/iomgr/timer_generic.cc
@@ -346,9 +346,9 @@ static void timer_init(grpc_timer* timer, grpc_millis deadline,
#endif
if (grpc_timer_trace.enabled()) {
- gpr_log(GPR_DEBUG,
- "TIMER %p: SET %" PRIdPTR " now %" PRIdPTR " call %p[%p]", timer,
- deadline, grpc_core::ExecCtx::Get()->Now(), closure, closure->cb);
+ gpr_log(GPR_INFO, "TIMER %p: SET %" PRIdPTR " now %" PRIdPTR " call %p[%p]",
+ timer, deadline, grpc_core::ExecCtx::Get()->Now(), closure,
+ closure->cb);
}
if (!g_shared_mutables.initialized) {
@@ -382,7 +382,7 @@ static void timer_init(grpc_timer* timer, grpc_millis deadline,
list_join(&shard->list, timer);
}
if (grpc_timer_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
" .. add to shard %d with queue_deadline_cap=%" PRIdPTR
" => is_first_timer=%s",
static_cast<int>(shard - g_shards), shard->queue_deadline_cap,
@@ -404,7 +404,7 @@ static void timer_init(grpc_timer* timer, grpc_millis deadline,
if (is_first_timer) {
gpr_mu_lock(&g_shared_mutables.mu);
if (grpc_timer_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. old shard min_deadline=%" PRIdPTR,
+ gpr_log(GPR_INFO, " .. old shard min_deadline=%" PRIdPTR,
shard->min_deadline);
}
if (deadline < shard->min_deadline) {
@@ -434,7 +434,7 @@ static void timer_cancel(grpc_timer* timer) {
timer_shard* shard = &g_shards[GPR_HASH_POINTER(timer, g_num_shards)];
gpr_mu_lock(&shard->mu);
if (grpc_timer_trace.enabled()) {
- gpr_log(GPR_DEBUG, "TIMER %p: CANCEL pending=%s", timer,
+ gpr_log(GPR_INFO, "TIMER %p: CANCEL pending=%s", timer,
timer->pending ? "true" : "false");
}
@@ -475,7 +475,7 @@ static int refill_heap(timer_shard* shard, gpr_atm now) {
static_cast<gpr_atm>(deadline_delta * 1000.0));
if (grpc_timer_check_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. shard[%d]->queue_deadline_cap --> %" PRIdPTR,
+ gpr_log(GPR_INFO, " .. shard[%d]->queue_deadline_cap --> %" PRIdPTR,
static_cast<int>(shard - g_shards), shard->queue_deadline_cap);
}
for (timer = shard->list.next; timer != &shard->list; timer = next) {
@@ -483,7 +483,7 @@ static int refill_heap(timer_shard* shard, gpr_atm now) {
if (timer->deadline < shard->queue_deadline_cap) {
if (grpc_timer_check_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. add timer with deadline %" PRIdPTR " to heap",
+ gpr_log(GPR_INFO, " .. add timer with deadline %" PRIdPTR " to heap",
timer->deadline);
}
list_remove(timer);
@@ -500,7 +500,7 @@ static grpc_timer* pop_one(timer_shard* shard, gpr_atm now) {
grpc_timer* timer;
for (;;) {
if (grpc_timer_check_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. shard[%d]: heap_empty=%s",
+ gpr_log(GPR_INFO, " .. shard[%d]: heap_empty=%s",
static_cast<int>(shard - g_shards),
grpc_timer_heap_is_empty(&shard->heap) ? "true" : "false");
}
@@ -510,13 +510,13 @@ static grpc_timer* pop_one(timer_shard* shard, gpr_atm now) {
}
timer = grpc_timer_heap_top(&shard->heap);
if (grpc_timer_check_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
" .. check top timer deadline=%" PRIdPTR " now=%" PRIdPTR,
timer->deadline, now);
}
if (timer->deadline > now) return nullptr;
if (grpc_timer_trace.enabled()) {
- gpr_log(GPR_DEBUG, "TIMER %p: FIRE %" PRIdPTR "ms late via %s scheduler",
+ gpr_log(GPR_INFO, "TIMER %p: FIRE %" PRIdPTR "ms late via %s scheduler",
timer, now - timer->deadline,
timer->closure->scheduler->vtable->name);
}
@@ -540,7 +540,7 @@ static size_t pop_timers(timer_shard* shard, gpr_atm now,
*new_min_deadline = compute_min_deadline(shard);
gpr_mu_unlock(&shard->mu);
if (grpc_timer_check_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. shard[%d] popped %" PRIdPTR,
+ gpr_log(GPR_INFO, " .. shard[%d] popped %" PRIdPTR,
static_cast<int>(shard - g_shards), n);
}
return n;
@@ -563,7 +563,7 @@ static grpc_timer_check_result run_some_expired_timers(gpr_atm now,
result = GRPC_TIMERS_CHECKED_AND_EMPTY;
if (grpc_timer_check_trace.enabled()) {
- gpr_log(GPR_DEBUG, " .. shard[%d]->min_deadline = %" PRIdPTR,
+ gpr_log(GPR_INFO, " .. shard[%d]->min_deadline = %" PRIdPTR,
static_cast<int>(g_shard_queue[0] - g_shards),
g_shard_queue[0]->min_deadline);
}
@@ -580,7 +580,7 @@ static grpc_timer_check_result run_some_expired_timers(gpr_atm now,
}
if (grpc_timer_check_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
" .. result --> %d"
", shard[%d]->min_deadline %" PRIdPTR " --> %" PRIdPTR
", now=%" PRIdPTR,
@@ -624,7 +624,7 @@ static grpc_timer_check_result timer_check(grpc_millis* next) {
*next = GPR_MIN(*next, min_timer);
}
if (grpc_timer_check_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"TIMER CHECK SKIP: now=%" PRIdPTR " min_timer=%" PRIdPTR, now,
min_timer);
}
@@ -644,7 +644,7 @@ static grpc_timer_check_result timer_check(grpc_millis* next) {
} else {
gpr_asprintf(&next_str, "%" PRIdPTR, *next);
}
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"TIMER CHECK BEGIN: now=%" PRIdPTR " next=%s tls_min=%" PRIdPTR
" glob_min=%" PRIdPTR,
now, next_str, gpr_tls_get(&g_last_seen_min_timer),
@@ -662,7 +662,7 @@ static grpc_timer_check_result timer_check(grpc_millis* next) {
} else {
gpr_asprintf(&next_str, "%" PRIdPTR, *next);
}
- gpr_log(GPR_DEBUG, "TIMER CHECK END: r=%d; next=%s", r, next_str);
+ gpr_log(GPR_INFO, "TIMER CHECK END: r=%d; next=%s", r, next_str);
gpr_free(next_str);
}
return r;
diff --git a/src/core/lib/iomgr/timer_manager.cc b/src/core/lib/iomgr/timer_manager.cc
index 94f288af27..35e7914568 100644
--- a/src/core/lib/iomgr/timer_manager.cc
+++ b/src/core/lib/iomgr/timer_manager.cc
@@ -82,7 +82,7 @@ static void start_timer_thread_and_unlock(void) {
++g_thread_count;
gpr_mu_unlock(&g_mu);
if (grpc_timer_check_trace.enabled()) {
- gpr_log(GPR_DEBUG, "Spawn timer thread");
+ gpr_log(GPR_INFO, "Spawn timer thread");
}
completed_thread* ct =
static_cast<completed_thread*>(gpr_malloc(sizeof(*ct)));
@@ -108,7 +108,7 @@ static void run_some_timers() {
// waiter so that the next deadline is not missed
if (!g_has_timed_waiter) {
if (grpc_timer_check_trace.enabled()) {
- gpr_log(GPR_DEBUG, "kick untimed waiter");
+ gpr_log(GPR_INFO, "kick untimed waiter");
}
gpr_cv_signal(&g_cv_wait);
}
@@ -116,7 +116,7 @@ static void run_some_timers() {
}
// without our lock, flush the exec_ctx
if (grpc_timer_check_trace.enabled()) {
- gpr_log(GPR_DEBUG, "flush exec_ctx");
+ gpr_log(GPR_INFO, "flush exec_ctx");
}
grpc_core::ExecCtx::Get()->Flush();
gpr_mu_lock(&g_mu);
@@ -172,8 +172,7 @@ static bool wait_until(grpc_millis next) {
if (grpc_timer_check_trace.enabled()) {
grpc_millis wait_time = next - grpc_core::ExecCtx::Get()->Now();
- gpr_log(GPR_DEBUG, "sleep for a %" PRIdPTR " milliseconds",
- wait_time);
+ gpr_log(GPR_INFO, "sleep for a %" PRIdPTR " milliseconds", wait_time);
}
} else { // g_timed_waiter == true && next >= g_timed_waiter_deadline
next = GRPC_MILLIS_INF_FUTURE;
@@ -181,14 +180,14 @@ static bool wait_until(grpc_millis next) {
}
if (grpc_timer_check_trace.enabled() && next == GRPC_MILLIS_INF_FUTURE) {
- gpr_log(GPR_DEBUG, "sleep until kicked");
+ gpr_log(GPR_INFO, "sleep until kicked");
}
gpr_cv_wait(&g_cv_wait, &g_mu,
grpc_millis_to_timespec(next, GPR_CLOCK_MONOTONIC));
if (grpc_timer_check_trace.enabled()) {
- gpr_log(GPR_DEBUG, "wait ended: was_timed:%d kicked:%d",
+ gpr_log(GPR_INFO, "wait ended: was_timed:%d kicked:%d",
my_timed_waiter_generation == g_timed_waiter_generation,
g_kicked);
}
@@ -233,7 +232,7 @@ static void timer_main_loop() {
Consequently, we can just sleep forever here and be happy at some
saved wakeup cycles. */
if (grpc_timer_check_trace.enabled()) {
- gpr_log(GPR_DEBUG, "timers not checked: expect another thread to");
+ gpr_log(GPR_INFO, "timers not checked: expect another thread to");
}
next = GRPC_MILLIS_INF_FUTURE;
/* fall through */
@@ -259,7 +258,7 @@ static void timer_thread_cleanup(completed_thread* ct) {
g_completed_threads = ct;
gpr_mu_unlock(&g_mu);
if (grpc_timer_check_trace.enabled()) {
- gpr_log(GPR_DEBUG, "End timer thread");
+ gpr_log(GPR_INFO, "End timer thread");
}
}
@@ -301,18 +300,18 @@ void grpc_timer_manager_init(void) {
static void stop_threads(void) {
gpr_mu_lock(&g_mu);
if (grpc_timer_check_trace.enabled()) {
- gpr_log(GPR_DEBUG, "stop timer threads: threaded=%d", g_threaded);
+ gpr_log(GPR_INFO, "stop timer threads: threaded=%d", g_threaded);
}
if (g_threaded) {
g_threaded = false;
gpr_cv_broadcast(&g_cv_wait);
if (grpc_timer_check_trace.enabled()) {
- gpr_log(GPR_DEBUG, "num timer threads: %d", g_thread_count);
+ gpr_log(GPR_INFO, "num timer threads: %d", g_thread_count);
}
while (g_thread_count > 0) {
gpr_cv_wait(&g_cv_shutdown, &g_mu, gpr_inf_future(GPR_CLOCK_MONOTONIC));
if (grpc_timer_check_trace.enabled()) {
- gpr_log(GPR_DEBUG, "num timer threads: %d", g_thread_count);
+ gpr_log(GPR_INFO, "num timer threads: %d", g_thread_count);
}
gc_completed_threads();
}
diff --git a/src/core/lib/profiling/basic_timers.cc b/src/core/lib/profiling/basic_timers.cc
index 652a498b6e..b19ad9fc23 100644
--- a/src/core/lib/profiling/basic_timers.cc
+++ b/src/core/lib/profiling/basic_timers.cc
@@ -27,6 +27,7 @@
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
#include <inttypes.h>
+#include <pthread.h>
#include <stdio.h>
#include <string.h>
diff --git a/src/core/lib/security/credentials/credentials.h b/src/core/lib/security/credentials/credentials.h
index b1421e83c5..b486d25ab2 100644
--- a/src/core/lib/security/credentials/credentials.h
+++ b/src/core/lib/security/credentials/credentials.h
@@ -45,6 +45,7 @@ typedef enum {
#define GRPC_CHANNEL_CREDENTIALS_TYPE_SSL "Ssl"
#define GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY \
"FakeTransportSecurity"
+#define GRPC_CHANNEL_CREDENTIALS_TYPE_GOOGLE_DEFAULT "GoogleDefault"
#define GRPC_CALL_CREDENTIALS_TYPE_OAUTH2 "Oauth2"
#define GRPC_CALL_CREDENTIALS_TYPE_JWT "Jwt"
diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.cc b/src/core/lib/security/credentials/google_default/google_default_credentials.cc
index 70d4c3ea51..38c9175717 100644
--- a/src/core/lib/security/credentials/google_default/google_default_credentials.cc
+++ b/src/core/lib/security/credentials/google_default/google_default_credentials.cc
@@ -26,12 +26,16 @@
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
+#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h"
+#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gpr/env.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/http/httpcli.h"
#include "src/core/lib/http/parser.h"
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/iomgr/polling_entity.h"
+#include "src/core/lib/security/credentials/alts/alts_credentials.h"
+#include "src/core/lib/security/credentials/alts/check_gcp_environment.h"
#include "src/core/lib/security/credentials/google_default/google_default_credentials.h"
#include "src/core/lib/security/credentials/jwt/jwt_credentials.h"
#include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h"
@@ -45,11 +49,12 @@
/* -- Default credentials. -- */
-static grpc_channel_credentials* default_credentials = nullptr;
-static int compute_engine_detection_done = 0;
+static grpc_channel_credentials* g_default_credentials = nullptr;
+static int g_compute_engine_detection_done = 0;
static gpr_mu g_state_mu;
-static gpr_mu* g_polling_mu;
static gpr_once g_once = GPR_ONCE_INIT;
+static grpc_core::internal::grpc_gce_tenancy_checker g_gce_tenancy_checker =
+ grpc_alts_is_running_on_gcp;
static void init_default_credentials(void) { gpr_mu_init(&g_state_mu); }
@@ -60,103 +65,54 @@ typedef struct {
grpc_http_response response;
} compute_engine_detector;
-static void on_compute_engine_detection_http_response(void* user_data,
- grpc_error* error) {
- compute_engine_detector* detector =
- static_cast<compute_engine_detector*>(user_data);
- if (error == GRPC_ERROR_NONE && detector->response.status == 200 &&
- detector->response.hdr_count > 0) {
- /* Internet providers can return a generic response to all requests, so
- it is necessary to check that metadata header is present also. */
- size_t i;
- for (i = 0; i < detector->response.hdr_count; i++) {
- grpc_http_header* header = &detector->response.hdrs[i];
- if (strcmp(header->key, "Metadata-Flavor") == 0 &&
- strcmp(header->value, "Google") == 0) {
- detector->success = 1;
- break;
- }
- }
- }
- gpr_mu_lock(g_polling_mu);
- detector->is_done = 1;
- GRPC_LOG_IF_ERROR(
- "Pollset kick",
- grpc_pollset_kick(grpc_polling_entity_pollset(&detector->pollent),
- nullptr));
- gpr_mu_unlock(g_polling_mu);
+static void google_default_credentials_destruct(
+ grpc_channel_credentials* creds) {
+ grpc_google_default_channel_credentials* c =
+ reinterpret_cast<grpc_google_default_channel_credentials*>(creds);
+ grpc_channel_credentials_unref(c->alts_creds);
+ grpc_channel_credentials_unref(c->ssl_creds);
}
-static void destroy_pollset(void* p, grpc_error* e) {
- grpc_pollset_destroy(static_cast<grpc_pollset*>(p));
-}
-
-static int is_stack_running_on_compute_engine() {
- compute_engine_detector detector;
- grpc_httpcli_request request;
- grpc_httpcli_context context;
- grpc_closure destroy_closure;
-
- /* The http call is local. If it takes more than one sec, it is for sure not
- on compute engine. */
- grpc_millis max_detection_delay = GPR_MS_PER_SEC;
-
- grpc_pollset* pollset =
- static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
- grpc_pollset_init(pollset, &g_polling_mu);
- detector.pollent = grpc_polling_entity_create_from_pollset(pollset);
- detector.is_done = 0;
- detector.success = 0;
-
- memset(&detector.response, 0, sizeof(detector.response));
- memset(&request, 0, sizeof(grpc_httpcli_request));
- request.host = (char*)GRPC_COMPUTE_ENGINE_DETECTION_HOST;
- request.http.path = (char*)"/";
-
- grpc_httpcli_context_init(&context);
-
- grpc_resource_quota* resource_quota =
- grpc_resource_quota_create("google_default_credentials");
- grpc_httpcli_get(
- &context, &detector.pollent, resource_quota, &request,
- grpc_core::ExecCtx::Get()->Now() + max_detection_delay,
- GRPC_CLOSURE_CREATE(on_compute_engine_detection_http_response, &detector,
- grpc_schedule_on_exec_ctx),
- &detector.response);
- grpc_resource_quota_unref_internal(resource_quota);
-
- grpc_core::ExecCtx::Get()->Flush();
-
- /* Block until we get the response. This is not ideal but this should only be
- called once for the lifetime of the process by the default credentials. */
- gpr_mu_lock(g_polling_mu);
- while (!detector.is_done) {
- grpc_pollset_worker* worker = nullptr;
- if (!GRPC_LOG_IF_ERROR(
- "pollset_work",
- grpc_pollset_work(grpc_polling_entity_pollset(&detector.pollent),
- &worker, GRPC_MILLIS_INF_FUTURE))) {
- detector.is_done = 1;
- detector.success = 0;
- }
+static grpc_security_status google_default_create_security_connector(
+ grpc_channel_credentials* creds, grpc_call_credentials* call_creds,
+ const char* target, const grpc_channel_args* args,
+ grpc_channel_security_connector** sc, grpc_channel_args** new_args) {
+ grpc_google_default_channel_credentials* c =
+ reinterpret_cast<grpc_google_default_channel_credentials*>(creds);
+ bool is_grpclb_load_balancer = grpc_channel_arg_get_bool(
+ grpc_channel_args_find(args, GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER),
+ false);
+ bool is_backend_from_grpclb_load_balancer = grpc_channel_arg_get_bool(
+ grpc_channel_args_find(
+ args, GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER),
+ false);
+ bool use_alts =
+ is_grpclb_load_balancer || is_backend_from_grpclb_load_balancer;
+ grpc_security_status status = GRPC_SECURITY_ERROR;
+ status = use_alts ? c->alts_creds->vtable->create_security_connector(
+ c->alts_creds, call_creds, target, args, sc, new_args)
+ : c->ssl_creds->vtable->create_security_connector(
+ c->ssl_creds, call_creds, target, args, sc, new_args);
+ /* grpclb-specific channel args are removed from the channel args set
+ * to ensure backends and fallback adresses will have the same set of channel
+ * args. By doing that, it guarantees the connections to backends will not be
+ * torn down and re-connected when switching in and out of fallback mode.
+ */
+ if (use_alts) {
+ static const char* args_to_remove[] = {
+ GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER,
+ GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER,
+ };
+ *new_args = grpc_channel_args_copy_and_add_and_remove(
+ args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), nullptr, 0);
}
- gpr_mu_unlock(g_polling_mu);
-
- grpc_httpcli_context_destroy(&context);
- GRPC_CLOSURE_INIT(&destroy_closure, destroy_pollset,
- grpc_polling_entity_pollset(&detector.pollent),
- grpc_schedule_on_exec_ctx);
- grpc_pollset_shutdown(grpc_polling_entity_pollset(&detector.pollent),
- &destroy_closure);
- g_polling_mu = nullptr;
- grpc_core::ExecCtx::Get()->Flush();
-
- gpr_free(grpc_polling_entity_pollset(&detector.pollent));
- grpc_http_response_destroy(&detector.response);
-
- return detector.success;
+ return status;
}
+static grpc_channel_credentials_vtable google_default_credentials_vtable = {
+ google_default_credentials_destruct,
+ google_default_create_security_connector, nullptr};
+
/* Takes ownership of creds_path if not NULL. */
static grpc_error* create_default_creds_from_path(
char* creds_path, grpc_call_credentials** creds) {
@@ -234,8 +190,8 @@ grpc_channel_credentials* grpc_google_default_credentials_create(void) {
gpr_mu_lock(&g_state_mu);
- if (default_credentials != nullptr) {
- result = grpc_channel_credentials_ref(default_credentials);
+ if (g_default_credentials != nullptr) {
+ result = grpc_channel_credentials_ref(g_default_credentials);
goto end;
}
@@ -253,9 +209,9 @@ grpc_channel_credentials* grpc_google_default_credentials_create(void) {
/* At last try to see if we're on compute engine (do the detection only once
since it requires a network test). */
- if (!compute_engine_detection_done) {
- int need_compute_engine_creds = is_stack_running_on_compute_engine();
- compute_engine_detection_done = 1;
+ if (!g_compute_engine_detection_done) {
+ int need_compute_engine_creds = g_gce_tenancy_checker();
+ g_compute_engine_detection_done = 1;
if (need_compute_engine_creds) {
call_creds = grpc_google_compute_engine_credentials_create(nullptr);
if (call_creds == nullptr) {
@@ -269,18 +225,25 @@ grpc_channel_credentials* grpc_google_default_credentials_create(void) {
end:
if (result == nullptr) {
if (call_creds != nullptr) {
- /* Blend with default ssl credentials and add a global reference so that
- it
- can be cached and re-served. */
- grpc_channel_credentials* ssl_creds =
- grpc_ssl_credentials_create(nullptr, nullptr, nullptr);
- default_credentials = grpc_channel_credentials_ref(
- grpc_composite_channel_credentials_create(ssl_creds, call_creds,
- nullptr));
- GPR_ASSERT(default_credentials != nullptr);
- grpc_channel_credentials_unref(ssl_creds);
+ /* Create google default credentials. */
+ auto creds = static_cast<grpc_google_default_channel_credentials*>(
+ gpr_zalloc(sizeof(grpc_google_default_channel_credentials)));
+ creds->base.vtable = &google_default_credentials_vtable;
+ creds->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_GOOGLE_DEFAULT;
+ gpr_ref_init(&creds->base.refcount, 1);
+ creds->ssl_creds = grpc_ssl_credentials_create(nullptr, nullptr, nullptr);
+ GPR_ASSERT(creds->ssl_creds != nullptr);
+ grpc_alts_credentials_options* options =
+ grpc_alts_credentials_client_options_create();
+ creds->alts_creds = grpc_alts_credentials_create(options);
+ grpc_alts_credentials_options_destroy(options);
+ /* Add a global reference so that it can be cached and re-served. */
+ g_default_credentials = grpc_composite_channel_credentials_create(
+ &creds->base, call_creds, nullptr);
+ GPR_ASSERT(g_default_credentials != nullptr);
+ grpc_channel_credentials_unref(&creds->base);
grpc_call_credentials_unref(call_creds);
- result = default_credentials;
+ result = grpc_channel_credentials_ref(g_default_credentials);
} else {
gpr_log(GPR_ERROR, "Could not create google default credentials.");
}
@@ -295,15 +258,25 @@ end:
return result;
}
+namespace grpc_core {
+namespace internal {
+
+void set_gce_tenancy_checker_for_testing(grpc_gce_tenancy_checker checker) {
+ g_gce_tenancy_checker = checker;
+}
+
+} // namespace internal
+} // namespace grpc_core
+
void grpc_flush_cached_google_default_credentials(void) {
grpc_core::ExecCtx exec_ctx;
gpr_once_init(&g_once, init_default_credentials);
gpr_mu_lock(&g_state_mu);
- if (default_credentials != nullptr) {
- grpc_channel_credentials_unref(default_credentials);
- default_credentials = nullptr;
+ if (g_default_credentials != nullptr) {
+ grpc_channel_credentials_unref(g_default_credentials);
+ g_default_credentials = nullptr;
}
- compute_engine_detection_done = 0;
+ g_compute_engine_detection_done = 0;
gpr_mu_unlock(&g_state_mu);
}
diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.h b/src/core/lib/security/credentials/google_default/google_default_credentials.h
index b163e48631..a7dd0ea8ae 100644
--- a/src/core/lib/security/credentials/google_default/google_default_credentials.h
+++ b/src/core/lib/security/credentials/google_default/google_default_credentials.h
@@ -39,7 +39,23 @@
"/" GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE
#endif
+typedef struct {
+ grpc_channel_credentials base;
+ grpc_channel_credentials* alts_creds;
+ grpc_channel_credentials* ssl_creds;
+} grpc_google_default_channel_credentials;
+
void grpc_flush_cached_google_default_credentials(void);
+namespace grpc_core {
+namespace internal {
+
+typedef bool (*grpc_gce_tenancy_checker)(void);
+
+void set_gce_tenancy_checker_for_testing(grpc_gce_tenancy_checker checker);
+
+} // namespace internal
+} // namespace grpc_core
+
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_GOOGLE_DEFAULT_GOOGLE_DEFAULT_CREDENTIALS_H \
*/
diff --git a/src/core/lib/security/security_connector/alts_security_connector.cc b/src/core/lib/security/security_connector/alts_security_connector.cc
index 5ff7d7938b..35a787871a 100644
--- a/src/core/lib/security/security_connector/alts_security_connector.cc
+++ b/src/core/lib/security/security_connector/alts_security_connector.cc
@@ -30,6 +30,7 @@
#include "src/core/lib/security/credentials/alts/alts_credentials.h"
#include "src/core/lib/security/transport/security_handshaker.h"
+#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/transport.h"
#include "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h"
@@ -133,7 +134,7 @@ grpc_security_status grpc_alts_auth_context_from_tsi_peer(
rpc_versions_prop->value.data, rpc_versions_prop->value.length);
bool decode_result =
grpc_gcp_rpc_protocol_versions_decode(slice, &peer_versions);
- grpc_slice_unref(slice);
+ grpc_slice_unref_internal(slice);
if (!decode_result) {
gpr_log(GPR_ERROR, "Invalid peer rpc protocol versions.");
return GRPC_SECURITY_ERROR;
diff --git a/src/core/lib/security/security_connector/security_connector.cc b/src/core/lib/security/security_connector/security_connector.cc
index 3551061aa4..b54a7643e4 100644
--- a/src/core/lib/security/security_connector/security_connector.cc
+++ b/src/core/lib/security/security_connector/security_connector.cc
@@ -44,7 +44,6 @@
#include "src/core/lib/security/transport/target_authority_table.h"
#include "src/core/tsi/fake_transport_security.h"
#include "src/core/tsi/ssl_transport_security.h"
-#include "src/core/tsi/transport_security_adapter.h"
grpc_core::DebugOnlyTraceFlag grpc_trace_security_connector_refcount(
false, "security_connector_refcount");
@@ -70,8 +69,11 @@ void grpc_set_ssl_roots_override_callback(grpc_ssl_roots_override_callback cb) {
/* Defines the cipher suites that we accept by default. All these cipher suites
are compliant with HTTP2. */
-#define GRPC_SSL_CIPHER_SUITES \
- "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384"
+#define GRPC_SSL_CIPHER_SUITES \
+ "ECDHE-ECDSA-AES128-GCM-SHA256:" \
+ "ECDHE-ECDSA-AES256-GCM-SHA384:" \
+ "ECDHE-RSA-AES128-GCM-SHA256:" \
+ "ECDHE-RSA-AES256-GCM-SHA384"
static gpr_once cipher_suites_once = GPR_ONCE_INIT;
static const char* cipher_suites = nullptr;
@@ -673,8 +675,7 @@ static void ssl_channel_add_handshakers(grpc_channel_security_connector* sc,
}
// Create handshakers.
grpc_handshake_manager_add(
- handshake_mgr, grpc_security_handshaker_create(
- tsi_create_adapter_handshaker(tsi_hs), &sc->base));
+ handshake_mgr, grpc_security_handshaker_create(tsi_hs, &sc->base));
}
static const char** fill_alpn_protocol_strings(size_t* num_alpn_protocols) {
@@ -782,27 +783,29 @@ static void ssl_server_add_handshakers(grpc_server_security_connector* sc,
}
// Create handshakers.
grpc_handshake_manager_add(
- handshake_mgr, grpc_security_handshaker_create(
- tsi_create_adapter_handshaker(tsi_hs), &sc->base));
+ handshake_mgr, grpc_security_handshaker_create(tsi_hs, &sc->base));
}
-static int ssl_host_matches_name(const tsi_peer* peer, const char* peer_name) {
+int grpc_ssl_host_matches_name(const tsi_peer* peer, const char* peer_name) {
char* allocated_name = nullptr;
int r;
- if (strchr(peer_name, ':') != nullptr) {
- char* ignored_port;
- gpr_split_host_port(peer_name, &allocated_name, &ignored_port);
- gpr_free(ignored_port);
- peer_name = allocated_name;
- if (!peer_name) return 0;
- }
+ char* ignored_port;
+ gpr_split_host_port(peer_name, &allocated_name, &ignored_port);
+ gpr_free(ignored_port);
+ peer_name = allocated_name;
+ if (!peer_name) return 0;
+
+ // IPv6 zone-id should not be included in comparisons.
+ char* const zone_id = strchr(allocated_name, '%');
+ if (zone_id != nullptr) *zone_id = '\0';
+
r = tsi_ssl_peer_matches_name(peer, peer_name);
gpr_free(allocated_name);
return r;
}
-grpc_auth_context* tsi_ssl_peer_to_auth_context(const tsi_peer* peer) {
+grpc_auth_context* grpc_ssl_peer_to_auth_context(const tsi_peer* peer) {
size_t i;
grpc_auth_context* ctx = nullptr;
const char* peer_identity_property_name = nullptr;
@@ -859,14 +862,14 @@ static grpc_error* ssl_check_peer(grpc_security_connector* sc,
}
/* Check the peer name if specified. */
- if (peer_name != nullptr && !ssl_host_matches_name(peer, peer_name)) {
+ if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) {
char* msg;
gpr_asprintf(&msg, "Peer name %s is not in peer certificate", peer_name);
grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
gpr_free(msg);
return error;
}
- *auth_context = tsi_ssl_peer_to_auth_context(peer);
+ *auth_context = grpc_ssl_peer_to_auth_context(peer);
return GRPC_ERROR_NONE;
}
@@ -924,7 +927,7 @@ static void add_shallow_auth_property_to_peer(tsi_peer* peer,
tsi_prop->value.length = prop->value_length;
}
-tsi_peer tsi_shallow_peer_from_ssl_auth_context(
+tsi_peer grpc_shallow_peer_from_ssl_auth_context(
const grpc_auth_context* auth_context) {
size_t max_num_props = 0;
grpc_auth_property_iterator it;
@@ -955,7 +958,7 @@ tsi_peer tsi_shallow_peer_from_ssl_auth_context(
return peer;
}
-void tsi_shallow_peer_destruct(tsi_peer* peer) {
+void grpc_shallow_peer_destruct(tsi_peer* peer) {
if (peer->properties != nullptr) gpr_free(peer->properties);
}
@@ -967,8 +970,8 @@ static bool ssl_channel_check_call_host(grpc_channel_security_connector* sc,
grpc_ssl_channel_security_connector* c =
reinterpret_cast<grpc_ssl_channel_security_connector*>(sc);
grpc_security_status status = GRPC_SECURITY_ERROR;
- tsi_peer peer = tsi_shallow_peer_from_ssl_auth_context(auth_context);
- if (ssl_host_matches_name(&peer, host)) status = GRPC_SECURITY_OK;
+ tsi_peer peer = grpc_shallow_peer_from_ssl_auth_context(auth_context);
+ if (grpc_ssl_host_matches_name(&peer, host)) status = GRPC_SECURITY_OK;
/* If the target name was overridden, then the original target_name was
'checked' transitively during the previous peer check at the end of the
handshake. */
@@ -980,7 +983,7 @@ static bool ssl_channel_check_call_host(grpc_channel_security_connector* sc,
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"call host does not match SSL server name");
}
- tsi_shallow_peer_destruct(&peer);
+ grpc_shallow_peer_destruct(&peer);
return true;
}
diff --git a/src/core/lib/security/security_connector/security_connector.h b/src/core/lib/security/security_connector/security_connector.h
index c4cc19db81..f9723166d0 100644
--- a/src/core/lib/security/security_connector/security_connector.h
+++ b/src/core/lib/security/security_connector/security_connector.h
@@ -239,10 +239,11 @@ const tsi_peer_property* tsi_peer_get_property_by_name(const tsi_peer* peer,
const char* name);
/* Exposed for testing only. */
-grpc_auth_context* tsi_ssl_peer_to_auth_context(const tsi_peer* peer);
-tsi_peer tsi_shallow_peer_from_ssl_auth_context(
+grpc_auth_context* grpc_ssl_peer_to_auth_context(const tsi_peer* peer);
+tsi_peer grpc_shallow_peer_from_ssl_auth_context(
const grpc_auth_context* auth_context);
-void tsi_shallow_peer_destruct(tsi_peer* peer);
+void grpc_shallow_peer_destruct(tsi_peer* peer);
+int grpc_ssl_host_matches_name(const tsi_peer* peer, const char* peer_name);
/* --- Default SSL Root Store. --- */
namespace grpc_core {
diff --git a/src/core/lib/security/transport/secure_endpoint.cc b/src/core/lib/security/transport/secure_endpoint.cc
index 31b779e333..840b2e73bc 100644
--- a/src/core/lib/security/transport/secure_endpoint.cc
+++ b/src/core/lib/security/transport/secure_endpoint.cc
@@ -133,7 +133,7 @@ static void call_read_cb(secure_endpoint* ep, grpc_error* error) {
for (i = 0; i < ep->read_buffer->count; i++) {
char* data = grpc_dump_slice(ep->read_buffer->slices[i],
GPR_DUMP_HEX | GPR_DUMP_ASCII);
- gpr_log(GPR_DEBUG, "READ %p: %s", ep, data);
+ gpr_log(GPR_INFO, "READ %p: %s", ep, data);
gpr_free(data);
}
}
@@ -269,7 +269,7 @@ static void endpoint_write(grpc_endpoint* secure_ep, grpc_slice_buffer* slices,
for (i = 0; i < slices->count; i++) {
char* data =
grpc_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
- gpr_log(GPR_DEBUG, "WRITE %p: %s", ep, data);
+ gpr_log(GPR_INFO, "WRITE %p: %s", ep, data);
gpr_free(data);
}
}
diff --git a/src/core/lib/security/transport/security_handshaker.cc b/src/core/lib/security/transport/security_handshaker.cc
index 57dd3406bc..aff723ed04 100644
--- a/src/core/lib/security/transport/security_handshaker.cc
+++ b/src/core/lib/security/transport/security_handshaker.cc
@@ -232,6 +232,10 @@ static grpc_error* on_handshake_next_done_locked(
const unsigned char* bytes_to_send, size_t bytes_to_send_size,
tsi_handshaker_result* handshaker_result) {
grpc_error* error = GRPC_ERROR_NONE;
+ // Handshaker was shutdown.
+ if (h->shutdown) {
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshaker shutdown");
+ }
// Read more if we need to.
if (result == TSI_INCOMPLETE_DATA) {
GPR_ASSERT(bytes_to_send_size == 0);
@@ -376,6 +380,7 @@ static void security_handshaker_shutdown(grpc_handshaker* handshaker,
gpr_mu_lock(&h->mu);
if (!h->shutdown) {
h->shutdown = true;
+ tsi_handshaker_shutdown(h->handshaker);
grpc_endpoint_shutdown(h->args->endpoint, GRPC_ERROR_REF(why));
cleanup_args_for_failure_locked(h);
}
diff --git a/src/core/lib/slice/slice_hash_table.h b/src/core/lib/slice/slice_hash_table.h
index fbe9cc58e8..4bbcf88e89 100644
--- a/src/core/lib/slice/slice_hash_table.h
+++ b/src/core/lib/slice/slice_hash_table.h
@@ -81,6 +81,10 @@ class SliceHashTable : public RefCounted<SliceHashTable<T>> {
template <typename T2, typename... Args>
friend T2* New(Args&&... args);
+ // So Delete() can call our private dtor.
+ template <typename T2>
+ friend void Delete(T2*);
+
SliceHashTable(size_t num_entries, Entry* entries, ValueCmp value_cmp);
virtual ~SliceHashTable();
diff --git a/src/core/lib/slice/slice_weak_hash_table.h b/src/core/lib/slice/slice_weak_hash_table.h
index 9d0ddfc2d2..dc3ccc5dad 100644
--- a/src/core/lib/slice/slice_weak_hash_table.h
+++ b/src/core/lib/slice/slice_weak_hash_table.h
@@ -65,6 +65,10 @@ class SliceWeakHashTable : public RefCounted<SliceWeakHashTable<T, Size>> {
template <typename T2, typename... Args>
friend T2* New(Args&&... args);
+ // So Delete() can call our private dtor.
+ template <typename T2>
+ friend void Delete(T2*);
+
SliceWeakHashTable() = default;
~SliceWeakHashTable() = default;
diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc
index 9a9113643d..86e0afa6ee 100644
--- a/src/core/lib/surface/call.cc
+++ b/src/core/lib/surface/call.cc
@@ -67,6 +67,9 @@
#define MAX_SEND_EXTRA_METADATA_COUNT 3
+// Used to create arena for the first call.
+#define ESTIMATED_MDELEM_COUNT 16
+
/* Status data for a request can come from several sources; this
enumerates them all, and acts as a priority sorting for which
status to return to the application - earlier entries override
@@ -323,6 +326,11 @@ static parent_call* get_parent_call(grpc_call* call) {
return (parent_call*)gpr_atm_acq_load(&call->parent_call_atm);
}
+size_t grpc_call_get_initial_size_estimate() {
+ return sizeof(grpc_call) + sizeof(batch_control) * MAX_CONCURRENT_BATCHES +
+ sizeof(grpc_linked_mdelem) * ESTIMATED_MDELEM_COUNT;
+}
+
grpc_error* grpc_call_create(const grpc_call_create_args* args,
grpc_call** out_call) {
GPR_TIMER_SCOPE("grpc_call_create", 0);
@@ -610,7 +618,7 @@ grpc_call_error grpc_call_cancel(grpc_call* call, void* reserved) {
// This is called via the call combiner to start sending a batch down
// the filter stack.
static void execute_batch_in_call_combiner(void* arg, grpc_error* ignored) {
- GPR_TIMER_SCOPE("execute_batch", 0);
+ GPR_TIMER_SCOPE("execute_batch_in_call_combiner", 0);
grpc_transport_stream_op_batch* batch =
static_cast<grpc_transport_stream_op_batch*>(arg);
grpc_call* call = static_cast<grpc_call*>(batch->handler_private.extra_arg);
@@ -747,10 +755,10 @@ static void get_final_status(
status[i] = unpack_received_status(gpr_atm_acq_load(&call->status[i]));
}
if (grpc_call_error_trace.enabled()) {
- gpr_log(GPR_DEBUG, "get_final_status %s", call->is_client ? "CLI" : "SVR");
+ gpr_log(GPR_INFO, "get_final_status %s", call->is_client ? "CLI" : "SVR");
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
if (status[i].is_set) {
- gpr_log(GPR_DEBUG, " %d: %s", i, grpc_error_string(status[i].error));
+ gpr_log(GPR_INFO, " %d: %s", i, grpc_error_string(status[i].error));
}
}
}
@@ -1124,7 +1132,7 @@ static bool are_initial_metadata_flags_valid(uint32_t flags, bool is_client) {
return !(flags & invalid_positions);
}
-static int batch_slot_for_op(grpc_op_type type) {
+static size_t batch_slot_for_op(grpc_op_type type) {
switch (type) {
case GRPC_OP_SEND_INITIAL_METADATA:
return 0;
@@ -1144,20 +1152,23 @@ static int batch_slot_for_op(grpc_op_type type) {
GPR_UNREACHABLE_CODE(return 123456789);
}
-static batch_control* allocate_batch_control(grpc_call* call,
- const grpc_op* ops,
- size_t num_ops) {
- int slot = batch_slot_for_op(ops[0].op);
- batch_control** pslot = &call->active_batches[slot];
- if (*pslot == nullptr) {
- *pslot = static_cast<batch_control*>(
+static batch_control* reuse_or_allocate_batch_control(grpc_call* call,
+ const grpc_op* ops,
+ size_t num_ops) {
+ size_t slot_idx = batch_slot_for_op(ops[0].op);
+ batch_control** pslot = &call->active_batches[slot_idx];
+ batch_control* bctl;
+ if (*pslot != nullptr) {
+ bctl = *pslot;
+ if (bctl->call != nullptr) {
+ return nullptr;
+ }
+ memset(bctl, 0, sizeof(*bctl));
+ } else {
+ bctl = static_cast<batch_control*>(
gpr_arena_alloc(call->arena, sizeof(batch_control)));
+ *pslot = bctl;
}
- batch_control* bctl = *pslot;
- if (bctl->call != nullptr) {
- return nullptr;
- }
- memset(bctl, 0, sizeof(*bctl));
bctl->call = call;
bctl->op.payload = &call->stream_op_payload;
return bctl;
@@ -1259,8 +1270,12 @@ static void post_batch_completion(batch_control* bctl) {
if (bctl->completion_data.notify_tag.is_closure) {
/* unrefs bctl->error */
bctl->call = nullptr;
- GRPC_CLOSURE_RUN((grpc_closure*)bctl->completion_data.notify_tag.tag,
- error);
+ /* This closure may be meant to be run within some combiner. Since we aren't
+ * running in any combiner here, we need to use GRPC_CLOSURE_SCHED instead
+ * of GRPC_CLOSURE_RUN.
+ */
+ GRPC_CLOSURE_SCHED((grpc_closure*)bctl->completion_data.notify_tag.tag,
+ error);
GRPC_CALL_INTERNAL_UNREF(call, "completion");
} else {
/* unrefs bctl->error */
@@ -1539,7 +1554,7 @@ static void free_no_op_completion(void* p, grpc_cq_completion* completion) {
static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
size_t nops, void* notify_tag,
int is_notify_tag_closure) {
- GPR_TIMER_SCOPE("grpc_call_start_batch", 0);
+ GPR_TIMER_SCOPE("call_start_batch", 0);
size_t i;
const grpc_op* op;
@@ -1565,7 +1580,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
goto done;
}
- bctl = allocate_batch_control(call, ops, nops);
+ bctl = reuse_or_allocate_batch_control(call, ops, nops);
if (bctl == nullptr) {
return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
}
diff --git a/src/core/lib/surface/call.h b/src/core/lib/surface/call.h
index 793cce4efa..e000f13e7d 100644
--- a/src/core/lib/surface/call.h
+++ b/src/core/lib/surface/call.h
@@ -98,6 +98,11 @@ void* grpc_call_context_get(grpc_call* call, grpc_context_index elem);
uint8_t grpc_call_is_client(grpc_call* call);
+/* Get the estimated memory size for a call BESIDES the call stack. Combined
+ * with the size of the call stack, it helps estimate the arena size for the
+ * initial call. */
+size_t grpc_call_get_initial_size_estimate();
+
/* Return an appropriate compression algorithm for the requested compression \a
* level in the context of \a call. */
grpc_compression_algorithm grpc_call_compression_for_level(
diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc
index d740ebd411..a466b325be 100644
--- a/src/core/lib/surface/channel.cc
+++ b/src/core/lib/surface/channel.cc
@@ -72,10 +72,6 @@ struct grpc_channel {
};
#define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack*)((c) + 1))
-#define CHANNEL_FROM_CHANNEL_STACK(channel_stack) \
- (((grpc_channel*)(channel_stack)) - 1)
-#define CHANNEL_FROM_TOP_ELEM(top_elem) \
- CHANNEL_FROM_CHANNEL_STACK(grpc_channel_stack_from_top_element(top_elem))
static void destroy_channel(void* arg, grpc_error* error);
@@ -112,7 +108,8 @@ grpc_channel* grpc_channel_create_with_builder(
gpr_atm_no_barrier_store(
&channel->call_size_estimate,
- (gpr_atm)CHANNEL_STACK_FROM_CHANNEL(channel)->call_stack_size);
+ (gpr_atm)CHANNEL_STACK_FROM_CHANNEL(channel)->call_stack_size +
+ grpc_call_get_initial_size_estimate());
grpc_compression_options_init(&channel->compression_options);
for (size_t i = 0; i < args->num_args; i++) {
diff --git a/src/core/lib/surface/completion_queue.cc b/src/core/lib/surface/completion_queue.cc
index d0363917b0..f751741712 100644
--- a/src/core/lib/surface/completion_queue.cc
+++ b/src/core/lib/surface/completion_queue.cc
@@ -390,7 +390,6 @@ static bool cq_event_queue_push(grpc_cq_event_queue* q, grpc_cq_completion* c) {
static grpc_cq_completion* cq_event_queue_pop(grpc_cq_event_queue* q) {
grpc_cq_completion* c = nullptr;
- grpc_core::ExecCtx exec_ctx;
if (gpr_spinlock_trylock(&q->queue_lock)) {
GRPC_STATS_INC_CQ_EV_QUEUE_TRYLOCK_SUCCESSES();
diff --git a/src/core/lib/surface/init.cc b/src/core/lib/surface/init.cc
index bd436d6857..16be81e9c2 100644
--- a/src/core/lib/surface/init.cc
+++ b/src/core/lib/surface/init.cc
@@ -27,13 +27,12 @@
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include "src/core/lib/channel/channel_stack.h"
-#include "src/core/lib/channel/channel_trace_registry.h"
+#include "src/core/lib/channel/channelz_registry.h"
#include "src/core/lib/channel/connected_channel.h"
#include "src/core/lib/channel/handshaker_registry.h"
#include "src/core/lib/debug/stats.h"
#include "src/core/lib/debug/trace.h"
-#include "src/core/lib/gpr/fork.h"
-#include "src/core/lib/gprpp/thd.h"
+#include "src/core/lib/gprpp/fork.h"
#include "src/core/lib/http/parser.h"
#include "src/core/lib/iomgr/call_combiner.h"
#include "src/core/lib/iomgr/combiner.h"
@@ -65,12 +64,10 @@ static int g_initializations;
static void do_basic_init(void) {
gpr_log_verbosity_init();
- grpc_fork_support_init();
gpr_mu_init(&g_init_mu);
grpc_register_built_in_plugins();
grpc_cq_global_init();
g_initializations = 0;
- grpc_fork_handlers_auto_register();
}
static bool append_filter(grpc_channel_stack_builder* builder, void* arg) {
@@ -123,13 +120,14 @@ void grpc_init(void) {
gpr_mu_lock(&g_init_mu);
if (++g_initializations == 1) {
+ grpc_core::Fork::GlobalInit();
+ grpc_fork_handlers_auto_register();
gpr_time_init();
- grpc_core::Thread::Init();
grpc_stats_init();
grpc_slice_intern_init();
grpc_mdctx_global_init();
grpc_channel_init_init();
- grpc_channel_trace_registry_init();
+ grpc_core::ChannelzRegistry::Init();
grpc_security_pre_init();
grpc_core::ExecCtx::GlobalInit();
grpc_iomgr_init();
@@ -178,8 +176,9 @@ void grpc_shutdown(void) {
grpc_mdctx_global_shutdown();
grpc_handshaker_factory_registry_shutdown();
grpc_slice_intern_shutdown();
- grpc_channel_trace_registry_shutdown();
+ grpc_core::ChannelzRegistry::Shutdown();
grpc_stats_shutdown();
+ grpc_core::Fork::GlobalShutdown();
}
grpc_core::ExecCtx::GlobalShutdown();
}
diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc
index f7505c888e..cb34def740 100644
--- a/src/core/lib/surface/server.cc
+++ b/src/core/lib/surface/server.cc
@@ -1161,6 +1161,22 @@ static void listener_destroy_done(void* s, grpc_error* error) {
gpr_mu_unlock(&server->mu_global);
}
+/*
+ - Kills all pending requests-for-incoming-RPC-calls (i.e the requests made via
+ grpc_server_request_call and grpc_server_request_registered call will now be
+ cancelled). See 'kill_pending_work_locked()'
+
+ - Shuts down the listeners (i.e the server will no longer listen on the port
+ for new incoming channels).
+
+ - Iterates through all channels on the server and sends shutdown msg (see
+ 'channel_broadcaster_shutdown()' for details) to the clients via the
+ transport layer. The transport layer then guarantees the following:
+ -- Sends shutdown to the client (for eg: HTTP2 transport sends GOAWAY)
+ -- If the server has outstanding calls that are in the process, the
+ connection is NOT closed until the server is done with all those calls
+ -- Once, there are no more calls in progress, the channel is closed
+ */
void grpc_server_shutdown_and_notify(grpc_server* server,
grpc_completion_queue* cq, void* tag) {
listener* l;
diff --git a/src/core/lib/surface/version.cc b/src/core/lib/surface/version.cc
index a712e10037..306b7c395e 100644
--- a/src/core/lib/surface/version.cc
+++ b/src/core/lib/surface/version.cc
@@ -25,4 +25,4 @@
const char* grpc_version_string(void) { return "6.0.0-dev"; }
-const char* grpc_g_stands_for(void) { return "glorious"; }
+const char* grpc_g_stands_for(void) { return "gloriosa"; }
diff --git a/src/core/lib/transport/bdp_estimator.cc b/src/core/lib/transport/bdp_estimator.cc
index 8130535ddd..8e71f86989 100644
--- a/src/core/lib/transport/bdp_estimator.cc
+++ b/src/core/lib/transport/bdp_estimator.cc
@@ -47,7 +47,7 @@ grpc_millis BdpEstimator::CompletePing() {
double bw = dt > 0 ? (static_cast<double>(accumulator_) / dt) : 0;
int start_inter_ping_delay = inter_ping_delay_;
if (grpc_bdp_estimator_trace.enabled()) {
- gpr_log(GPR_DEBUG,
+ gpr_log(GPR_INFO,
"bdp[%s]:complete acc=%" PRId64 " est=%" PRId64
" dt=%lf bw=%lfMbs bw_est=%lfMbs",
name_, accumulator_, estimate_, dt, bw / 125000.0,
@@ -58,7 +58,7 @@ grpc_millis BdpEstimator::CompletePing() {
estimate_ = GPR_MAX(accumulator_, estimate_ * 2);
bw_est_ = bw;
if (grpc_bdp_estimator_trace.enabled()) {
- gpr_log(GPR_DEBUG, "bdp[%s]: estimate increased to %" PRId64, name_,
+ gpr_log(GPR_INFO, "bdp[%s]: estimate increased to %" PRId64, name_,
estimate_);
}
inter_ping_delay_ /= 2; // if the ping estimate changes,
@@ -75,7 +75,7 @@ grpc_millis BdpEstimator::CompletePing() {
if (start_inter_ping_delay != inter_ping_delay_) {
stable_estimate_count_ = 0;
if (grpc_bdp_estimator_trace.enabled()) {
- gpr_log(GPR_DEBUG, "bdp[%s]:update_inter_time to %dms", name_,
+ gpr_log(GPR_INFO, "bdp[%s]:update_inter_time to %dms", name_,
inter_ping_delay_);
}
}
diff --git a/src/core/lib/transport/bdp_estimator.h b/src/core/lib/transport/bdp_estimator.h
index e703af121c..ab13ae4be4 100644
--- a/src/core/lib/transport/bdp_estimator.h
+++ b/src/core/lib/transport/bdp_estimator.h
@@ -50,7 +50,7 @@ class BdpEstimator {
// transport (but not necessarily started)
void SchedulePing() {
if (grpc_bdp_estimator_trace.enabled()) {
- gpr_log(GPR_DEBUG, "bdp[%s]:sched acc=%" PRId64 " est=%" PRId64, name_,
+ gpr_log(GPR_INFO, "bdp[%s]:sched acc=%" PRId64 " est=%" PRId64, name_,
accumulator_, estimate_);
}
GPR_ASSERT(ping_state_ == PingState::UNSCHEDULED);
@@ -63,7 +63,7 @@ class BdpEstimator {
// the ping is on the wire
void StartPing() {
if (grpc_bdp_estimator_trace.enabled()) {
- gpr_log(GPR_DEBUG, "bdp[%s]:start acc=%" PRId64 " est=%" PRId64, name_,
+ gpr_log(GPR_INFO, "bdp[%s]:start acc=%" PRId64 " est=%" PRId64, name_,
accumulator_, estimate_);
}
GPR_ASSERT(ping_state_ == PingState::SCHEDULED);
diff --git a/src/core/lib/transport/byte_stream.cc b/src/core/lib/transport/byte_stream.cc
index cb15a71a91..16b85ca0db 100644
--- a/src/core/lib/transport/byte_stream.cc
+++ b/src/core/lib/transport/byte_stream.cc
@@ -45,7 +45,7 @@ SliceBufferByteStream::SliceBufferByteStream(grpc_slice_buffer* slice_buffer,
SliceBufferByteStream::~SliceBufferByteStream() {}
void SliceBufferByteStream::Orphan() {
- grpc_slice_buffer_destroy(&backing_buffer_);
+ grpc_slice_buffer_destroy_internal(&backing_buffer_);
GRPC_ERROR_UNREF(shutdown_error_);
// Note: We do not actually delete the object here, since
// SliceBufferByteStream is usually allocated as part of a larger
diff --git a/src/core/lib/transport/connectivity_state.cc b/src/core/lib/transport/connectivity_state.cc
index 0122e773ca..db6b6c0444 100644
--- a/src/core/lib/transport/connectivity_state.cc
+++ b/src/core/lib/transport/connectivity_state.cc
@@ -78,7 +78,7 @@ grpc_connectivity_state grpc_connectivity_state_check(
grpc_connectivity_state cur = static_cast<grpc_connectivity_state>(
gpr_atm_no_barrier_load(&tracker->current_state_atm));
if (grpc_connectivity_state_trace.enabled()) {
- gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name,
+ gpr_log(GPR_INFO, "CONWATCH: %p %s: get %s", tracker, tracker->name,
grpc_connectivity_state_name(cur));
}
return cur;
@@ -89,7 +89,7 @@ grpc_connectivity_state grpc_connectivity_state_get(
grpc_connectivity_state cur = static_cast<grpc_connectivity_state>(
gpr_atm_no_barrier_load(&tracker->current_state_atm));
if (grpc_connectivity_state_trace.enabled()) {
- gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name,
+ gpr_log(GPR_INFO, "CONWATCH: %p %s: get %s", tracker, tracker->name,
grpc_connectivity_state_name(cur));
}
if (error != nullptr) {
@@ -110,10 +110,10 @@ bool grpc_connectivity_state_notify_on_state_change(
gpr_atm_no_barrier_load(&tracker->current_state_atm));
if (grpc_connectivity_state_trace.enabled()) {
if (current == nullptr) {
- gpr_log(GPR_DEBUG, "CONWATCH: %p %s: unsubscribe notify=%p", tracker,
+ gpr_log(GPR_INFO, "CONWATCH: %p %s: unsubscribe notify=%p", tracker,
tracker->name, notify);
} else {
- gpr_log(GPR_DEBUG, "CONWATCH: %p %s: from %s [cur=%s] notify=%p", tracker,
+ gpr_log(GPR_INFO, "CONWATCH: %p %s: from %s [cur=%s] notify=%p", tracker,
tracker->name, grpc_connectivity_state_name(*current),
grpc_connectivity_state_name(cur), notify);
}
@@ -161,7 +161,7 @@ void grpc_connectivity_state_set(grpc_connectivity_state_tracker* tracker,
grpc_connectivity_state_watcher* w;
if (grpc_connectivity_state_trace.enabled()) {
const char* error_string = grpc_error_string(error);
- gpr_log(GPR_DEBUG, "SET: %p %s: %s --> %s [%s] error=%p %s", tracker,
+ gpr_log(GPR_INFO, "SET: %p %s: %s --> %s [%s] error=%p %s", tracker,
tracker->name, grpc_connectivity_state_name(cur),
grpc_connectivity_state_name(state), reason, error, error_string);
}
@@ -187,8 +187,7 @@ void grpc_connectivity_state_set(grpc_connectivity_state_tracker* tracker,
*w->current = state;
tracker->watchers = w->next;
if (grpc_connectivity_state_trace.enabled()) {
- gpr_log(GPR_DEBUG, "NOTIFY: %p %s: %p", tracker, tracker->name,
- w->notify);
+ gpr_log(GPR_INFO, "NOTIFY: %p %s: %p", tracker, tracker->name, w->notify);
}
GRPC_CLOSURE_SCHED(w->notify, GRPC_ERROR_REF(tracker->current_error));
gpr_free(w);
diff --git a/src/core/tsi/alts/handshaker/alts_handshaker_client.cc b/src/core/tsi/alts/handshaker/alts_handshaker_client.cc
index 40f30e41ca..b5268add0d 100644
--- a/src/core/tsi/alts/handshaker/alts_handshaker_client.cc
+++ b/src/core/tsi/alts/handshaker/alts_handshaker_client.cc
@@ -118,8 +118,7 @@ static grpc_byte_buffer* get_serialized_start_client(alts_tsi_event* event) {
static tsi_result handshaker_client_start_client(alts_handshaker_client* client,
alts_tsi_event* event) {
if (client == nullptr || event == nullptr) {
- gpr_log(GPR_ERROR,
- "Invalid arguments to alts_grpc_handshaker_client_start_client()");
+ gpr_log(GPR_ERROR, "Invalid arguments to handshaker_client_start_client()");
return TSI_INVALID_ARGUMENT;
}
grpc_byte_buffer* buffer = get_serialized_start_client(event);
@@ -167,8 +166,7 @@ static tsi_result handshaker_client_start_server(alts_handshaker_client* client,
alts_tsi_event* event,
grpc_slice* bytes_received) {
if (client == nullptr || event == nullptr || bytes_received == nullptr) {
- gpr_log(GPR_ERROR,
- "Invalid arguments to alts_grpc_handshaker_client_start_server()");
+ gpr_log(GPR_ERROR, "Invalid arguments to handshaker_client_start_server()");
return TSI_INVALID_ARGUMENT;
}
grpc_byte_buffer* buffer = get_serialized_start_server(event, bytes_received);
@@ -206,8 +204,7 @@ static tsi_result handshaker_client_next(alts_handshaker_client* client,
alts_tsi_event* event,
grpc_slice* bytes_received) {
if (client == nullptr || event == nullptr || bytes_received == nullptr) {
- gpr_log(GPR_ERROR,
- "Invalid arguments to alts_grpc_handshaker_client_next()");
+ gpr_log(GPR_ERROR, "Invalid arguments to handshaker_client_next()");
return TSI_INVALID_ARGUMENT;
}
grpc_byte_buffer* buffer = get_serialized_next(bytes_received);
@@ -223,6 +220,13 @@ static tsi_result handshaker_client_next(alts_handshaker_client* client,
return result;
}
+static void handshaker_client_shutdown(alts_handshaker_client* client) {
+ GPR_ASSERT(client != nullptr);
+ alts_grpc_handshaker_client* grpc_client =
+ reinterpret_cast<alts_grpc_handshaker_client*>(client);
+ GPR_ASSERT(grpc_call_cancel(grpc_client->call, nullptr) == GRPC_CALL_OK);
+}
+
static void handshaker_client_destruct(alts_handshaker_client* client) {
if (client == nullptr) {
return;
@@ -234,7 +238,8 @@ static void handshaker_client_destruct(alts_handshaker_client* client) {
static const alts_handshaker_client_vtable vtable = {
handshaker_client_start_client, handshaker_client_start_server,
- handshaker_client_next, handshaker_client_destruct};
+ handshaker_client_next, handshaker_client_shutdown,
+ handshaker_client_destruct};
alts_handshaker_client* alts_grpc_handshaker_client_create(
grpc_channel* channel, grpc_completion_queue* queue,
@@ -306,6 +311,13 @@ tsi_result alts_handshaker_client_next(alts_handshaker_client* client,
return TSI_INVALID_ARGUMENT;
}
+void alts_handshaker_client_shutdown(alts_handshaker_client* client) {
+ if (client != nullptr && client->vtable != nullptr &&
+ client->vtable->shutdown != nullptr) {
+ client->vtable->shutdown(client);
+ }
+}
+
void alts_handshaker_client_destroy(alts_handshaker_client* client) {
if (client != nullptr) {
if (client->vtable != nullptr && client->vtable->destruct != nullptr) {
diff --git a/src/core/tsi/alts/handshaker/alts_handshaker_client.h b/src/core/tsi/alts/handshaker/alts_handshaker_client.h
index fb2d2cf68e..8dd8fe440d 100644
--- a/src/core/tsi/alts/handshaker/alts_handshaker_client.h
+++ b/src/core/tsi/alts/handshaker/alts_handshaker_client.h
@@ -51,6 +51,7 @@ typedef struct alts_handshaker_client_vtable {
alts_tsi_event* event, grpc_slice* bytes_received);
tsi_result (*next)(alts_handshaker_client* client, alts_tsi_event* event,
grpc_slice* bytes_received);
+ void (*shutdown)(alts_handshaker_client* client);
void (*destruct)(alts_handshaker_client* client);
} alts_handshaker_client_vtable;
@@ -100,6 +101,15 @@ tsi_result alts_handshaker_client_next(alts_handshaker_client* client,
grpc_slice* bytes_received);
/**
+ * This method cancels previously scheduled, but yet executed handshaker
+ * requests to ALTS handshaker service. After this operation, the handshake
+ * will be shutdown, and no more handshaker requests will get scheduled.
+ *
+ * - client: ALTS handshaker client instance.
+ */
+void alts_handshaker_client_shutdown(alts_handshaker_client* client);
+
+/**
* This method destroys a ALTS handshaker client.
*
* - client: a ALTS handshaker client instance.
diff --git a/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc b/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc
index 529f2103c7..9676085380 100644
--- a/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc
+++ b/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc
@@ -241,6 +241,10 @@ static tsi_result handshaker_next(
gpr_log(GPR_ERROR, "Invalid arguments to handshaker_next()");
return TSI_INVALID_ARGUMENT;
}
+ if (self->handshake_shutdown) {
+ gpr_log(GPR_ERROR, "TSI handshake shutdown");
+ return TSI_HANDSHAKE_SHUTDOWN;
+ }
alts_tsi_handshaker* handshaker =
reinterpret_cast<alts_tsi_handshaker*>(self);
tsi_result ok = TSI_OK;
@@ -277,6 +281,16 @@ static tsi_result handshaker_next(
return TSI_ASYNC;
}
+static void handshaker_shutdown(tsi_handshaker* self) {
+ GPR_ASSERT(self != nullptr);
+ if (self->handshake_shutdown) {
+ return;
+ }
+ alts_tsi_handshaker* handshaker =
+ reinterpret_cast<alts_tsi_handshaker*>(self);
+ alts_handshaker_client_shutdown(handshaker->client);
+}
+
static void handshaker_destroy(tsi_handshaker* self) {
if (self == nullptr) {
return;
@@ -292,8 +306,10 @@ static void handshaker_destroy(tsi_handshaker* self) {
}
static const tsi_handshaker_vtable handshaker_vtable = {
- nullptr, nullptr, nullptr, nullptr, nullptr, handshaker_destroy,
- handshaker_next};
+ nullptr, nullptr,
+ nullptr, nullptr,
+ nullptr, handshaker_destroy,
+ handshaker_next, handshaker_shutdown};
static void thread_worker(void* arg) {
while (true) {
@@ -401,6 +417,11 @@ void alts_tsi_handshaker_handle_response(alts_tsi_handshaker* handshaker,
cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr);
return;
}
+ if (handshaker->base.handshake_shutdown) {
+ gpr_log(GPR_ERROR, "TSI handshake shutdown");
+ cb(TSI_HANDSHAKE_SHUTDOWN, user_data, nullptr, 0, nullptr);
+ return;
+ }
/* Failed grpc call check. */
if (!is_ok || status != GRPC_STATUS_OK) {
gpr_log(GPR_ERROR, "grpc call made to handshaker service failed");
@@ -479,5 +500,10 @@ void alts_tsi_handshaker_set_client_for_testing(
handshaker->client = client;
}
+alts_handshaker_client* alts_tsi_handshaker_get_client_for_testing(
+ alts_tsi_handshaker* handshaker) {
+ return handshaker->client;
+}
+
} // namespace internal
} // namespace grpc_core
diff --git a/src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h b/src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h
index 9b7b9bb6b1..9612071407 100644
--- a/src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h
+++ b/src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h
@@ -33,6 +33,9 @@ namespace internal {
void alts_tsi_handshaker_set_client_for_testing(alts_tsi_handshaker* handshaker,
alts_handshaker_client* client);
+alts_handshaker_client* alts_tsi_handshaker_get_client_for_testing(
+ alts_tsi_handshaker* handshaker);
+
/* For testing only. */
bool alts_tsi_handshaker_get_has_sent_start_message_for_testing(
alts_tsi_handshaker* handshaker);
diff --git a/src/core/tsi/fake_transport_security.cc b/src/core/tsi/fake_transport_security.cc
index ad08b50ede..4d4c495045 100644
--- a/src/core/tsi/fake_transport_security.cc
+++ b/src/core/tsi/fake_transport_security.cc
@@ -738,6 +738,7 @@ static const tsi_handshaker_vtable handshaker_vtable = {
nullptr, /* create_frame_protector -- deprecated */
fake_handshaker_destroy,
fake_handshaker_next,
+ nullptr, /* shutdown */
};
tsi_handshaker* tsi_create_fake_handshaker(int is_client) {
diff --git a/src/core/tsi/ssl/session_cache/ssl_session_cache.h b/src/core/tsi/ssl/session_cache/ssl_session_cache.h
index 488638c9bb..a90cca1a2e 100644
--- a/src/core/tsi/ssl/session_cache/ssl_session_cache.h
+++ b/src/core/tsi/ssl/session_cache/ssl_session_cache.h
@@ -69,6 +69,10 @@ class SslSessionLRUCache : public grpc_core::RefCounted<SslSessionLRUCache> {
template <typename T, typename... Args>
friend T* grpc_core::New(Args&&... args);
+ // So Delete() can call our private dtor.
+ template <typename T>
+ friend void grpc_core::Delete(T*);
+
class Node;
explicit SslSessionLRUCache(size_t capacity);
diff --git a/src/core/tsi/ssl_transport_security.cc b/src/core/tsi/ssl_transport_security.cc
index 0ba6587678..8065a8b185 100644
--- a/src/core/tsi/ssl_transport_security.cc
+++ b/src/core/tsi/ssl_transport_security.cc
@@ -57,6 +57,7 @@ extern "C" {
#define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND 16384
#define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND 1024
+#define TSI_SSL_HANDSHAKER_OUTGOING_BUFFER_INITIAL_SIZE 1024
/* Putting a macro like this and littering the source file with #if is really
bad practice.
@@ -105,10 +106,20 @@ typedef struct {
SSL* ssl;
BIO* network_io;
tsi_result result;
+ unsigned char* outgoing_bytes_buffer;
+ size_t outgoing_bytes_buffer_size;
tsi_ssl_handshaker_factory* factory_ref;
} tsi_ssl_handshaker;
typedef struct {
+ tsi_handshaker_result base;
+ SSL* ssl;
+ BIO* network_io;
+ unsigned char* unused_bytes;
+ size_t unused_bytes_size;
+} tsi_ssl_handshaker_result;
+
+typedef struct {
tsi_frame_protector base;
SSL* ssl;
BIO* network_io;
@@ -120,12 +131,14 @@ typedef struct {
/* --- Library Initialization. ---*/
static gpr_once g_init_openssl_once = GPR_ONCE_INIT;
-static gpr_mu* g_openssl_mutexes = nullptr;
static int g_ssl_ctx_ex_factory_index = -1;
+static const unsigned char kSslSessionIdContext[] = {'g', 'r', 'p', 'c'};
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+static gpr_mu* g_openssl_mutexes = nullptr;
static void openssl_locking_cb(int mode, int type, const char* file,
int line) GRPC_UNUSED;
static unsigned long openssl_thread_id_cb(void) GRPC_UNUSED;
-static const unsigned char kSslSessionIdContext[] = {'g', 'r', 'p', 'c'};
static void openssl_locking_cb(int mode, int type, const char* file, int line) {
if (mode & CRYPTO_LOCK) {
@@ -138,22 +151,27 @@ static void openssl_locking_cb(int mode, int type, const char* file, int line) {
static unsigned long openssl_thread_id_cb(void) {
return static_cast<unsigned long>(gpr_thd_currentid());
}
+#endif
static void init_openssl(void) {
- int i;
- int num_locks;
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
- num_locks = CRYPTO_num_locks();
- GPR_ASSERT(num_locks > 0);
- g_openssl_mutexes = static_cast<gpr_mu*>(
- gpr_malloc(static_cast<size_t>(num_locks) * sizeof(gpr_mu)));
- for (i = 0; i < CRYPTO_num_locks(); i++) {
- gpr_mu_init(&g_openssl_mutexes[i]);
- }
- CRYPTO_set_locking_callback(openssl_locking_cb);
- CRYPTO_set_id_callback(openssl_thread_id_cb);
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+ if (!CRYPTO_get_locking_callback()) {
+ int num_locks = CRYPTO_num_locks();
+ GPR_ASSERT(num_locks > 0);
+ g_openssl_mutexes = static_cast<gpr_mu*>(
+ gpr_malloc(static_cast<size_t>(num_locks) * sizeof(gpr_mu)));
+ for (int i = 0; i < num_locks; i++) {
+ gpr_mu_init(&g_openssl_mutexes[i]);
+ }
+ CRYPTO_set_locking_callback(openssl_locking_cb);
+ CRYPTO_set_id_callback(openssl_thread_id_cb);
+ } else {
+ gpr_log(GPR_INFO, "OpenSSL callback has already been set.");
+ }
+#endif
g_ssl_ctx_ex_factory_index =
SSL_CTX_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
GPR_ASSERT(g_ssl_ctx_ex_factory_index != -1);
@@ -987,94 +1005,15 @@ static void tsi_ssl_handshaker_factory_init(
gpr_ref_init(&factory->refcount, 1);
}
-/* --- tsi_handshaker methods implementation. ---*/
-
-static tsi_result ssl_handshaker_get_bytes_to_send_to_peer(tsi_handshaker* self,
- unsigned char* bytes,
- size_t* bytes_size) {
- tsi_ssl_handshaker* impl = reinterpret_cast<tsi_ssl_handshaker*>(self);
- int bytes_read_from_ssl = 0;
- if (bytes == nullptr || bytes_size == nullptr || *bytes_size == 0 ||
- *bytes_size > INT_MAX) {
- return TSI_INVALID_ARGUMENT;
- }
- GPR_ASSERT(*bytes_size <= INT_MAX);
- bytes_read_from_ssl =
- BIO_read(impl->network_io, bytes, static_cast<int>(*bytes_size));
- if (bytes_read_from_ssl < 0) {
- *bytes_size = 0;
- if (!BIO_should_retry(impl->network_io)) {
- impl->result = TSI_INTERNAL_ERROR;
- return impl->result;
- } else {
- return TSI_OK;
- }
- }
- *bytes_size = static_cast<size_t>(bytes_read_from_ssl);
- return BIO_pending(impl->network_io) == 0 ? TSI_OK : TSI_INCOMPLETE_DATA;
-}
-
-static tsi_result ssl_handshaker_get_result(tsi_handshaker* self) {
- tsi_ssl_handshaker* impl = reinterpret_cast<tsi_ssl_handshaker*>(self);
- if ((impl->result == TSI_HANDSHAKE_IN_PROGRESS) &&
- SSL_is_init_finished(impl->ssl)) {
- impl->result = TSI_OK;
- }
- return impl->result;
-}
+/* --- tsi_handshaker_result methods implementation. ---*/
-static tsi_result ssl_handshaker_process_bytes_from_peer(
- tsi_handshaker* self, const unsigned char* bytes, size_t* bytes_size) {
- tsi_ssl_handshaker* impl = reinterpret_cast<tsi_ssl_handshaker*>(self);
- int bytes_written_into_ssl_size = 0;
- if (bytes == nullptr || bytes_size == nullptr || *bytes_size > INT_MAX) {
- return TSI_INVALID_ARGUMENT;
- }
- GPR_ASSERT(*bytes_size <= INT_MAX);
- bytes_written_into_ssl_size =
- BIO_write(impl->network_io, bytes, static_cast<int>(*bytes_size));
- if (bytes_written_into_ssl_size < 0) {
- gpr_log(GPR_ERROR, "Could not write to memory BIO.");
- impl->result = TSI_INTERNAL_ERROR;
- return impl->result;
- }
- *bytes_size = static_cast<size_t>(bytes_written_into_ssl_size);
-
- if (!tsi_handshaker_is_in_progress(self)) {
- impl->result = TSI_OK;
- return impl->result;
- } else {
- /* Get ready to get some bytes from SSL. */
- int ssl_result = SSL_do_handshake(impl->ssl);
- ssl_result = SSL_get_error(impl->ssl, ssl_result);
- switch (ssl_result) {
- case SSL_ERROR_WANT_READ:
- if (BIO_pending(impl->network_io) == 0) {
- /* We need more data. */
- return TSI_INCOMPLETE_DATA;
- } else {
- return TSI_OK;
- }
- case SSL_ERROR_NONE:
- return TSI_OK;
- default: {
- char err_str[256];
- ERR_error_string_n(ERR_get_error(), err_str, sizeof(err_str));
- gpr_log(GPR_ERROR, "Handshake failed with fatal error %s: %s.",
- ssl_error_string(ssl_result), err_str);
- impl->result = TSI_PROTOCOL_FAILURE;
- return impl->result;
- }
- }
- }
-}
-
-static tsi_result ssl_handshaker_extract_peer(tsi_handshaker* self,
- tsi_peer* peer) {
+static tsi_result ssl_handshaker_result_extract_peer(
+ const tsi_handshaker_result* self, tsi_peer* peer) {
tsi_result result = TSI_OK;
const unsigned char* alpn_selected = nullptr;
unsigned int alpn_selected_len;
- tsi_ssl_handshaker* impl = reinterpret_cast<tsi_ssl_handshaker*>(self);
+ const tsi_ssl_handshaker_result* impl =
+ reinterpret_cast<const tsi_ssl_handshaker_result*>(self);
X509* peer_cert = SSL_get_peer_certificate(impl->ssl);
if (peer_cert != nullptr) {
result = peer_from_x509(peer_cert, 1, peer);
@@ -1120,12 +1059,14 @@ static tsi_result ssl_handshaker_extract_peer(tsi_handshaker* self,
return result;
}
-static tsi_result ssl_handshaker_create_frame_protector(
- tsi_handshaker* self, size_t* max_output_protected_frame_size,
+static tsi_result ssl_handshaker_result_create_frame_protector(
+ const tsi_handshaker_result* self, size_t* max_output_protected_frame_size,
tsi_frame_protector** protector) {
size_t actual_max_output_protected_frame_size =
TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
- tsi_ssl_handshaker* impl = reinterpret_cast<tsi_ssl_handshaker*>(self);
+ tsi_ssl_handshaker_result* impl =
+ reinterpret_cast<tsi_ssl_handshaker_result*>(
+ const_cast<tsi_handshaker_result*>(self));
tsi_ssl_frame_protector* protector_impl =
static_cast<tsi_ssl_frame_protector*>(
gpr_zalloc(sizeof(*protector_impl)));
@@ -1153,35 +1094,218 @@ static tsi_result ssl_handshaker_create_frame_protector(
return TSI_INTERNAL_ERROR;
}
- /* Transfer ownership of ssl and network_io to the frame protector. It is OK
- * as the caller cannot call anything else but destroy on the handshaker
- * after this call. */
+ /* Transfer ownership of ssl and network_io to the frame protector. */
protector_impl->ssl = impl->ssl;
impl->ssl = nullptr;
protector_impl->network_io = impl->network_io;
impl->network_io = nullptr;
-
protector_impl->base.vtable = &frame_protector_vtable;
*protector = &protector_impl->base;
return TSI_OK;
}
+static tsi_result ssl_handshaker_result_get_unused_bytes(
+ const tsi_handshaker_result* self, const unsigned char** bytes,
+ size_t* bytes_size) {
+ const tsi_ssl_handshaker_result* impl =
+ reinterpret_cast<const tsi_ssl_handshaker_result*>(self);
+ *bytes_size = impl->unused_bytes_size;
+ *bytes = impl->unused_bytes;
+ return TSI_OK;
+}
+
+static void ssl_handshaker_result_destroy(tsi_handshaker_result* self) {
+ tsi_ssl_handshaker_result* impl =
+ reinterpret_cast<tsi_ssl_handshaker_result*>(self);
+ SSL_free(impl->ssl);
+ BIO_free(impl->network_io);
+ gpr_free(impl->unused_bytes);
+ gpr_free(impl);
+}
+
+static const tsi_handshaker_result_vtable handshaker_result_vtable = {
+ ssl_handshaker_result_extract_peer,
+ nullptr, /* create_zero_copy_grpc_protector */
+ ssl_handshaker_result_create_frame_protector,
+ ssl_handshaker_result_get_unused_bytes,
+ ssl_handshaker_result_destroy,
+};
+
+static tsi_result ssl_handshaker_result_create(
+ tsi_ssl_handshaker* handshaker, const unsigned char* unused_bytes,
+ size_t unused_bytes_size, tsi_handshaker_result** handshaker_result) {
+ if (handshaker == nullptr || handshaker_result == nullptr ||
+ (unused_bytes_size > 0 && unused_bytes == nullptr)) {
+ return TSI_INVALID_ARGUMENT;
+ }
+ tsi_ssl_handshaker_result* result =
+ static_cast<tsi_ssl_handshaker_result*>(gpr_zalloc(sizeof(*result)));
+ result->base.vtable = &handshaker_result_vtable;
+ /* Transfer ownership of ssl and network_io to the handshaker result. */
+ result->ssl = handshaker->ssl;
+ handshaker->ssl = nullptr;
+ result->network_io = handshaker->network_io;
+ handshaker->network_io = nullptr;
+ if (unused_bytes_size > 0) {
+ result->unused_bytes =
+ static_cast<unsigned char*>(gpr_malloc(unused_bytes_size));
+ memcpy(result->unused_bytes, unused_bytes, unused_bytes_size);
+ }
+ result->unused_bytes_size = unused_bytes_size;
+ *handshaker_result = &result->base;
+ return TSI_OK;
+}
+
+/* --- tsi_handshaker methods implementation. ---*/
+
+static tsi_result ssl_handshaker_get_bytes_to_send_to_peer(
+ tsi_ssl_handshaker* impl, unsigned char* bytes, size_t* bytes_size) {
+ int bytes_read_from_ssl = 0;
+ if (bytes == nullptr || bytes_size == nullptr || *bytes_size == 0 ||
+ *bytes_size > INT_MAX) {
+ return TSI_INVALID_ARGUMENT;
+ }
+ GPR_ASSERT(*bytes_size <= INT_MAX);
+ bytes_read_from_ssl =
+ BIO_read(impl->network_io, bytes, static_cast<int>(*bytes_size));
+ if (bytes_read_from_ssl < 0) {
+ *bytes_size = 0;
+ if (!BIO_should_retry(impl->network_io)) {
+ impl->result = TSI_INTERNAL_ERROR;
+ return impl->result;
+ } else {
+ return TSI_OK;
+ }
+ }
+ *bytes_size = static_cast<size_t>(bytes_read_from_ssl);
+ return BIO_pending(impl->network_io) == 0 ? TSI_OK : TSI_INCOMPLETE_DATA;
+}
+
+static tsi_result ssl_handshaker_get_result(tsi_ssl_handshaker* impl) {
+ if ((impl->result == TSI_HANDSHAKE_IN_PROGRESS) &&
+ SSL_is_init_finished(impl->ssl)) {
+ impl->result = TSI_OK;
+ }
+ return impl->result;
+}
+
+static tsi_result ssl_handshaker_process_bytes_from_peer(
+ tsi_ssl_handshaker* impl, const unsigned char* bytes, size_t* bytes_size) {
+ int bytes_written_into_ssl_size = 0;
+ if (bytes == nullptr || bytes_size == nullptr || *bytes_size > INT_MAX) {
+ return TSI_INVALID_ARGUMENT;
+ }
+ GPR_ASSERT(*bytes_size <= INT_MAX);
+ bytes_written_into_ssl_size =
+ BIO_write(impl->network_io, bytes, static_cast<int>(*bytes_size));
+ if (bytes_written_into_ssl_size < 0) {
+ gpr_log(GPR_ERROR, "Could not write to memory BIO.");
+ impl->result = TSI_INTERNAL_ERROR;
+ return impl->result;
+ }
+ *bytes_size = static_cast<size_t>(bytes_written_into_ssl_size);
+
+ if (ssl_handshaker_get_result(impl) != TSI_HANDSHAKE_IN_PROGRESS) {
+ impl->result = TSI_OK;
+ return impl->result;
+ } else {
+ /* Get ready to get some bytes from SSL. */
+ int ssl_result = SSL_do_handshake(impl->ssl);
+ ssl_result = SSL_get_error(impl->ssl, ssl_result);
+ switch (ssl_result) {
+ case SSL_ERROR_WANT_READ:
+ if (BIO_pending(impl->network_io) == 0) {
+ /* We need more data. */
+ return TSI_INCOMPLETE_DATA;
+ } else {
+ return TSI_OK;
+ }
+ case SSL_ERROR_NONE:
+ return TSI_OK;
+ default: {
+ char err_str[256];
+ ERR_error_string_n(ERR_get_error(), err_str, sizeof(err_str));
+ gpr_log(GPR_ERROR, "Handshake failed with fatal error %s: %s.",
+ ssl_error_string(ssl_result), err_str);
+ impl->result = TSI_PROTOCOL_FAILURE;
+ return impl->result;
+ }
+ }
+ }
+}
+
static void ssl_handshaker_destroy(tsi_handshaker* self) {
tsi_ssl_handshaker* impl = reinterpret_cast<tsi_ssl_handshaker*>(self);
SSL_free(impl->ssl);
BIO_free(impl->network_io);
+ gpr_free(impl->outgoing_bytes_buffer);
tsi_ssl_handshaker_factory_unref(impl->factory_ref);
gpr_free(impl);
}
+static tsi_result ssl_handshaker_next(
+ tsi_handshaker* self, const unsigned char* received_bytes,
+ size_t received_bytes_size, const unsigned char** bytes_to_send,
+ size_t* bytes_to_send_size, tsi_handshaker_result** handshaker_result,
+ tsi_handshaker_on_next_done_cb cb, void* user_data) {
+ /* Input sanity check. */
+ if ((received_bytes_size > 0 && received_bytes == nullptr) ||
+ bytes_to_send == nullptr || bytes_to_send_size == nullptr ||
+ handshaker_result == nullptr) {
+ return TSI_INVALID_ARGUMENT;
+ }
+ /* If there are received bytes, process them first. */
+ tsi_ssl_handshaker* impl = reinterpret_cast<tsi_ssl_handshaker*>(self);
+ tsi_result status = TSI_OK;
+ size_t bytes_consumed = received_bytes_size;
+ if (received_bytes_size > 0) {
+ status = ssl_handshaker_process_bytes_from_peer(impl, received_bytes,
+ &bytes_consumed);
+ if (status != TSI_OK) return status;
+ }
+ /* Get bytes to send to the peer, if available. */
+ size_t offset = 0;
+ do {
+ size_t to_send_size = impl->outgoing_bytes_buffer_size - offset;
+ status = ssl_handshaker_get_bytes_to_send_to_peer(
+ impl, impl->outgoing_bytes_buffer + offset, &to_send_size);
+ offset += to_send_size;
+ if (status == TSI_INCOMPLETE_DATA) {
+ impl->outgoing_bytes_buffer_size *= 2;
+ impl->outgoing_bytes_buffer = static_cast<unsigned char*>(gpr_realloc(
+ impl->outgoing_bytes_buffer, impl->outgoing_bytes_buffer_size));
+ }
+ } while (status == TSI_INCOMPLETE_DATA);
+ if (status != TSI_OK) return status;
+ *bytes_to_send = impl->outgoing_bytes_buffer;
+ *bytes_to_send_size = offset;
+ /* If handshake completes, create tsi_handshaker_result. */
+ if (ssl_handshaker_get_result(impl) == TSI_HANDSHAKE_IN_PROGRESS) {
+ *handshaker_result = nullptr;
+ } else {
+ size_t unused_bytes_size = received_bytes_size - bytes_consumed;
+ const unsigned char* unused_bytes =
+ unused_bytes_size == 0 ? nullptr : received_bytes + bytes_consumed;
+ status = ssl_handshaker_result_create(impl, unused_bytes, unused_bytes_size,
+ handshaker_result);
+ if (status == TSI_OK) {
+ /* Indicates that the handshake has completed and that a handshaker_result
+ * has been created. */
+ self->handshaker_result_created = true;
+ }
+ }
+ return status;
+}
+
static const tsi_handshaker_vtable handshaker_vtable = {
- ssl_handshaker_get_bytes_to_send_to_peer,
- ssl_handshaker_process_bytes_from_peer,
- ssl_handshaker_get_result,
- ssl_handshaker_extract_peer,
- ssl_handshaker_create_frame_protector,
+ nullptr, /* get_bytes_to_send_to_peer -- deprecated */
+ nullptr, /* process_bytes_from_peer -- deprecated */
+ nullptr, /* get_result -- deprecated */
+ nullptr, /* extract_peer -- deprecated */
+ nullptr, /* create_frame_protector -- deprecated */
ssl_handshaker_destroy,
- nullptr,
+ ssl_handshaker_next,
+ nullptr, /* shutdown */
};
/* --- tsi_ssl_handshaker_factory common methods. --- */
@@ -1259,6 +1383,10 @@ static tsi_result create_tsi_ssl_handshaker(SSL_CTX* ctx, int is_client,
impl->ssl = ssl;
impl->network_io = network_io;
impl->result = TSI_HANDSHAKE_IN_PROGRESS;
+ impl->outgoing_bytes_buffer_size =
+ TSI_SSL_HANDSHAKER_OUTGOING_BUFFER_INITIAL_SIZE;
+ impl->outgoing_bytes_buffer =
+ static_cast<unsigned char*>(gpr_zalloc(impl->outgoing_bytes_buffer_size));
impl->base.vtable = &handshaker_vtable;
impl->factory_ref = tsi_ssl_handshaker_factory_ref(factory);
diff --git a/src/core/tsi/transport_security.cc b/src/core/tsi/transport_security.cc
index 129533f779..99b3229e88 100644
--- a/src/core/tsi/transport_security.cc
+++ b/src/core/tsi/transport_security.cc
@@ -136,6 +136,7 @@ tsi_result tsi_handshaker_get_bytes_to_send_to_peer(tsi_handshaker* self,
return TSI_INVALID_ARGUMENT;
}
if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
+ if (self->handshake_shutdown) return TSI_HANDSHAKE_SHUTDOWN;
if (self->vtable->get_bytes_to_send_to_peer == nullptr)
return TSI_UNIMPLEMENTED;
return self->vtable->get_bytes_to_send_to_peer(self, bytes, bytes_size);
@@ -149,6 +150,7 @@ tsi_result tsi_handshaker_process_bytes_from_peer(tsi_handshaker* self,
return TSI_INVALID_ARGUMENT;
}
if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
+ if (self->handshake_shutdown) return TSI_HANDSHAKE_SHUTDOWN;
if (self->vtable->process_bytes_from_peer == nullptr)
return TSI_UNIMPLEMENTED;
return self->vtable->process_bytes_from_peer(self, bytes, bytes_size);
@@ -157,6 +159,7 @@ tsi_result tsi_handshaker_process_bytes_from_peer(tsi_handshaker* self,
tsi_result tsi_handshaker_get_result(tsi_handshaker* self) {
if (self == nullptr || self->vtable == nullptr) return TSI_INVALID_ARGUMENT;
if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
+ if (self->handshake_shutdown) return TSI_HANDSHAKE_SHUTDOWN;
if (self->vtable->get_result == nullptr) return TSI_UNIMPLEMENTED;
return self->vtable->get_result(self);
}
@@ -167,6 +170,7 @@ tsi_result tsi_handshaker_extract_peer(tsi_handshaker* self, tsi_peer* peer) {
}
memset(peer, 0, sizeof(tsi_peer));
if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
+ if (self->handshake_shutdown) return TSI_HANDSHAKE_SHUTDOWN;
if (tsi_handshaker_get_result(self) != TSI_OK) {
return TSI_FAILED_PRECONDITION;
}
@@ -182,6 +186,7 @@ tsi_result tsi_handshaker_create_frame_protector(
return TSI_INVALID_ARGUMENT;
}
if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
+ if (self->handshake_shutdown) return TSI_HANDSHAKE_SHUTDOWN;
if (tsi_handshaker_get_result(self) != TSI_OK) return TSI_FAILED_PRECONDITION;
if (self->vtable->create_frame_protector == nullptr) return TSI_UNIMPLEMENTED;
result = self->vtable->create_frame_protector(self, max_protected_frame_size,
@@ -199,12 +204,21 @@ tsi_result tsi_handshaker_next(
tsi_handshaker_on_next_done_cb cb, void* user_data) {
if (self == nullptr || self->vtable == nullptr) return TSI_INVALID_ARGUMENT;
if (self->handshaker_result_created) return TSI_FAILED_PRECONDITION;
+ if (self->handshake_shutdown) return TSI_HANDSHAKE_SHUTDOWN;
if (self->vtable->next == nullptr) return TSI_UNIMPLEMENTED;
return self->vtable->next(self, received_bytes, received_bytes_size,
bytes_to_send, bytes_to_send_size,
handshaker_result, cb, user_data);
}
+void tsi_handshaker_shutdown(tsi_handshaker* self) {
+ if (self == nullptr || self->vtable == nullptr) return;
+ self->handshake_shutdown = true;
+ if (self->vtable->shutdown != nullptr) {
+ self->vtable->shutdown(self);
+ }
+}
+
void tsi_handshaker_destroy(tsi_handshaker* self) {
if (self == nullptr) return;
self->vtable->destroy(self);
diff --git a/src/core/tsi/transport_security.h b/src/core/tsi/transport_security.h
index b1ec82d3f7..1923a702e5 100644
--- a/src/core/tsi/transport_security.h
+++ b/src/core/tsi/transport_security.h
@@ -73,12 +73,14 @@ typedef struct {
size_t* bytes_to_send_size,
tsi_handshaker_result** handshaker_result,
tsi_handshaker_on_next_done_cb cb, void* user_data);
+ void (*shutdown)(tsi_handshaker* self);
} tsi_handshaker_vtable;
struct tsi_handshaker {
const tsi_handshaker_vtable* vtable;
bool frame_protector_created;
bool handshaker_result_created;
+ bool handshake_shutdown;
};
/* Base for tsi_handshaker_result implementations.
diff --git a/src/core/tsi/transport_security_adapter.cc b/src/core/tsi/transport_security_adapter.cc
deleted file mode 100644
index 25608f065a..0000000000
--- a/src/core/tsi/transport_security_adapter.cc
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- *
- * Copyright 2017 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/tsi/transport_security_adapter.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include "src/core/tsi/transport_security.h"
-
-#define TSI_ADAPTER_INITIAL_BUFFER_SIZE 256
-
-/* --- tsi_adapter_handshaker_result implementation ---*/
-
-typedef struct {
- tsi_handshaker_result base;
- tsi_handshaker* wrapped;
- unsigned char* unused_bytes;
- size_t unused_bytes_size;
-} tsi_adapter_handshaker_result;
-
-static tsi_result adapter_result_extract_peer(const tsi_handshaker_result* self,
- tsi_peer* peer) {
- tsi_adapter_handshaker_result* impl = (tsi_adapter_handshaker_result*)self;
- return tsi_handshaker_extract_peer(impl->wrapped, peer);
-}
-
-static tsi_result adapter_result_create_frame_protector(
- const tsi_handshaker_result* self, size_t* max_output_protected_frame_size,
- tsi_frame_protector** protector) {
- tsi_adapter_handshaker_result* impl = (tsi_adapter_handshaker_result*)self;
- return tsi_handshaker_create_frame_protector(
- impl->wrapped, max_output_protected_frame_size, protector);
-}
-
-static tsi_result adapter_result_get_unused_bytes(
- const tsi_handshaker_result* self, const unsigned char** bytes,
- size_t* byte_size) {
- tsi_adapter_handshaker_result* impl = (tsi_adapter_handshaker_result*)self;
- *bytes = impl->unused_bytes;
- *byte_size = impl->unused_bytes_size;
- return TSI_OK;
-}
-
-static void adapter_result_destroy(tsi_handshaker_result* self) {
- tsi_adapter_handshaker_result* impl =
- reinterpret_cast<tsi_adapter_handshaker_result*>(self);
- tsi_handshaker_destroy(impl->wrapped);
- gpr_free(impl->unused_bytes);
- gpr_free(self);
-}
-
-static const tsi_handshaker_result_vtable result_vtable = {
- adapter_result_extract_peer,
- nullptr, /* create_zero_copy_grpc_protector */
- adapter_result_create_frame_protector,
- adapter_result_get_unused_bytes,
- adapter_result_destroy,
-};
-
-/* Ownership of wrapped tsi_handshaker is transferred to the result object. */
-static tsi_result tsi_adapter_create_handshaker_result(
- tsi_handshaker* wrapped, const unsigned char* unused_bytes,
- size_t unused_bytes_size, tsi_handshaker_result** handshaker_result) {
- if (wrapped == nullptr ||
- (unused_bytes_size > 0 && unused_bytes == nullptr)) {
- return TSI_INVALID_ARGUMENT;
- }
- tsi_adapter_handshaker_result* impl =
- static_cast<tsi_adapter_handshaker_result*>(gpr_zalloc(sizeof(*impl)));
- impl->base.vtable = &result_vtable;
- impl->wrapped = wrapped;
- impl->unused_bytes_size = unused_bytes_size;
- if (unused_bytes_size > 0) {
- impl->unused_bytes =
- static_cast<unsigned char*>(gpr_malloc(unused_bytes_size));
- memcpy(impl->unused_bytes, unused_bytes, unused_bytes_size);
- } else {
- impl->unused_bytes = nullptr;
- }
- *handshaker_result = &impl->base;
- return TSI_OK;
-}
-
-/* --- tsi_adapter_handshaker implementation ---*/
-
-typedef struct {
- tsi_handshaker base;
- tsi_handshaker* wrapped;
- unsigned char* adapter_buffer;
- size_t adapter_buffer_size;
-} tsi_adapter_handshaker;
-
-static tsi_result adapter_get_bytes_to_send_to_peer(tsi_handshaker* self,
- unsigned char* bytes,
- size_t* bytes_size) {
- return tsi_handshaker_get_bytes_to_send_to_peer(
- tsi_adapter_handshaker_get_wrapped(self), bytes, bytes_size);
-}
-
-static tsi_result adapter_process_bytes_from_peer(tsi_handshaker* self,
- const unsigned char* bytes,
- size_t* bytes_size) {
- return tsi_handshaker_process_bytes_from_peer(
- tsi_adapter_handshaker_get_wrapped(self), bytes, bytes_size);
-}
-
-static tsi_result adapter_get_result(tsi_handshaker* self) {
- return tsi_handshaker_get_result(tsi_adapter_handshaker_get_wrapped(self));
-}
-
-static tsi_result adapter_extract_peer(tsi_handshaker* self, tsi_peer* peer) {
- return tsi_handshaker_extract_peer(tsi_adapter_handshaker_get_wrapped(self),
- peer);
-}
-
-static tsi_result adapter_create_frame_protector(
- tsi_handshaker* self, size_t* max_protected_frame_size,
- tsi_frame_protector** protector) {
- return tsi_handshaker_create_frame_protector(
- tsi_adapter_handshaker_get_wrapped(self), max_protected_frame_size,
- protector);
-}
-
-static void adapter_destroy(tsi_handshaker* self) {
- tsi_adapter_handshaker* impl =
- reinterpret_cast<tsi_adapter_handshaker*>(self);
- tsi_handshaker_destroy(impl->wrapped);
- gpr_free(impl->adapter_buffer);
- gpr_free(self);
-}
-
-static tsi_result adapter_next(
- tsi_handshaker* self, const unsigned char* received_bytes,
- size_t received_bytes_size, const unsigned char** bytes_to_send,
- size_t* bytes_to_send_size, tsi_handshaker_result** handshaker_result,
- tsi_handshaker_on_next_done_cb cb, void* user_data) {
- /* Input sanity check. */
- if ((received_bytes_size > 0 && received_bytes == nullptr) ||
- bytes_to_send == nullptr || bytes_to_send_size == nullptr ||
- handshaker_result == nullptr) {
- return TSI_INVALID_ARGUMENT;
- }
-
- /* If there are received bytes, process them first. */
- tsi_adapter_handshaker* impl =
- reinterpret_cast<tsi_adapter_handshaker*>(self);
- tsi_result status = TSI_OK;
- size_t bytes_consumed = received_bytes_size;
- if (received_bytes_size > 0) {
- status = tsi_handshaker_process_bytes_from_peer(
- impl->wrapped, received_bytes, &bytes_consumed);
- if (status != TSI_OK) return status;
- }
-
- /* Get bytes to send to the peer, if available. */
- size_t offset = 0;
- do {
- size_t to_send_size = impl->adapter_buffer_size - offset;
- status = tsi_handshaker_get_bytes_to_send_to_peer(
- impl->wrapped, impl->adapter_buffer + offset, &to_send_size);
- offset += to_send_size;
- if (status == TSI_INCOMPLETE_DATA) {
- impl->adapter_buffer_size *= 2;
- impl->adapter_buffer = static_cast<unsigned char*>(
- gpr_realloc(impl->adapter_buffer, impl->adapter_buffer_size));
- }
- } while (status == TSI_INCOMPLETE_DATA);
- if (status != TSI_OK) return status;
- *bytes_to_send = impl->adapter_buffer;
- *bytes_to_send_size = offset;
-
- /* If handshake completes, create tsi_handshaker_result. */
- if (tsi_handshaker_is_in_progress(impl->wrapped)) {
- *handshaker_result = nullptr;
- } else {
- size_t unused_bytes_size = received_bytes_size - bytes_consumed;
- const unsigned char* unused_bytes =
- unused_bytes_size == 0 ? nullptr : received_bytes + bytes_consumed;
- status = tsi_adapter_create_handshaker_result(
- impl->wrapped, unused_bytes, unused_bytes_size, handshaker_result);
- if (status == TSI_OK) {
- impl->base.handshaker_result_created = true;
- impl->wrapped = nullptr;
- }
- }
- return status;
-}
-
-static const tsi_handshaker_vtable handshaker_vtable = {
- adapter_get_bytes_to_send_to_peer,
- adapter_process_bytes_from_peer,
- adapter_get_result,
- adapter_extract_peer,
- adapter_create_frame_protector,
- adapter_destroy,
- adapter_next,
-};
-
-tsi_handshaker* tsi_create_adapter_handshaker(tsi_handshaker* wrapped) {
- GPR_ASSERT(wrapped != nullptr);
- tsi_adapter_handshaker* impl =
- static_cast<tsi_adapter_handshaker*>(gpr_zalloc(sizeof(*impl)));
- impl->base.vtable = &handshaker_vtable;
- impl->wrapped = wrapped;
- impl->adapter_buffer_size = TSI_ADAPTER_INITIAL_BUFFER_SIZE;
- impl->adapter_buffer =
- static_cast<unsigned char*>(gpr_malloc(impl->adapter_buffer_size));
- return &impl->base;
-}
-
-tsi_handshaker* tsi_adapter_handshaker_get_wrapped(tsi_handshaker* adapter) {
- if (adapter == nullptr) return nullptr;
- tsi_adapter_handshaker* impl =
- reinterpret_cast<tsi_adapter_handshaker*>(adapter);
- return impl->wrapped;
-}
diff --git a/src/core/tsi/transport_security_adapter.h b/src/core/tsi/transport_security_adapter.h
deleted file mode 100644
index f83ecc53e5..0000000000
--- a/src/core/tsi/transport_security_adapter.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *
- * Copyright 2017 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef GRPC_CORE_TSI_TRANSPORT_SECURITY_ADAPTER_H
-#define GRPC_CORE_TSI_TRANSPORT_SECURITY_ADAPTER_H
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/tsi/transport_security_interface.h"
-
-/* Create a tsi handshaker that takes an implementation of old interface and
- converts into an implementation of new interface. In the old interface,
- there are get_bytes_to_send_to_peer, process_bytes_from_peer, get_result,
- extract_peer, and create_frame_protector. In the new interface, only next
- method is needed. See transport_security_interface.h for details. Note that
- this tsi adapter handshaker is temporary. It will be removed once TSI has
- been fully migrated to the new interface.
- Ownership of input tsi_handshaker is transferred to this new adapter. */
-tsi_handshaker* tsi_create_adapter_handshaker(tsi_handshaker* wrapped);
-
-/* Given a tsi adapter handshaker, return the original wrapped handshaker. The
- adapter still owns the wrapped handshaker which should not be destroyed by
- the caller. */
-tsi_handshaker* tsi_adapter_handshaker_get_wrapped(tsi_handshaker* adapter);
-
-#endif /* GRPC_CORE_TSI_TRANSPORT_SECURITY_ADAPTER_H */
diff --git a/src/core/tsi/transport_security_interface.h b/src/core/tsi/transport_security_interface.h
index 8c10866934..7a0cdc3453 100644
--- a/src/core/tsi/transport_security_interface.h
+++ b/src/core/tsi/transport_security_interface.h
@@ -42,7 +42,8 @@ typedef enum {
TSI_PROTOCOL_FAILURE = 10,
TSI_HANDSHAKE_IN_PROGRESS = 11,
TSI_OUT_OF_RESOURCES = 12,
- TSI_ASYNC = 13
+ TSI_ASYNC = 13,
+ TSI_HANDSHAKE_SHUTDOWN = 14,
} tsi_result;
typedef enum {
@@ -332,6 +333,8 @@ void tsi_handshaker_result_destroy(tsi_handshaker_result* self);
------------------------------------------------------------------------ */
typedef struct tsi_handshaker tsi_handshaker;
+/* TODO(jiangtaoli2016): Cleans up deprecated methods when we are ready. */
+
/* TO BE DEPRECATED SOON. Use tsi_handshaker_next instead.
Gets bytes that need to be sent to the peer.
- bytes is the buffer that will be written with the data to be sent to the
@@ -440,6 +443,13 @@ tsi_result tsi_handshaker_next(
size_t* bytes_to_send_size, tsi_handshaker_result** handshaker_result,
tsi_handshaker_on_next_done_cb cb, void* user_data);
+/* This method shuts down a TSI handshake that is in progress.
+ *
+ * This method will be invoked when TSI handshake should be terminated before
+ * being finished in order to free any resources being used.
+ */
+void tsi_handshaker_shutdown(tsi_handshaker* self);
+
/* This method releases the tsi_handshaker object. After this method is called,
no other method can be called on the object. */
void tsi_handshaker_destroy(tsi_handshaker* self);
diff --git a/src/cpp/common/version_cc.cc b/src/cpp/common/version_cc.cc
index d669ea21a9..54cd2076ec 100644
--- a/src/cpp/common/version_cc.cc
+++ b/src/cpp/common/version_cc.cc
@@ -22,5 +22,5 @@
#include <grpcpp/grpcpp.h>
namespace grpc {
-grpc::string Version() { return "1.12.0-dev"; }
+grpc::string Version() { return "1.13.0-dev"; }
} // namespace grpc
diff --git a/src/cpp/server/load_reporter/load_data_store.cc b/src/cpp/server/load_reporter/load_data_store.cc
new file mode 100644
index 0000000000..70f12c1102
--- /dev/null
+++ b/src/cpp/server/load_reporter/load_data_store.cc
@@ -0,0 +1,273 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <cstdlib>
+#include <set>
+#include <unordered_map>
+#include <vector>
+
+#include "src/cpp/server/load_reporter/load_data_store.h"
+
+namespace grpc {
+namespace load_reporter {
+
+// Some helper functions.
+namespace {
+
+// Given a map from type K to a set of value type V, finds the set associated
+// with the given key and erases the value from the set. If the set becomes
+// empty, also erases the key-set pair. Returns true if the value is erased
+// successfully.
+template <typename K, typename V>
+bool UnorderedMapOfSetEraseKeyValue(std::unordered_map<K, std::set<V>>& map,
+ const K& key, const V& value) {
+ auto it = map.find(key);
+ if (it != map.end()) {
+ size_t erased = it->second.erase(value);
+ if (it->second.size() == 0) {
+ map.erase(it);
+ }
+ return erased;
+ }
+ return false;
+};
+
+// Given a map from type K to a set of value type V, removes the given key and
+// the associated set, and returns the set. Returns an empty set if the key is
+// not found.
+template <typename K, typename V>
+std::set<V> UnorderedMapOfSetExtract(std::unordered_map<K, std::set<V>>& map,
+ const K& key) {
+ auto it = map.find(key);
+ if (it != map.end()) {
+ auto set = std::move(it->second);
+ map.erase(it);
+ return set;
+ }
+ return {};
+};
+
+// From a non-empty container, returns a pointer to a random element.
+template <typename C>
+const typename C::value_type* RandomElement(const C& container) {
+ GPR_ASSERT(!container.empty());
+ auto it = container.begin();
+ std::advance(it, std::rand() % container.size());
+ return &(*it);
+}
+
+} // namespace
+
+void PerBalancerStore::MergeRow(const LoadRecordKey& key,
+ const LoadRecordValue& value) {
+ // During suspension, the load data received will be dropped.
+ if (!suspended_) {
+ load_record_map_[key].MergeFrom(value);
+ gpr_log(GPR_DEBUG,
+ "[PerBalancerStore %p] Load data merged (Key: %s, Value: %s).",
+ this, key.ToString().c_str(), value.ToString().c_str());
+ } else {
+ gpr_log(GPR_DEBUG,
+ "[PerBalancerStore %p] Load data dropped (Key: %s, Value: %s).",
+ this, key.ToString().c_str(), value.ToString().c_str());
+ }
+ // We always keep track of num_calls_in_progress_, so that when this
+ // store is resumed, we still have a correct value of
+ // num_calls_in_progress_.
+ GPR_ASSERT(static_cast<int64_t>(num_calls_in_progress_) +
+ value.GetNumCallsInProgressDelta() >=
+ 0);
+ num_calls_in_progress_ += value.GetNumCallsInProgressDelta();
+}
+
+void PerBalancerStore::Suspend() {
+ suspended_ = true;
+ load_record_map_.clear();
+ gpr_log(GPR_DEBUG, "[PerBalancerStore %p] Suspended.", this);
+}
+
+void PerBalancerStore::Resume() {
+ suspended_ = false;
+ gpr_log(GPR_DEBUG, "[PerBalancerStore %p] Resumed.", this);
+}
+
+uint64_t PerBalancerStore::GetNumCallsInProgressForReport() {
+ GPR_ASSERT(!suspended_);
+ last_reported_num_calls_in_progress_ = num_calls_in_progress_;
+ return num_calls_in_progress_;
+}
+
+void PerHostStore::ReportStreamCreated(const grpc::string& lb_id,
+ const grpc::string& load_key) {
+ GPR_ASSERT(lb_id != kInvalidLbId);
+ SetUpForNewLbId(lb_id, load_key);
+ // Prior to this one, there was no load balancer receiving report, so we may
+ // have unassigned orphaned stores to assign to this new balancer.
+ // TODO(juanlishen): If the load key of this new stream is the same with
+ // some previously adopted orphan store, we may want to take the orphan to
+ // this stream. Need to discuss with LB team.
+ if (assigned_stores_.size() == 1) {
+ for (const auto& p : per_balancer_stores_) {
+ const grpc::string& other_lb_id = p.first;
+ const std::unique_ptr<PerBalancerStore>& orphaned_store = p.second;
+ if (other_lb_id != lb_id) {
+ orphaned_store->Resume();
+ AssignOrphanedStore(orphaned_store.get(), lb_id);
+ }
+ }
+ }
+ // The first connected balancer will adopt the kInvalidLbId.
+ if (per_balancer_stores_.size() == 1) {
+ SetUpForNewLbId(kInvalidLbId, "");
+ ReportStreamClosed(kInvalidLbId);
+ }
+}
+
+void PerHostStore::ReportStreamClosed(const grpc::string& lb_id) {
+ auto it_store_for_gone_lb = per_balancer_stores_.find(lb_id);
+ GPR_ASSERT(it_store_for_gone_lb != per_balancer_stores_.end());
+ // Remove this closed stream from our records.
+ GPR_ASSERT(UnorderedMapOfSetEraseKeyValue(
+ load_key_to_receiving_lb_ids_, it_store_for_gone_lb->second->load_key(),
+ lb_id));
+ std::set<PerBalancerStore*> orphaned_stores =
+ UnorderedMapOfSetExtract(assigned_stores_, lb_id);
+ // The stores that were assigned to this balancer are orphaned now. They
+ // should be re-assigned to other balancers which are still receiving reports.
+ for (PerBalancerStore* orphaned_store : orphaned_stores) {
+ const grpc::string* new_receiver = nullptr;
+ auto it = load_key_to_receiving_lb_ids_.find(orphaned_store->load_key());
+ if (it != load_key_to_receiving_lb_ids_.end()) {
+ // First, try to pick from the active balancers with the same load key.
+ new_receiver = RandomElement(it->second);
+ } else if (!assigned_stores_.empty()) {
+ // If failed, pick from all the remaining active balancers.
+ new_receiver = &(RandomElement(assigned_stores_)->first);
+ }
+ if (new_receiver != nullptr) {
+ AssignOrphanedStore(orphaned_store, *new_receiver);
+ } else {
+ // Load data for an LB ID that can't be assigned to any stream should
+ // be dropped.
+ orphaned_store->Suspend();
+ }
+ }
+}
+
+PerBalancerStore* PerHostStore::FindPerBalancerStore(
+ const grpc::string& lb_id) const {
+ return per_balancer_stores_.find(lb_id) != per_balancer_stores_.end()
+ ? per_balancer_stores_.find(lb_id)->second.get()
+ : nullptr;
+}
+
+const std::set<PerBalancerStore*>* PerHostStore::GetAssignedStores(
+ const grpc::string& lb_id) const {
+ auto it = assigned_stores_.find(lb_id);
+ if (it == assigned_stores_.end()) return nullptr;
+ return &(it->second);
+}
+
+void PerHostStore::AssignOrphanedStore(PerBalancerStore* orphaned_store,
+ const grpc::string& new_receiver) {
+ auto it = assigned_stores_.find(new_receiver);
+ GPR_ASSERT(it != assigned_stores_.end());
+ it->second.insert(orphaned_store);
+ gpr_log(GPR_INFO,
+ "[PerHostStore %p] Re-assigned orphaned store (%p) with original LB"
+ " ID of %s to new receiver %s",
+ this, orphaned_store, orphaned_store->lb_id().c_str(),
+ new_receiver.c_str());
+}
+
+void PerHostStore::SetUpForNewLbId(const grpc::string& lb_id,
+ const grpc::string& load_key) {
+ // The top-level caller (i.e., LoadReportService) should guarantee the
+ // lb_id is unique for each reporting stream.
+ GPR_ASSERT(per_balancer_stores_.find(lb_id) == per_balancer_stores_.end());
+ GPR_ASSERT(assigned_stores_.find(lb_id) == assigned_stores_.end());
+ load_key_to_receiving_lb_ids_[load_key].insert(lb_id);
+ std::unique_ptr<PerBalancerStore> per_balancer_store(
+ new PerBalancerStore(lb_id, load_key));
+ assigned_stores_[lb_id] = {per_balancer_store.get()};
+ per_balancer_stores_[lb_id] = std::move(per_balancer_store);
+}
+
+PerBalancerStore* LoadDataStore::FindPerBalancerStore(
+ const string& hostname, const string& lb_id) const {
+ auto it = per_host_stores_.find(hostname);
+ if (it != per_host_stores_.end()) {
+ const PerHostStore& per_host_store = it->second;
+ return per_host_store.FindPerBalancerStore(lb_id);
+ } else {
+ return nullptr;
+ }
+}
+
+void LoadDataStore::MergeRow(const grpc::string& hostname,
+ const LoadRecordKey& key,
+ const LoadRecordValue& value) {
+ PerBalancerStore* per_balancer_store =
+ FindPerBalancerStore(hostname, key.lb_id());
+ if (per_balancer_store != nullptr) {
+ per_balancer_store->MergeRow(key, value);
+ return;
+ }
+ // Unknown LB ID. Track it until its number of in-progress calls drops to
+ // zero.
+ int64_t in_progress_delta = value.GetNumCallsInProgressDelta();
+ if (in_progress_delta != 0) {
+ auto it_tracker = unknown_balancer_id_trackers_.find(key.lb_id());
+ if (it_tracker == unknown_balancer_id_trackers_.end()) {
+ gpr_log(
+ GPR_DEBUG,
+ "[LoadDataStore %p] Start tracking unknown balancer (lb_id_: %s).",
+ this, key.lb_id().c_str());
+ unknown_balancer_id_trackers_.insert(
+ {key.lb_id(), static_cast<uint64_t>(in_progress_delta)});
+ } else if ((it_tracker->second += in_progress_delta) == 0) {
+ unknown_balancer_id_trackers_.erase(it_tracker);
+ gpr_log(GPR_DEBUG,
+ "[LoadDataStore %p] Stop tracking unknown balancer (lb_id_: %s).",
+ this, key.lb_id().c_str());
+ }
+ }
+}
+
+const std::set<PerBalancerStore*>* LoadDataStore::GetAssignedStores(
+ const grpc::string& hostname, const grpc::string& lb_id) {
+ auto it = per_host_stores_.find(hostname);
+ if (it == per_host_stores_.end()) return nullptr;
+ return it->second.GetAssignedStores(lb_id);
+}
+
+void LoadDataStore::ReportStreamCreated(const grpc::string& hostname,
+ const grpc::string& lb_id,
+ const grpc::string& load_key) {
+ per_host_stores_[hostname].ReportStreamCreated(lb_id, load_key);
+}
+
+void LoadDataStore::ReportStreamClosed(const grpc::string& hostname,
+ const grpc::string& lb_id) {
+ auto it_per_host_store = per_host_stores_.find(hostname);
+ GPR_ASSERT(it_per_host_store != per_host_stores_.end());
+ it_per_host_store->second.ReportStreamClosed(lb_id);
+}
+
+} // namespace load_reporter
+} // namespace grpc
diff --git a/src/cpp/server/load_reporter/load_data_store.h b/src/cpp/server/load_reporter/load_data_store.h
new file mode 100644
index 0000000000..feb8b2fd59
--- /dev/null
+++ b/src/cpp/server/load_reporter/load_data_store.h
@@ -0,0 +1,339 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPC_SRC_CPP_SERVER_LOAD_REPORTER_LOAD_DATA_STORE_H
+#define GRPC_SRC_CPP_SERVER_LOAD_REPORTER_LOAD_DATA_STORE_H
+
+#include <grpc/support/port_platform.h>
+
+#include <memory>
+#include <set>
+#include <unordered_map>
+
+#include <grpc/support/log.h>
+#include <grpcpp/impl/codegen/config.h>
+
+namespace grpc {
+namespace load_reporter {
+
+constexpr char kInvalidLbId[] = "<INVALID_LBID_238dsb234890rb>";
+constexpr uint8_t kLbIdLen = 8;
+
+// The load data storage is organized in hierarchy. The LoadDataStore is the
+// top-level data store. In LoadDataStore, for each host we keep a
+// PerHostStore, in which for each balancer we keep a PerBalancerStore. Each
+// PerBalancerStore maintains a map of load records, mapping from LoadRecordKey
+// to LoadRecordValue. The LoadRecordValue contains a map of customized call
+// metrics, mapping from a call metric name to the CallMetricValue.
+
+// The value of a customized call metric.
+class CallMetricValue {
+ public:
+ explicit CallMetricValue(uint64_t num_calls = 0,
+ double total_metric_value = 0)
+ : num_calls_(num_calls), total_metric_value_(total_metric_value) {}
+
+ void MergeFrom(CallMetricValue other) {
+ num_calls_ += other.num_calls_;
+ total_metric_value_ += other.total_metric_value_;
+ }
+
+ // Getters.
+ uint64_t num_calls() const { return num_calls_; }
+ double total_metric_value() const { return total_metric_value_; }
+
+ private:
+ // The number of calls that finished with this metric.
+ uint64_t num_calls_ = 0;
+ // The sum of metric values across all the calls that finished with this
+ // metric.
+ double total_metric_value_ = 0;
+};
+
+// The key of a load record.
+class LoadRecordKey {
+ public:
+ explicit LoadRecordKey(grpc::string lb_id, grpc::string lb_tag,
+ grpc::string user_id, grpc::string client_ip_hex)
+ : lb_id_(std::move(lb_id)),
+ lb_tag_(std::move(lb_tag)),
+ user_id_(std::move(user_id)),
+ client_ip_hex_(std::move(client_ip_hex)) {}
+
+ grpc::string ToString() const {
+ return "[lb_id_=" + lb_id_ + ", lb_tag_=" + lb_tag_ +
+ ", user_id_=" + user_id_ + ", client_ip_hex_=" + client_ip_hex_ +
+ "]";
+ }
+
+ bool operator==(const LoadRecordKey& other) const {
+ return lb_id_ == other.lb_id_ && lb_tag_ == other.lb_tag_ &&
+ user_id_ == other.user_id_ && client_ip_hex_ == other.client_ip_hex_;
+ }
+
+ // Getters.
+ const grpc::string& lb_id() const { return lb_id_; }
+ const grpc::string& lb_tag() const { return lb_tag_; }
+ const grpc::string& user_id() const { return user_id_; }
+ const grpc::string& client_ip_hex() const { return client_ip_hex_; }
+
+ struct Hasher {
+ void hash_combine(size_t* seed, const grpc::string& k) const {
+ *seed ^= std::hash<grpc::string>()(k) + 0x9e3779b9 + (*seed << 6) +
+ (*seed >> 2);
+ }
+
+ size_t operator()(const LoadRecordKey& k) const {
+ size_t h = 0;
+ hash_combine(&h, k.lb_id_);
+ hash_combine(&h, k.lb_tag_);
+ hash_combine(&h, k.user_id_);
+ hash_combine(&h, k.client_ip_hex_);
+ return h;
+ }
+ };
+
+ private:
+ grpc::string lb_id_;
+ grpc::string lb_tag_;
+ grpc::string user_id_;
+ grpc::string client_ip_hex_;
+};
+
+// The value of a load record.
+class LoadRecordValue {
+ public:
+ explicit LoadRecordValue(uint64_t start_count = 0, uint64_t ok_count = 0,
+ uint64_t error_count = 0, double bytes_sent = 0,
+ double bytes_recv = 0, double latency_ms = 0)
+ : start_count_(start_count),
+ ok_count_(ok_count),
+ error_count_(error_count),
+ bytes_sent_(bytes_sent),
+ bytes_recv_(bytes_recv),
+ latency_ms_(latency_ms) {}
+
+ void MergeFrom(const LoadRecordValue& other) {
+ start_count_ += other.start_count_;
+ ok_count_ += other.ok_count_;
+ error_count_ += other.error_count_;
+ bytes_sent_ += other.bytes_sent_;
+ bytes_recv_ += other.bytes_recv_;
+ latency_ms_ += other.latency_ms_;
+ for (const auto& p : other.call_metrics_) {
+ const grpc::string& key = p.first;
+ const CallMetricValue& value = p.second;
+ call_metrics_[key].MergeFrom(value);
+ }
+ }
+
+ int64_t GetNumCallsInProgressDelta() const {
+ return static_cast<int64_t>(start_count_ - ok_count_ - error_count_);
+ }
+
+ grpc::string ToString() const {
+ return "[start_count_=" + grpc::to_string(start_count_) +
+ ", ok_count_=" + grpc::to_string(ok_count_) +
+ ", error_count_=" + grpc::to_string(error_count_) +
+ ", bytes_sent_=" + grpc::to_string(bytes_sent_) +
+ ", bytes_recv_=" + grpc::to_string(bytes_recv_) +
+ ", latency_ms_=" + grpc::to_string(latency_ms_) + "]";
+ }
+
+ bool InsertCallMetric(const grpc::string& metric_name,
+ const CallMetricValue& metric_value) {
+ return call_metrics_.insert({metric_name, metric_value}).second;
+ }
+
+ // Getters.
+ uint64_t start_count() const { return start_count_; }
+ uint64_t ok_count() const { return ok_count_; }
+ uint64_t error_count() const { return error_count_; }
+ double bytes_sent() const { return bytes_sent_; }
+ double bytes_recv() const { return bytes_recv_; }
+ double latency_ms() const { return latency_ms_; }
+ const std::unordered_map<grpc::string, CallMetricValue>& call_metrics()
+ const {
+ return call_metrics_;
+ }
+
+ private:
+ uint64_t start_count_ = 0;
+ uint64_t ok_count_ = 0;
+ uint64_t error_count_ = 0;
+ double bytes_sent_ = 0;
+ double bytes_recv_ = 0;
+ double latency_ms_ = 0;
+ std::unordered_map<grpc::string, CallMetricValue> call_metrics_;
+};
+
+// Stores the data associated with a particular LB ID.
+class PerBalancerStore {
+ public:
+ using LoadRecordMap =
+ std::unordered_map<LoadRecordKey, LoadRecordValue, LoadRecordKey::Hasher>;
+
+ PerBalancerStore(grpc::string lb_id, grpc::string load_key)
+ : lb_id_(std::move(lb_id)), load_key_(std::move(load_key)) {}
+
+ // Merge a load record with the given key and value if the store is not
+ // suspended.
+ void MergeRow(const LoadRecordKey& key, const LoadRecordValue& value);
+
+ // Suspend this store, so that no detailed load data will be recorded.
+ void Suspend();
+ // Resume this store from suspension.
+ void Resume();
+ // Is this store suspended or not?
+ bool IsSuspended() const { return suspended_; }
+
+ bool IsNumCallsInProgressChangedSinceLastReport() const {
+ return num_calls_in_progress_ != last_reported_num_calls_in_progress_;
+ }
+
+ uint64_t GetNumCallsInProgressForReport();
+
+ grpc::string ToString() {
+ return "[PerBalancerStore lb_id_=" + lb_id_ + " load_key_=" + load_key_ +
+ "]";
+ }
+
+ void ClearLoadRecordMap() { load_record_map_.clear(); }
+
+ // Getters.
+ const grpc::string& lb_id() const { return lb_id_; }
+ const grpc::string& load_key() const { return load_key_; }
+ const LoadRecordMap& load_record_map() const { return load_record_map_; }
+
+ private:
+ grpc::string lb_id_;
+ // TODO(juanlishen): Use bytestring protobuf type?
+ grpc::string load_key_;
+ LoadRecordMap load_record_map_;
+ uint64_t num_calls_in_progress_ = 0;
+ uint64_t last_reported_num_calls_in_progress_ = 0;
+ bool suspended_ = false;
+};
+
+// Stores the data associated with a particular host.
+class PerHostStore {
+ public:
+ // When a report stream is created, a PerBalancerStore is created for the
+ // LB ID (guaranteed unique) associated with that stream. If it is the only
+ // active store, adopt all the orphaned stores. If it is the first created
+ // store, adopt the store of kInvalidLbId.
+ void ReportStreamCreated(const grpc::string& lb_id,
+ const grpc::string& load_key);
+
+ // When a report stream is closed, the PerBalancerStores assigned to the
+ // associate LB ID need to be re-assigned to other active balancers,
+ // ideally with the same load key. If there is no active balancer, we have
+ // to suspend those stores and drop the incoming load data until they are
+ // resumed.
+ void ReportStreamClosed(const grpc::string& lb_id);
+
+ // Returns null if not found. Caller doesn't own the returned store.
+ PerBalancerStore* FindPerBalancerStore(const grpc::string& lb_id) const;
+
+ // Returns null if lb_id is not found. The returned pointer points to the
+ // underlying data structure, which is not owned by the caller.
+ const std::set<PerBalancerStore*>* GetAssignedStores(
+ const grpc::string& lb_id) const;
+
+ private:
+ // Creates a PerBalancerStore for the given LB ID, assigns the store to
+ // itself, and records the LB ID to the load key.
+ void SetUpForNewLbId(const grpc::string& lb_id, const grpc::string& load_key);
+
+ void AssignOrphanedStore(PerBalancerStore* orphaned_store,
+ const grpc::string& new_receiver);
+
+ std::unordered_map<grpc::string, std::set<grpc::string>>
+ load_key_to_receiving_lb_ids_;
+
+ // Key: LB ID. The key set includes all the LB IDs that have been
+ // allocated for reporting streams so far.
+ // Value: the unique pointer to the PerBalancerStore of the LB ID.
+ std::unordered_map<grpc::string, std::unique_ptr<PerBalancerStore>>
+ per_balancer_stores_;
+
+ // Key: LB ID. The key set includes the LB IDs of the balancers that are
+ // currently receiving report.
+ // Value: the set of raw pointers to the PerBalancerStores assigned to the LB
+ // ID. Note that the sets in assigned_stores_ form a division of the value set
+ // of per_balancer_stores_.
+ std::unordered_map<grpc::string, std::set<PerBalancerStore*>>
+ assigned_stores_;
+};
+
+// Thread-unsafe two-level bookkeeper of all the load data.
+// Note: We never remove any store objects from this class, as per the
+// current spec. That's because premature removal of the store objects
+// may lead to loss of critical information, e.g., mapping from lb_id to
+// load_key, and the number of in-progress calls. Such loss will cause
+// information inconsistency when the balancer is re-connected. Keeping
+// all the stores should be fine for PerHostStore, since we assume there
+// should only be a few hostnames. But it's a potential problem for
+// PerBalancerStore.
+class LoadDataStore {
+ public:
+ // Returns null if not found. Caller doesn't own the returned store.
+ PerBalancerStore* FindPerBalancerStore(const grpc::string& hostname,
+ const grpc::string& lb_id) const;
+
+ // Returns null if hostname or lb_id is not found. The returned pointer points
+ // to the underlying data structure, which is not owned by the caller.
+ const std::set<PerBalancerStore*>* GetAssignedStores(const string& hostname,
+ const string& lb_id);
+
+ // If a PerBalancerStore can be found by the hostname and LB ID in
+ // LoadRecordKey, the load data will be merged to that store. Otherwise,
+ // only track the number of the in-progress calls for this unknown LB ID.
+ void MergeRow(const grpc::string& hostname, const LoadRecordKey& key,
+ const LoadRecordValue& value);
+
+ // Is the given lb_id a tracked unknown LB ID (i.e., the LB ID was associated
+ // with some received load data but unknown to this load data store)?
+ bool IsTrackedUnknownBalancerId(const grpc::string& lb_id) const {
+ return unknown_balancer_id_trackers_.find(lb_id) !=
+ unknown_balancer_id_trackers_.end();
+ }
+
+ // Wrapper around PerHostStore::ReportStreamCreated.
+ void ReportStreamCreated(const grpc::string& hostname,
+ const grpc::string& lb_id,
+ const grpc::string& load_key);
+
+ // Wrapper around PerHostStore::ReportStreamClosed.
+ void ReportStreamClosed(const grpc::string& hostname,
+ const grpc::string& lb_id);
+
+ private:
+ // Buffered data that was fetched from Census but hasn't been sent to
+ // balancer. We need to keep this data ourselves because Census will
+ // delete the data once it's returned.
+ std::unordered_map<grpc::string, PerHostStore> per_host_stores_;
+
+ // Tracks the number of in-progress calls for each unknown LB ID.
+ std::unordered_map<grpc::string, uint64_t> unknown_balancer_id_trackers_;
+};
+
+} // namespace load_reporter
+} // namespace grpc
+
+#endif // GRPC_SRC_CPP_SERVER_LOAD_REPORTER_LOAD_DATA_STORE_H
diff --git a/src/csharp/Grpc.Core.Testing/TestServerCallContext.cs b/src/csharp/Grpc.Core.Testing/TestServerCallContext.cs
new file mode 100644
index 0000000000..5418417d7e
--- /dev/null
+++ b/src/csharp/Grpc.Core.Testing/TestServerCallContext.cs
@@ -0,0 +1,58 @@
+#region Copyright notice and license
+
+// Copyright 2015 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#endregion
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+
+namespace Grpc.Core.Testing
+{
+ /// <summary>
+ /// Creates test doubles for <c>ServerCallContext</c>.
+ /// </summary>
+ public static class TestServerCallContext
+ {
+ /// <summary>
+ /// Creates a test double for <c>ServerCallContext</c>. Only for testing.
+ /// Note: experimental API that can change or be removed without any prior notice.
+ /// </summary>
+ public static ServerCallContext Create(string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken,
+ string peer, AuthContext authContext, ContextPropagationToken contextPropagationToken,
+ Func<Metadata, Task> writeHeadersFunc, Func<WriteOptions> writeOptionsGetter, Action<WriteOptions> writeOptionsSetter)
+ {
+ return new ServerCallContext(null, method, host, deadline, requestHeaders, cancellationToken,
+ writeHeadersFunc, new WriteOptionsHolder(writeOptionsGetter, writeOptionsSetter),
+ () => peer, () => authContext, () => contextPropagationToken);
+ }
+
+ private class WriteOptionsHolder : IHasWriteOptions
+ {
+ Func<WriteOptions> writeOptionsGetter;
+ Action<WriteOptions> writeOptionsSetter;
+
+ public WriteOptionsHolder(Func<WriteOptions> writeOptionsGetter, Action<WriteOptions> writeOptionsSetter)
+ {
+ this.writeOptionsGetter = writeOptionsGetter;
+ this.writeOptionsSetter = writeOptionsSetter;
+ }
+
+ public WriteOptions WriteOptions { get => writeOptionsGetter(); set => writeOptionsSetter(value); }
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core/ServerCallContext.cs b/src/csharp/Grpc.Core/ServerCallContext.cs
index c63a4c45db..74a7deabea 100644
--- a/src/csharp/Grpc.Core/ServerCallContext.cs
+++ b/src/csharp/Grpc.Core/ServerCallContext.cs
@@ -36,14 +36,25 @@ namespace Grpc.Core
private readonly Metadata requestHeaders;
private readonly CancellationToken cancellationToken;
private readonly Metadata responseTrailers = new Metadata();
+ private readonly Func<Metadata, Task> writeHeadersFunc;
+ private readonly IHasWriteOptions writeOptionsHolder;
+ private readonly Lazy<AuthContext> authContext;
+ private readonly Func<string> testingOnlyPeerGetter;
+ private readonly Func<AuthContext> testingOnlyAuthContextGetter;
+ private readonly Func<ContextPropagationToken> testingOnlyContextPropagationTokenFactory;
private Status status = Status.DefaultSuccess;
- private Func<Metadata, Task> writeHeadersFunc;
- private IHasWriteOptions writeOptionsHolder;
- private Lazy<AuthContext> authContext;
internal ServerCallContext(CallSafeHandle callHandle, string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken,
Func<Metadata, Task> writeHeadersFunc, IHasWriteOptions writeOptionsHolder)
+ : this(callHandle, method, host, deadline, requestHeaders, cancellationToken, writeHeadersFunc, writeOptionsHolder, null, null, null)
+ {
+ }
+
+ // Additional constructor params should be used for testing only
+ internal ServerCallContext(CallSafeHandle callHandle, string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken,
+ Func<Metadata, Task> writeHeadersFunc, IHasWriteOptions writeOptionsHolder,
+ Func<string> testingOnlyPeerGetter, Func<AuthContext> testingOnlyAuthContextGetter, Func<ContextPropagationToken> testingOnlyContextPropagationTokenFactory)
{
this.callHandle = callHandle;
this.method = method;
@@ -54,6 +65,9 @@ namespace Grpc.Core
this.writeHeadersFunc = writeHeadersFunc;
this.writeOptionsHolder = writeOptionsHolder;
this.authContext = new Lazy<AuthContext>(GetAuthContextEager);
+ this.testingOnlyPeerGetter = testingOnlyPeerGetter;
+ this.testingOnlyAuthContextGetter = testingOnlyAuthContextGetter;
+ this.testingOnlyContextPropagationTokenFactory = testingOnlyContextPropagationTokenFactory;
}
/// <summary>
@@ -73,6 +87,10 @@ namespace Grpc.Core
/// </summary>
public ContextPropagationToken CreatePropagationToken(ContextPropagationOptions options = null)
{
+ if (testingOnlyContextPropagationTokenFactory != null)
+ {
+ return testingOnlyContextPropagationTokenFactory();
+ }
return new ContextPropagationToken(callHandle, deadline, cancellationToken, options);
}
@@ -99,6 +117,10 @@ namespace Grpc.Core
{
get
{
+ if (testingOnlyPeerGetter != null)
+ {
+ return testingOnlyPeerGetter();
+ }
// Getting the peer lazily is fine as the native call is guaranteed
// not to be disposed before user-supplied server side handler returns.
// Most users won't need to read this field anyway.
@@ -182,6 +204,10 @@ namespace Grpc.Core
{
get
{
+ if (testingOnlyAuthContextGetter != null)
+ {
+ return testingOnlyAuthContextGetter();
+ }
return authContext.Value;
}
}
@@ -198,7 +224,7 @@ namespace Grpc.Core
/// <summary>
/// Allows sharing write options between ServerCallContext and other objects.
/// </summary>
- public interface IHasWriteOptions
+ internal interface IHasWriteOptions
{
/// <summary>
/// Gets or sets the write options.
diff --git a/src/csharp/Grpc.Core/Version.csproj.include b/src/csharp/Grpc.Core/Version.csproj.include
index 6e28c11df2..f5d63b77f0 100755
--- a/src/csharp/Grpc.Core/Version.csproj.include
+++ b/src/csharp/Grpc.Core/Version.csproj.include
@@ -1,7 +1,7 @@
<!-- This file is generated -->
<Project>
<PropertyGroup>
- <GrpcCsharpVersion>1.12.0-dev</GrpcCsharpVersion>
+ <GrpcCsharpVersion>1.13.0-dev</GrpcCsharpVersion>
<GoogleProtobufVersion>3.5.1</GoogleProtobufVersion>
</PropertyGroup>
</Project>
diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs
index 06a0396c34..87edddae3f 100644
--- a/src/csharp/Grpc.Core/VersionInfo.cs
+++ b/src/csharp/Grpc.Core/VersionInfo.cs
@@ -33,11 +33,11 @@ namespace Grpc.Core
/// <summary>
/// Current <c>AssemblyFileVersion</c> of gRPC C# assemblies
/// </summary>
- public const string CurrentAssemblyFileVersion = "1.12.0.0";
+ public const string CurrentAssemblyFileVersion = "1.13.0.0";
/// <summary>
/// Current version of gRPC C#
/// </summary>
- public const string CurrentVersion = "1.12.0-dev";
+ public const string CurrentVersion = "1.13.0-dev";
}
}
diff --git a/src/csharp/Grpc.Examples/Math.cs b/src/csharp/Grpc.Examples/Math.cs
index e5b76f8305..4c3879f577 100644
--- a/src/csharp/Grpc.Examples/Math.cs
+++ b/src/csharp/Grpc.Examples/Math.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
-// source: math/math.proto
+// <auto-generated>
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: math/math.proto
+// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
@@ -47,6 +49,7 @@ namespace Math {
#region Messages
public sealed partial class DivArgs : pb::IMessage<DivArgs> {
private static readonly pb::MessageParser<DivArgs> _parser = new pb::MessageParser<DivArgs>(() => new DivArgs());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<DivArgs> Parser { get { return _parser; } }
@@ -71,6 +74,7 @@ namespace Math {
public DivArgs(DivArgs other) : this() {
dividend_ = other.dividend_;
divisor_ = other.divisor_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -115,7 +119,7 @@ namespace Math {
}
if (Dividend != other.Dividend) return false;
if (Divisor != other.Divisor) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -123,6 +127,9 @@ namespace Math {
int hash = 1;
if (Dividend != 0L) hash ^= Dividend.GetHashCode();
if (Divisor != 0L) hash ^= Divisor.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -141,6 +148,9 @@ namespace Math {
output.WriteRawTag(16);
output.WriteInt64(Divisor);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -152,6 +162,9 @@ namespace Math {
if (Divisor != 0L) {
size += 1 + pb::CodedOutputStream.ComputeInt64Size(Divisor);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -166,6 +179,7 @@ namespace Math {
if (other.Divisor != 0L) {
Divisor = other.Divisor;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -174,7 +188,7 @@ namespace Math {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
Dividend = input.ReadInt64();
@@ -192,6 +206,7 @@ namespace Math {
public sealed partial class DivReply : pb::IMessage<DivReply> {
private static readonly pb::MessageParser<DivReply> _parser = new pb::MessageParser<DivReply>(() => new DivReply());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<DivReply> Parser { get { return _parser; } }
@@ -216,6 +231,7 @@ namespace Math {
public DivReply(DivReply other) : this() {
quotient_ = other.quotient_;
remainder_ = other.remainder_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -260,7 +276,7 @@ namespace Math {
}
if (Quotient != other.Quotient) return false;
if (Remainder != other.Remainder) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -268,6 +284,9 @@ namespace Math {
int hash = 1;
if (Quotient != 0L) hash ^= Quotient.GetHashCode();
if (Remainder != 0L) hash ^= Remainder.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -286,6 +305,9 @@ namespace Math {
output.WriteRawTag(16);
output.WriteInt64(Remainder);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -297,6 +319,9 @@ namespace Math {
if (Remainder != 0L) {
size += 1 + pb::CodedOutputStream.ComputeInt64Size(Remainder);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -311,6 +336,7 @@ namespace Math {
if (other.Remainder != 0L) {
Remainder = other.Remainder;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -319,7 +345,7 @@ namespace Math {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
Quotient = input.ReadInt64();
@@ -337,6 +363,7 @@ namespace Math {
public sealed partial class FibArgs : pb::IMessage<FibArgs> {
private static readonly pb::MessageParser<FibArgs> _parser = new pb::MessageParser<FibArgs>(() => new FibArgs());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<FibArgs> Parser { get { return _parser; } }
@@ -360,6 +387,7 @@ namespace Math {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public FibArgs(FibArgs other) : this() {
limit_ = other.limit_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -392,13 +420,16 @@ namespace Math {
return true;
}
if (Limit != other.Limit) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Limit != 0L) hash ^= Limit.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -413,6 +444,9 @@ namespace Math {
output.WriteRawTag(8);
output.WriteInt64(Limit);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -421,6 +455,9 @@ namespace Math {
if (Limit != 0L) {
size += 1 + pb::CodedOutputStream.ComputeInt64Size(Limit);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -432,6 +469,7 @@ namespace Math {
if (other.Limit != 0L) {
Limit = other.Limit;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -440,7 +478,7 @@ namespace Math {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
Limit = input.ReadInt64();
@@ -454,6 +492,7 @@ namespace Math {
public sealed partial class Num : pb::IMessage<Num> {
private static readonly pb::MessageParser<Num> _parser = new pb::MessageParser<Num>(() => new Num());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Num> Parser { get { return _parser; } }
@@ -477,6 +516,7 @@ namespace Math {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Num(Num other) : this() {
num_ = other.num_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -509,13 +549,16 @@ namespace Math {
return true;
}
if (Num_ != other.Num_) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Num_ != 0L) hash ^= Num_.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -530,6 +573,9 @@ namespace Math {
output.WriteRawTag(8);
output.WriteInt64(Num_);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -538,6 +584,9 @@ namespace Math {
if (Num_ != 0L) {
size += 1 + pb::CodedOutputStream.ComputeInt64Size(Num_);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -549,6 +598,7 @@ namespace Math {
if (other.Num_ != 0L) {
Num_ = other.Num_;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -557,7 +607,7 @@ namespace Math {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
Num_ = input.ReadInt64();
@@ -571,6 +621,7 @@ namespace Math {
public sealed partial class FibReply : pb::IMessage<FibReply> {
private static readonly pb::MessageParser<FibReply> _parser = new pb::MessageParser<FibReply>(() => new FibReply());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<FibReply> Parser { get { return _parser; } }
@@ -594,6 +645,7 @@ namespace Math {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public FibReply(FibReply other) : this() {
count_ = other.count_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -626,13 +678,16 @@ namespace Math {
return true;
}
if (Count != other.Count) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Count != 0L) hash ^= Count.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -647,6 +702,9 @@ namespace Math {
output.WriteRawTag(8);
output.WriteInt64(Count);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -655,6 +713,9 @@ namespace Math {
if (Count != 0L) {
size += 1 + pb::CodedOutputStream.ComputeInt64Size(Count);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -666,6 +727,7 @@ namespace Math {
if (other.Count != 0L) {
Count = other.Count;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -674,7 +736,7 @@ namespace Math {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
Count = input.ReadInt64();
diff --git a/src/csharp/Grpc.HealthCheck/Health.cs b/src/csharp/Grpc.HealthCheck/Health.cs
index b9880d9636..a90f261d28 100644
--- a/src/csharp/Grpc.HealthCheck/Health.cs
+++ b/src/csharp/Grpc.HealthCheck/Health.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
-// source: grpc/health/v1/health.proto
+// <auto-generated>
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: grpc/health/v1/health.proto
+// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
@@ -29,7 +31,9 @@ namespace Grpc.Health.V1 {
"ZXJ2aW5nU3RhdHVzEgsKB1VOS05PV04QABILCgdTRVJWSU5HEAESDwoLTk9U",
"X1NFUlZJTkcQAjJaCgZIZWFsdGgSUAoFQ2hlY2sSIi5ncnBjLmhlYWx0aC52",
"MS5IZWFsdGhDaGVja1JlcXVlc3QaIy5ncnBjLmhlYWx0aC52MS5IZWFsdGhD",
- "aGVja1Jlc3BvbnNlQhGqAg5HcnBjLkhlYWx0aC5WMWIGcHJvdG8z"));
+ "aGVja1Jlc3BvbnNlQmEKEWlvLmdycGMuaGVhbHRoLnYxQgtIZWFsdGhQcm90",
+ "b1ABWixnb29nbGUuZ29sYW5nLm9yZy9ncnBjL2hlYWx0aC9ncnBjX2hlYWx0",
+ "aF92MaoCDkdycGMuSGVhbHRoLlYxYgZwcm90bzM="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
@@ -43,6 +47,7 @@ namespace Grpc.Health.V1 {
#region Messages
public sealed partial class HealthCheckRequest : pb::IMessage<HealthCheckRequest> {
private static readonly pb::MessageParser<HealthCheckRequest> _parser = new pb::MessageParser<HealthCheckRequest>(() => new HealthCheckRequest());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<HealthCheckRequest> Parser { get { return _parser; } }
@@ -66,6 +71,7 @@ namespace Grpc.Health.V1 {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public HealthCheckRequest(HealthCheckRequest other) : this() {
service_ = other.service_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -98,13 +104,16 @@ namespace Grpc.Health.V1 {
return true;
}
if (Service != other.Service) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Service.Length != 0) hash ^= Service.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -119,6 +128,9 @@ namespace Grpc.Health.V1 {
output.WriteRawTag(10);
output.WriteString(Service);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -127,6 +139,9 @@ namespace Grpc.Health.V1 {
if (Service.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Service);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -138,6 +153,7 @@ namespace Grpc.Health.V1 {
if (other.Service.Length != 0) {
Service = other.Service;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -146,7 +162,7 @@ namespace Grpc.Health.V1 {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Service = input.ReadString();
@@ -160,6 +176,7 @@ namespace Grpc.Health.V1 {
public sealed partial class HealthCheckResponse : pb::IMessage<HealthCheckResponse> {
private static readonly pb::MessageParser<HealthCheckResponse> _parser = new pb::MessageParser<HealthCheckResponse>(() => new HealthCheckResponse());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<HealthCheckResponse> Parser { get { return _parser; } }
@@ -183,6 +200,7 @@ namespace Grpc.Health.V1 {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public HealthCheckResponse(HealthCheckResponse other) : this() {
status_ = other.status_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -215,13 +233,16 @@ namespace Grpc.Health.V1 {
return true;
}
if (Status != other.Status) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Status != 0) hash ^= Status.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -236,6 +257,9 @@ namespace Grpc.Health.V1 {
output.WriteRawTag(8);
output.WriteEnum((int) Status);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -244,6 +268,9 @@ namespace Grpc.Health.V1 {
if (Status != 0) {
size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Status);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -255,6 +282,7 @@ namespace Grpc.Health.V1 {
if (other.Status != 0) {
Status = other.Status;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -263,7 +291,7 @@ namespace Grpc.Health.V1 {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
status_ = (global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus) input.ReadEnum();
diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
index 1d80bcd59e..a26f483981 100644
--- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
+++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
@@ -3,7 +3,7 @@
// source: grpc/health/v1/health.proto
// </auto-generated>
// Original file comments:
-// Copyright 2015 gRPC authors.
+// Copyright 2015 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -17,6 +17,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
+// The canonical version of this proto can be found at
+// https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto
+//
#pragma warning disable 1591
#region Designer generated code
diff --git a/src/csharp/Grpc.IntegrationTesting/BenchmarkService.cs b/src/csharp/Grpc.IntegrationTesting/BenchmarkService.cs
index 11d34c6341..bc8c10352a 100644
--- a/src/csharp/Grpc.IntegrationTesting/BenchmarkService.cs
+++ b/src/csharp/Grpc.IntegrationTesting/BenchmarkService.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
-// source: src/proto/grpc/testing/benchmark_service.proto
+// <auto-generated>
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: src/proto/grpc/testing/benchmark_service.proto
+// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
diff --git a/src/csharp/Grpc.IntegrationTesting/Control.cs b/src/csharp/Grpc.IntegrationTesting/Control.cs
index 8795728906..f3284a5390 100644
--- a/src/csharp/Grpc.IntegrationTesting/Control.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Control.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
-// source: src/proto/grpc/testing/control.proto
+// <auto-generated>
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: src/proto/grpc/testing/control.proto
+// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
@@ -167,6 +169,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class PoissonParams : pb::IMessage<PoissonParams> {
private static readonly pb::MessageParser<PoissonParams> _parser = new pb::MessageParser<PoissonParams>(() => new PoissonParams());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<PoissonParams> Parser { get { return _parser; } }
@@ -190,6 +193,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public PoissonParams(PoissonParams other) : this() {
offeredLoad_ = other.offeredLoad_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -224,14 +228,17 @@ namespace Grpc.Testing {
if (ReferenceEquals(other, this)) {
return true;
}
- if (OfferedLoad != other.OfferedLoad) return false;
- return true;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(OfferedLoad, other.OfferedLoad)) return false;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
- if (OfferedLoad != 0D) hash ^= OfferedLoad.GetHashCode();
+ if (OfferedLoad != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(OfferedLoad);
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -246,6 +253,9 @@ namespace Grpc.Testing {
output.WriteRawTag(9);
output.WriteDouble(OfferedLoad);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -254,6 +264,9 @@ namespace Grpc.Testing {
if (OfferedLoad != 0D) {
size += 1 + 8;
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -265,6 +278,7 @@ namespace Grpc.Testing {
if (other.OfferedLoad != 0D) {
OfferedLoad = other.OfferedLoad;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -273,7 +287,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 9: {
OfferedLoad = input.ReadDouble();
@@ -291,6 +305,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class ClosedLoopParams : pb::IMessage<ClosedLoopParams> {
private static readonly pb::MessageParser<ClosedLoopParams> _parser = new pb::MessageParser<ClosedLoopParams>(() => new ClosedLoopParams());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ClosedLoopParams> Parser { get { return _parser; } }
@@ -313,6 +328,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ClosedLoopParams(ClosedLoopParams other) : this() {
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -333,12 +349,15 @@ namespace Grpc.Testing {
if (ReferenceEquals(other, this)) {
return true;
}
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -349,11 +368,17 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -362,6 +387,7 @@ namespace Grpc.Testing {
if (other == null) {
return;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -370,7 +396,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
}
}
@@ -380,6 +406,7 @@ namespace Grpc.Testing {
public sealed partial class LoadParams : pb::IMessage<LoadParams> {
private static readonly pb::MessageParser<LoadParams> _parser = new pb::MessageParser<LoadParams>(() => new LoadParams());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<LoadParams> Parser { get { return _parser; } }
@@ -411,6 +438,7 @@ namespace Grpc.Testing {
break;
}
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -475,7 +503,7 @@ namespace Grpc.Testing {
if (!object.Equals(ClosedLoop, other.ClosedLoop)) return false;
if (!object.Equals(Poisson, other.Poisson)) return false;
if (LoadCase != other.LoadCase) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -484,6 +512,9 @@ namespace Grpc.Testing {
if (loadCase_ == LoadOneofCase.ClosedLoop) hash ^= ClosedLoop.GetHashCode();
if (loadCase_ == LoadOneofCase.Poisson) hash ^= Poisson.GetHashCode();
hash ^= (int) loadCase_;
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -502,6 +533,9 @@ namespace Grpc.Testing {
output.WriteRawTag(18);
output.WriteMessage(Poisson);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -513,6 +547,9 @@ namespace Grpc.Testing {
if (loadCase_ == LoadOneofCase.Poisson) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Poisson);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -536,6 +573,7 @@ namespace Grpc.Testing {
break;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -544,7 +582,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
global::Grpc.Testing.ClosedLoopParams subBuilder = new global::Grpc.Testing.ClosedLoopParams();
@@ -575,6 +613,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class SecurityParams : pb::IMessage<SecurityParams> {
private static readonly pb::MessageParser<SecurityParams> _parser = new pb::MessageParser<SecurityParams>(() => new SecurityParams());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<SecurityParams> Parser { get { return _parser; } }
@@ -600,6 +639,7 @@ namespace Grpc.Testing {
useTestCa_ = other.useTestCa_;
serverHostOverride_ = other.serverHostOverride_;
credType_ = other.credType_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -656,7 +696,7 @@ namespace Grpc.Testing {
if (UseTestCa != other.UseTestCa) return false;
if (ServerHostOverride != other.ServerHostOverride) return false;
if (CredType != other.CredType) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -665,6 +705,9 @@ namespace Grpc.Testing {
if (UseTestCa != false) hash ^= UseTestCa.GetHashCode();
if (ServerHostOverride.Length != 0) hash ^= ServerHostOverride.GetHashCode();
if (CredType.Length != 0) hash ^= CredType.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -687,6 +730,9 @@ namespace Grpc.Testing {
output.WriteRawTag(26);
output.WriteString(CredType);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -701,6 +747,9 @@ namespace Grpc.Testing {
if (CredType.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(CredType);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -718,6 +767,7 @@ namespace Grpc.Testing {
if (other.CredType.Length != 0) {
CredType = other.CredType;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -726,7 +776,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
UseTestCa = input.ReadBool();
@@ -748,6 +798,7 @@ namespace Grpc.Testing {
public sealed partial class ChannelArg : pb::IMessage<ChannelArg> {
private static readonly pb::MessageParser<ChannelArg> _parser = new pb::MessageParser<ChannelArg>(() => new ChannelArg());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ChannelArg> Parser { get { return _parser; } }
@@ -780,6 +831,7 @@ namespace Grpc.Testing {
break;
}
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -856,7 +908,7 @@ namespace Grpc.Testing {
if (StrValue != other.StrValue) return false;
if (IntValue != other.IntValue) return false;
if (ValueCase != other.ValueCase) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -866,6 +918,9 @@ namespace Grpc.Testing {
if (valueCase_ == ValueOneofCase.StrValue) hash ^= StrValue.GetHashCode();
if (valueCase_ == ValueOneofCase.IntValue) hash ^= IntValue.GetHashCode();
hash ^= (int) valueCase_;
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -888,6 +943,9 @@ namespace Grpc.Testing {
output.WriteRawTag(24);
output.WriteInt32(IntValue);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -902,6 +960,9 @@ namespace Grpc.Testing {
if (valueCase_ == ValueOneofCase.IntValue) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntValue);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -922,6 +983,7 @@ namespace Grpc.Testing {
break;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -930,7 +992,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Name = input.ReadString();
@@ -952,6 +1014,7 @@ namespace Grpc.Testing {
public sealed partial class ClientConfig : pb::IMessage<ClientConfig> {
private static readonly pb::MessageParser<ClientConfig> _parser = new pb::MessageParser<ClientConfig>(() => new ClientConfig());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ClientConfig> Parser { get { return _parser; } }
@@ -991,6 +1054,7 @@ namespace Grpc.Testing {
threadsPerCq_ = other.threadsPerCq_;
messagesPerStream_ = other.messagesPerStream_;
useCoalesceApi_ = other.useCoalesceApi_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1244,7 +1308,7 @@ namespace Grpc.Testing {
if (ThreadsPerCq != other.ThreadsPerCq) return false;
if (MessagesPerStream != other.MessagesPerStream) return false;
if (UseCoalesceApi != other.UseCoalesceApi) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1267,6 +1331,9 @@ namespace Grpc.Testing {
if (ThreadsPerCq != 0) hash ^= ThreadsPerCq.GetHashCode();
if (MessagesPerStream != 0) hash ^= MessagesPerStream.GetHashCode();
if (UseCoalesceApi != false) hash ^= UseCoalesceApi.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -1336,6 +1403,9 @@ namespace Grpc.Testing {
output.WriteRawTag(152, 1);
output.WriteBool(UseCoalesceApi);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1386,6 +1456,9 @@ namespace Grpc.Testing {
if (UseCoalesceApi != false) {
size += 2 + 1;
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1451,6 +1524,7 @@ namespace Grpc.Testing {
if (other.UseCoalesceApi != false) {
UseCoalesceApi = other.UseCoalesceApi;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1459,7 +1533,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
serverTargets_.AddEntriesFrom(input, _repeated_serverTargets_codec);
@@ -1550,6 +1624,7 @@ namespace Grpc.Testing {
public sealed partial class ClientStatus : pb::IMessage<ClientStatus> {
private static readonly pb::MessageParser<ClientStatus> _parser = new pb::MessageParser<ClientStatus>(() => new ClientStatus());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ClientStatus> Parser { get { return _parser; } }
@@ -1573,6 +1648,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ClientStatus(ClientStatus other) : this() {
Stats = other.stats_ != null ? other.Stats.Clone() : null;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1605,13 +1681,16 @@ namespace Grpc.Testing {
return true;
}
if (!object.Equals(Stats, other.Stats)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (stats_ != null) hash ^= Stats.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -1626,6 +1705,9 @@ namespace Grpc.Testing {
output.WriteRawTag(10);
output.WriteMessage(Stats);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1634,6 +1716,9 @@ namespace Grpc.Testing {
if (stats_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stats);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1648,6 +1733,7 @@ namespace Grpc.Testing {
}
Stats.MergeFrom(other.Stats);
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1656,7 +1742,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
if (stats_ == null) {
@@ -1676,6 +1762,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class Mark : pb::IMessage<Mark> {
private static readonly pb::MessageParser<Mark> _parser = new pb::MessageParser<Mark>(() => new Mark());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Mark> Parser { get { return _parser; } }
@@ -1699,6 +1786,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Mark(Mark other) : this() {
reset_ = other.reset_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1734,13 +1822,16 @@ namespace Grpc.Testing {
return true;
}
if (Reset != other.Reset) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Reset != false) hash ^= Reset.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -1755,6 +1846,9 @@ namespace Grpc.Testing {
output.WriteRawTag(8);
output.WriteBool(Reset);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1763,6 +1857,9 @@ namespace Grpc.Testing {
if (Reset != false) {
size += 1 + 1;
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1774,6 +1871,7 @@ namespace Grpc.Testing {
if (other.Reset != false) {
Reset = other.Reset;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1782,7 +1880,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
Reset = input.ReadBool();
@@ -1796,6 +1894,7 @@ namespace Grpc.Testing {
public sealed partial class ClientArgs : pb::IMessage<ClientArgs> {
private static readonly pb::MessageParser<ClientArgs> _parser = new pb::MessageParser<ClientArgs>(() => new ClientArgs());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ClientArgs> Parser { get { return _parser; } }
@@ -1827,6 +1926,7 @@ namespace Grpc.Testing {
break;
}
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1891,7 +1991,7 @@ namespace Grpc.Testing {
if (!object.Equals(Setup, other.Setup)) return false;
if (!object.Equals(Mark, other.Mark)) return false;
if (ArgtypeCase != other.ArgtypeCase) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1900,6 +2000,9 @@ namespace Grpc.Testing {
if (argtypeCase_ == ArgtypeOneofCase.Setup) hash ^= Setup.GetHashCode();
if (argtypeCase_ == ArgtypeOneofCase.Mark) hash ^= Mark.GetHashCode();
hash ^= (int) argtypeCase_;
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -1918,6 +2021,9 @@ namespace Grpc.Testing {
output.WriteRawTag(18);
output.WriteMessage(Mark);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1929,6 +2035,9 @@ namespace Grpc.Testing {
if (argtypeCase_ == ArgtypeOneofCase.Mark) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Mark);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1952,6 +2061,7 @@ namespace Grpc.Testing {
break;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1960,7 +2070,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
global::Grpc.Testing.ClientConfig subBuilder = new global::Grpc.Testing.ClientConfig();
@@ -1988,6 +2098,7 @@ namespace Grpc.Testing {
public sealed partial class ServerConfig : pb::IMessage<ServerConfig> {
private static readonly pb::MessageParser<ServerConfig> _parser = new pb::MessageParser<ServerConfig>(() => new ServerConfig());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ServerConfig> Parser { get { return _parser; } }
@@ -2021,6 +2132,7 @@ namespace Grpc.Testing {
threadsPerCq_ = other.threadsPerCq_;
resourceQuotaSize_ = other.resourceQuotaSize_;
channelArgs_ = other.channelArgs_.Clone();
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2198,7 +2310,7 @@ namespace Grpc.Testing {
if (ThreadsPerCq != other.ThreadsPerCq) return false;
if (ResourceQuotaSize != other.ResourceQuotaSize) return false;
if(!channelArgs_.Equals(other.channelArgs_)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2215,6 +2327,9 @@ namespace Grpc.Testing {
if (ThreadsPerCq != 0) hash ^= ThreadsPerCq.GetHashCode();
if (ResourceQuotaSize != 0) hash ^= ResourceQuotaSize.GetHashCode();
hash ^= channelArgs_.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -2263,6 +2378,9 @@ namespace Grpc.Testing {
output.WriteInt32(ResourceQuotaSize);
}
channelArgs_.WriteTo(output, _repeated_channelArgs_codec);
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2297,6 +2415,9 @@ namespace Grpc.Testing {
size += 2 + pb::CodedOutputStream.ComputeInt32Size(ResourceQuotaSize);
}
size += channelArgs_.CalculateSize(_repeated_channelArgs_codec);
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -2340,6 +2461,7 @@ namespace Grpc.Testing {
ResourceQuotaSize = other.ResourceQuotaSize;
}
channelArgs_.Add(other.channelArgs_);
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2348,7 +2470,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
serverType_ = (global::Grpc.Testing.ServerType) input.ReadEnum();
@@ -2409,6 +2531,7 @@ namespace Grpc.Testing {
public sealed partial class ServerArgs : pb::IMessage<ServerArgs> {
private static readonly pb::MessageParser<ServerArgs> _parser = new pb::MessageParser<ServerArgs>(() => new ServerArgs());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ServerArgs> Parser { get { return _parser; } }
@@ -2440,6 +2563,7 @@ namespace Grpc.Testing {
break;
}
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2504,7 +2628,7 @@ namespace Grpc.Testing {
if (!object.Equals(Setup, other.Setup)) return false;
if (!object.Equals(Mark, other.Mark)) return false;
if (ArgtypeCase != other.ArgtypeCase) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2513,6 +2637,9 @@ namespace Grpc.Testing {
if (argtypeCase_ == ArgtypeOneofCase.Setup) hash ^= Setup.GetHashCode();
if (argtypeCase_ == ArgtypeOneofCase.Mark) hash ^= Mark.GetHashCode();
hash ^= (int) argtypeCase_;
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -2531,6 +2658,9 @@ namespace Grpc.Testing {
output.WriteRawTag(18);
output.WriteMessage(Mark);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2542,6 +2672,9 @@ namespace Grpc.Testing {
if (argtypeCase_ == ArgtypeOneofCase.Mark) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Mark);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -2565,6 +2698,7 @@ namespace Grpc.Testing {
break;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2573,7 +2707,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
global::Grpc.Testing.ServerConfig subBuilder = new global::Grpc.Testing.ServerConfig();
@@ -2601,6 +2735,7 @@ namespace Grpc.Testing {
public sealed partial class ServerStatus : pb::IMessage<ServerStatus> {
private static readonly pb::MessageParser<ServerStatus> _parser = new pb::MessageParser<ServerStatus>(() => new ServerStatus());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ServerStatus> Parser { get { return _parser; } }
@@ -2626,6 +2761,7 @@ namespace Grpc.Testing {
Stats = other.stats_ != null ? other.Stats.Clone() : null;
port_ = other.port_;
cores_ = other.cores_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2688,7 +2824,7 @@ namespace Grpc.Testing {
if (!object.Equals(Stats, other.Stats)) return false;
if (Port != other.Port) return false;
if (Cores != other.Cores) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2697,6 +2833,9 @@ namespace Grpc.Testing {
if (stats_ != null) hash ^= Stats.GetHashCode();
if (Port != 0) hash ^= Port.GetHashCode();
if (Cores != 0) hash ^= Cores.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -2719,6 +2858,9 @@ namespace Grpc.Testing {
output.WriteRawTag(24);
output.WriteInt32(Cores);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2733,6 +2875,9 @@ namespace Grpc.Testing {
if (Cores != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(Cores);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -2753,6 +2898,7 @@ namespace Grpc.Testing {
if (other.Cores != 0) {
Cores = other.Cores;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2761,7 +2907,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
if (stats_ == null) {
@@ -2786,6 +2932,7 @@ namespace Grpc.Testing {
public sealed partial class CoreRequest : pb::IMessage<CoreRequest> {
private static readonly pb::MessageParser<CoreRequest> _parser = new pb::MessageParser<CoreRequest>(() => new CoreRequest());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<CoreRequest> Parser { get { return _parser; } }
@@ -2808,6 +2955,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public CoreRequest(CoreRequest other) : this() {
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2828,12 +2976,15 @@ namespace Grpc.Testing {
if (ReferenceEquals(other, this)) {
return true;
}
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -2844,11 +2995,17 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -2857,6 +3014,7 @@ namespace Grpc.Testing {
if (other == null) {
return;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2865,7 +3023,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
}
}
@@ -2875,6 +3033,7 @@ namespace Grpc.Testing {
public sealed partial class CoreResponse : pb::IMessage<CoreResponse> {
private static readonly pb::MessageParser<CoreResponse> _parser = new pb::MessageParser<CoreResponse>(() => new CoreResponse());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<CoreResponse> Parser { get { return _parser; } }
@@ -2898,6 +3057,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public CoreResponse(CoreResponse other) : this() {
cores_ = other.cores_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2933,13 +3093,16 @@ namespace Grpc.Testing {
return true;
}
if (Cores != other.Cores) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Cores != 0) hash ^= Cores.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -2954,6 +3117,9 @@ namespace Grpc.Testing {
output.WriteRawTag(8);
output.WriteInt32(Cores);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2962,6 +3128,9 @@ namespace Grpc.Testing {
if (Cores != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(Cores);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -2973,6 +3142,7 @@ namespace Grpc.Testing {
if (other.Cores != 0) {
Cores = other.Cores;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2981,7 +3151,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
Cores = input.ReadInt32();
@@ -2995,6 +3165,7 @@ namespace Grpc.Testing {
public sealed partial class Void : pb::IMessage<Void> {
private static readonly pb::MessageParser<Void> _parser = new pb::MessageParser<Void>(() => new Void());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Void> Parser { get { return _parser; } }
@@ -3017,6 +3188,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Void(Void other) : this() {
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3037,12 +3209,15 @@ namespace Grpc.Testing {
if (ReferenceEquals(other, this)) {
return true;
}
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -3053,11 +3228,17 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -3066,6 +3247,7 @@ namespace Grpc.Testing {
if (other == null) {
return;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3074,7 +3256,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
}
}
@@ -3087,6 +3269,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class Scenario : pb::IMessage<Scenario> {
private static readonly pb::MessageParser<Scenario> _parser = new pb::MessageParser<Scenario>(() => new Scenario());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Scenario> Parser { get { return _parser; } }
@@ -3117,6 +3300,7 @@ namespace Grpc.Testing {
warmupSeconds_ = other.warmupSeconds_;
benchmarkSeconds_ = other.benchmarkSeconds_;
spawnLocalWorkerCount_ = other.spawnLocalWorkerCount_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3257,7 +3441,7 @@ namespace Grpc.Testing {
if (WarmupSeconds != other.WarmupSeconds) return false;
if (BenchmarkSeconds != other.BenchmarkSeconds) return false;
if (SpawnLocalWorkerCount != other.SpawnLocalWorkerCount) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3271,6 +3455,9 @@ namespace Grpc.Testing {
if (WarmupSeconds != 0) hash ^= WarmupSeconds.GetHashCode();
if (BenchmarkSeconds != 0) hash ^= BenchmarkSeconds.GetHashCode();
if (SpawnLocalWorkerCount != 0) hash ^= SpawnLocalWorkerCount.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -3313,6 +3500,9 @@ namespace Grpc.Testing {
output.WriteRawTag(64);
output.WriteInt32(SpawnLocalWorkerCount);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3342,6 +3532,9 @@ namespace Grpc.Testing {
if (SpawnLocalWorkerCount != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(SpawnLocalWorkerCount);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -3380,6 +3573,7 @@ namespace Grpc.Testing {
if (other.SpawnLocalWorkerCount != 0) {
SpawnLocalWorkerCount = other.SpawnLocalWorkerCount;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3388,7 +3582,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Name = input.ReadString();
@@ -3439,6 +3633,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class Scenarios : pb::IMessage<Scenarios> {
private static readonly pb::MessageParser<Scenarios> _parser = new pb::MessageParser<Scenarios>(() => new Scenarios());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Scenarios> Parser { get { return _parser; } }
@@ -3462,6 +3657,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Scenarios(Scenarios other) : this() {
scenarios_ = other.scenarios_.Clone();
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3493,13 +3689,16 @@ namespace Grpc.Testing {
return true;
}
if(!scenarios_.Equals(other.scenarios_)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
hash ^= scenarios_.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -3511,12 +3710,18 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
scenarios_.WriteTo(output, _repeated_scenarios_codec);
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
size += scenarios_.CalculateSize(_repeated_scenarios_codec);
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -3526,6 +3731,7 @@ namespace Grpc.Testing {
return;
}
scenarios_.Add(other.scenarios_);
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3534,7 +3740,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
scenarios_.AddEntriesFrom(input, _repeated_scenarios_codec);
@@ -3552,6 +3758,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class ScenarioResultSummary : pb::IMessage<ScenarioResultSummary> {
private static readonly pb::MessageParser<ScenarioResultSummary> _parser = new pb::MessageParser<ScenarioResultSummary>(() => new ScenarioResultSummary());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ScenarioResultSummary> Parser { get { return _parser; } }
@@ -3592,6 +3799,7 @@ namespace Grpc.Testing {
serverPollsPerRequest_ = other.serverPollsPerRequest_;
serverQueriesPerCpuSec_ = other.serverQueriesPerCpuSec_;
clientQueriesPerCpuSec_ = other.clientQueriesPerCpuSec_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3843,48 +4051,51 @@ namespace Grpc.Testing {
if (ReferenceEquals(other, this)) {
return true;
}
- if (Qps != other.Qps) return false;
- if (QpsPerServerCore != other.QpsPerServerCore) return false;
- if (ServerSystemTime != other.ServerSystemTime) return false;
- if (ServerUserTime != other.ServerUserTime) return false;
- if (ClientSystemTime != other.ClientSystemTime) return false;
- if (ClientUserTime != other.ClientUserTime) return false;
- if (Latency50 != other.Latency50) return false;
- if (Latency90 != other.Latency90) return false;
- if (Latency95 != other.Latency95) return false;
- if (Latency99 != other.Latency99) return false;
- if (Latency999 != other.Latency999) return false;
- if (ServerCpuUsage != other.ServerCpuUsage) return false;
- if (SuccessfulRequestsPerSecond != other.SuccessfulRequestsPerSecond) return false;
- if (FailedRequestsPerSecond != other.FailedRequestsPerSecond) return false;
- if (ClientPollsPerRequest != other.ClientPollsPerRequest) return false;
- if (ServerPollsPerRequest != other.ServerPollsPerRequest) return false;
- if (ServerQueriesPerCpuSec != other.ServerQueriesPerCpuSec) return false;
- if (ClientQueriesPerCpuSec != other.ClientQueriesPerCpuSec) return false;
- return true;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Qps, other.Qps)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(QpsPerServerCore, other.QpsPerServerCore)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerSystemTime, other.ServerSystemTime)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerUserTime, other.ServerUserTime)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ClientSystemTime, other.ClientSystemTime)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ClientUserTime, other.ClientUserTime)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency50, other.Latency50)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency90, other.Latency90)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency95, other.Latency95)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency99, other.Latency99)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency999, other.Latency999)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerCpuUsage, other.ServerCpuUsage)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(SuccessfulRequestsPerSecond, other.SuccessfulRequestsPerSecond)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(FailedRequestsPerSecond, other.FailedRequestsPerSecond)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ClientPollsPerRequest, other.ClientPollsPerRequest)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerPollsPerRequest, other.ServerPollsPerRequest)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerQueriesPerCpuSec, other.ServerQueriesPerCpuSec)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ClientQueriesPerCpuSec, other.ClientQueriesPerCpuSec)) return false;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
- if (Qps != 0D) hash ^= Qps.GetHashCode();
- if (QpsPerServerCore != 0D) hash ^= QpsPerServerCore.GetHashCode();
- if (ServerSystemTime != 0D) hash ^= ServerSystemTime.GetHashCode();
- if (ServerUserTime != 0D) hash ^= ServerUserTime.GetHashCode();
- if (ClientSystemTime != 0D) hash ^= ClientSystemTime.GetHashCode();
- if (ClientUserTime != 0D) hash ^= ClientUserTime.GetHashCode();
- if (Latency50 != 0D) hash ^= Latency50.GetHashCode();
- if (Latency90 != 0D) hash ^= Latency90.GetHashCode();
- if (Latency95 != 0D) hash ^= Latency95.GetHashCode();
- if (Latency99 != 0D) hash ^= Latency99.GetHashCode();
- if (Latency999 != 0D) hash ^= Latency999.GetHashCode();
- if (ServerCpuUsage != 0D) hash ^= ServerCpuUsage.GetHashCode();
- if (SuccessfulRequestsPerSecond != 0D) hash ^= SuccessfulRequestsPerSecond.GetHashCode();
- if (FailedRequestsPerSecond != 0D) hash ^= FailedRequestsPerSecond.GetHashCode();
- if (ClientPollsPerRequest != 0D) hash ^= ClientPollsPerRequest.GetHashCode();
- if (ServerPollsPerRequest != 0D) hash ^= ServerPollsPerRequest.GetHashCode();
- if (ServerQueriesPerCpuSec != 0D) hash ^= ServerQueriesPerCpuSec.GetHashCode();
- if (ClientQueriesPerCpuSec != 0D) hash ^= ClientQueriesPerCpuSec.GetHashCode();
+ if (Qps != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Qps);
+ if (QpsPerServerCore != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(QpsPerServerCore);
+ if (ServerSystemTime != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerSystemTime);
+ if (ServerUserTime != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerUserTime);
+ if (ClientSystemTime != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ClientSystemTime);
+ if (ClientUserTime != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ClientUserTime);
+ if (Latency50 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency50);
+ if (Latency90 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency90);
+ if (Latency95 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency95);
+ if (Latency99 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency99);
+ if (Latency999 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency999);
+ if (ServerCpuUsage != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerCpuUsage);
+ if (SuccessfulRequestsPerSecond != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(SuccessfulRequestsPerSecond);
+ if (FailedRequestsPerSecond != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(FailedRequestsPerSecond);
+ if (ClientPollsPerRequest != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ClientPollsPerRequest);
+ if (ServerPollsPerRequest != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerPollsPerRequest);
+ if (ServerQueriesPerCpuSec != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerQueriesPerCpuSec);
+ if (ClientQueriesPerCpuSec != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ClientQueriesPerCpuSec);
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -3967,6 +4178,9 @@ namespace Grpc.Testing {
output.WriteRawTag(145, 1);
output.WriteDouble(ClientQueriesPerCpuSec);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -4026,6 +4240,9 @@ namespace Grpc.Testing {
if (ClientQueriesPerCpuSec != 0D) {
size += 2 + 8;
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -4088,6 +4305,7 @@ namespace Grpc.Testing {
if (other.ClientQueriesPerCpuSec != 0D) {
ClientQueriesPerCpuSec = other.ClientQueriesPerCpuSec;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -4096,7 +4314,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 9: {
Qps = input.ReadDouble();
@@ -4181,6 +4399,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class ScenarioResult : pb::IMessage<ScenarioResult> {
private static readonly pb::MessageParser<ScenarioResult> _parser = new pb::MessageParser<ScenarioResult>(() => new ScenarioResult());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ScenarioResult> Parser { get { return _parser; } }
@@ -4212,6 +4431,7 @@ namespace Grpc.Testing {
clientSuccess_ = other.clientSuccess_.Clone();
serverSuccess_ = other.serverSuccess_.Clone();
requestResults_ = other.requestResults_.Clone();
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -4358,7 +4578,7 @@ namespace Grpc.Testing {
if(!clientSuccess_.Equals(other.clientSuccess_)) return false;
if(!serverSuccess_.Equals(other.serverSuccess_)) return false;
if(!requestResults_.Equals(other.requestResults_)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -4373,6 +4593,9 @@ namespace Grpc.Testing {
hash ^= clientSuccess_.GetHashCode();
hash ^= serverSuccess_.GetHashCode();
hash ^= requestResults_.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -4401,6 +4624,9 @@ namespace Grpc.Testing {
clientSuccess_.WriteTo(output, _repeated_clientSuccess_codec);
serverSuccess_.WriteTo(output, _repeated_serverSuccess_codec);
requestResults_.WriteTo(output, _repeated_requestResults_codec);
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -4421,6 +4647,9 @@ namespace Grpc.Testing {
size += clientSuccess_.CalculateSize(_repeated_clientSuccess_codec);
size += serverSuccess_.CalculateSize(_repeated_serverSuccess_codec);
size += requestResults_.CalculateSize(_repeated_requestResults_codec);
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -4453,6 +4682,7 @@ namespace Grpc.Testing {
clientSuccess_.Add(other.clientSuccess_);
serverSuccess_.Add(other.serverSuccess_);
requestResults_.Add(other.requestResults_);
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -4461,7 +4691,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
if (scenario_ == null) {
diff --git a/src/csharp/Grpc.IntegrationTesting/CoreStats/Stats.cs b/src/csharp/Grpc.IntegrationTesting/CoreStats/Stats.cs
index 380294e335..4ff56cd3ec 100644
--- a/src/csharp/Grpc.IntegrationTesting/CoreStats/Stats.cs
+++ b/src/csharp/Grpc.IntegrationTesting/CoreStats/Stats.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
-// source: grpc/core/stats.proto
+// <auto-generated>
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: grpc/core/stats.proto
+// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
@@ -43,6 +45,7 @@ namespace Grpc.Core {
#region Messages
public sealed partial class Bucket : pb::IMessage<Bucket> {
private static readonly pb::MessageParser<Bucket> _parser = new pb::MessageParser<Bucket>(() => new Bucket());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Bucket> Parser { get { return _parser; } }
@@ -67,6 +70,7 @@ namespace Grpc.Core {
public Bucket(Bucket other) : this() {
start_ = other.start_;
count_ = other.count_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -109,16 +113,19 @@ namespace Grpc.Core {
if (ReferenceEquals(other, this)) {
return true;
}
- if (Start != other.Start) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Start, other.Start)) return false;
if (Count != other.Count) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
- if (Start != 0D) hash ^= Start.GetHashCode();
+ if (Start != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Start);
if (Count != 0UL) hash ^= Count.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -137,6 +144,9 @@ namespace Grpc.Core {
output.WriteRawTag(16);
output.WriteUInt64(Count);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -148,6 +158,9 @@ namespace Grpc.Core {
if (Count != 0UL) {
size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Count);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -162,6 +175,7 @@ namespace Grpc.Core {
if (other.Count != 0UL) {
Count = other.Count;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -170,7 +184,7 @@ namespace Grpc.Core {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 9: {
Start = input.ReadDouble();
@@ -188,6 +202,7 @@ namespace Grpc.Core {
public sealed partial class Histogram : pb::IMessage<Histogram> {
private static readonly pb::MessageParser<Histogram> _parser = new pb::MessageParser<Histogram>(() => new Histogram());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Histogram> Parser { get { return _parser; } }
@@ -211,6 +226,7 @@ namespace Grpc.Core {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Histogram(Histogram other) : this() {
buckets_ = other.buckets_.Clone();
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -242,13 +258,16 @@ namespace Grpc.Core {
return true;
}
if(!buckets_.Equals(other.buckets_)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
hash ^= buckets_.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -260,12 +279,18 @@ namespace Grpc.Core {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
buckets_.WriteTo(output, _repeated_buckets_codec);
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
size += buckets_.CalculateSize(_repeated_buckets_codec);
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -275,6 +300,7 @@ namespace Grpc.Core {
return;
}
buckets_.Add(other.buckets_);
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -283,7 +309,7 @@ namespace Grpc.Core {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
buckets_.AddEntriesFrom(input, _repeated_buckets_codec);
@@ -297,6 +323,7 @@ namespace Grpc.Core {
public sealed partial class Metric : pb::IMessage<Metric> {
private static readonly pb::MessageParser<Metric> _parser = new pb::MessageParser<Metric>(() => new Metric());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Metric> Parser { get { return _parser; } }
@@ -329,6 +356,7 @@ namespace Grpc.Core {
break;
}
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -405,7 +433,7 @@ namespace Grpc.Core {
if (Count != other.Count) return false;
if (!object.Equals(Histogram, other.Histogram)) return false;
if (ValueCase != other.ValueCase) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -415,6 +443,9 @@ namespace Grpc.Core {
if (valueCase_ == ValueOneofCase.Count) hash ^= Count.GetHashCode();
if (valueCase_ == ValueOneofCase.Histogram) hash ^= Histogram.GetHashCode();
hash ^= (int) valueCase_;
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -437,6 +468,9 @@ namespace Grpc.Core {
output.WriteRawTag(90);
output.WriteMessage(Histogram);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -451,6 +485,9 @@ namespace Grpc.Core {
if (valueCase_ == ValueOneofCase.Histogram) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Histogram);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -474,6 +511,7 @@ namespace Grpc.Core {
break;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -482,7 +520,7 @@ namespace Grpc.Core {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Name = input.ReadString();
@@ -509,6 +547,7 @@ namespace Grpc.Core {
public sealed partial class Stats : pb::IMessage<Stats> {
private static readonly pb::MessageParser<Stats> _parser = new pb::MessageParser<Stats>(() => new Stats());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Stats> Parser { get { return _parser; } }
@@ -532,6 +571,7 @@ namespace Grpc.Core {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Stats(Stats other) : this() {
metrics_ = other.metrics_.Clone();
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -563,13 +603,16 @@ namespace Grpc.Core {
return true;
}
if(!metrics_.Equals(other.metrics_)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
hash ^= metrics_.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -581,12 +624,18 @@ namespace Grpc.Core {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
metrics_.WriteTo(output, _repeated_metrics_codec);
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
size += metrics_.CalculateSize(_repeated_metrics_codec);
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -596,6 +645,7 @@ namespace Grpc.Core {
return;
}
metrics_.Add(other.metrics_);
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -604,7 +654,7 @@ namespace Grpc.Core {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
metrics_.AddEntriesFrom(input, _repeated_metrics_codec);
diff --git a/src/csharp/Grpc.IntegrationTesting/EchoMessages.cs b/src/csharp/Grpc.IntegrationTesting/EchoMessages.cs
index 9581aded58..39c3d76ce8 100644
--- a/src/csharp/Grpc.IntegrationTesting/EchoMessages.cs
+++ b/src/csharp/Grpc.IntegrationTesting/EchoMessages.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
-// source: src/proto/grpc/testing/echo_messages.proto
+// <auto-generated>
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: src/proto/grpc/testing/echo_messages.proto
+// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
@@ -63,6 +65,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class DebugInfo : pb::IMessage<DebugInfo> {
private static readonly pb::MessageParser<DebugInfo> _parser = new pb::MessageParser<DebugInfo>(() => new DebugInfo());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<DebugInfo> Parser { get { return _parser; } }
@@ -87,6 +90,7 @@ namespace Grpc.Testing {
public DebugInfo(DebugInfo other) : this() {
stackEntries_ = other.stackEntries_.Clone();
detail_ = other.detail_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -130,7 +134,7 @@ namespace Grpc.Testing {
}
if(!stackEntries_.Equals(other.stackEntries_)) return false;
if (Detail != other.Detail) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -138,6 +142,9 @@ namespace Grpc.Testing {
int hash = 1;
hash ^= stackEntries_.GetHashCode();
if (Detail.Length != 0) hash ^= Detail.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -153,6 +160,9 @@ namespace Grpc.Testing {
output.WriteRawTag(18);
output.WriteString(Detail);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -162,6 +172,9 @@ namespace Grpc.Testing {
if (Detail.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Detail);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -174,6 +187,7 @@ namespace Grpc.Testing {
if (other.Detail.Length != 0) {
Detail = other.Detail;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -182,7 +196,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
stackEntries_.AddEntriesFrom(input, _repeated_stackEntries_codec);
@@ -203,6 +217,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class ErrorStatus : pb::IMessage<ErrorStatus> {
private static readonly pb::MessageParser<ErrorStatus> _parser = new pb::MessageParser<ErrorStatus>(() => new ErrorStatus());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ErrorStatus> Parser { get { return _parser; } }
@@ -228,6 +243,7 @@ namespace Grpc.Testing {
code_ = other.code_;
errorMessage_ = other.errorMessage_;
binaryErrorDetails_ = other.binaryErrorDetails_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -284,7 +300,7 @@ namespace Grpc.Testing {
if (Code != other.Code) return false;
if (ErrorMessage != other.ErrorMessage) return false;
if (BinaryErrorDetails != other.BinaryErrorDetails) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -293,6 +309,9 @@ namespace Grpc.Testing {
if (Code != 0) hash ^= Code.GetHashCode();
if (ErrorMessage.Length != 0) hash ^= ErrorMessage.GetHashCode();
if (BinaryErrorDetails.Length != 0) hash ^= BinaryErrorDetails.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -315,6 +334,9 @@ namespace Grpc.Testing {
output.WriteRawTag(26);
output.WriteString(BinaryErrorDetails);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -329,6 +351,9 @@ namespace Grpc.Testing {
if (BinaryErrorDetails.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(BinaryErrorDetails);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -346,6 +371,7 @@ namespace Grpc.Testing {
if (other.BinaryErrorDetails.Length != 0) {
BinaryErrorDetails = other.BinaryErrorDetails;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -354,7 +380,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
Code = input.ReadInt32();
@@ -376,6 +402,7 @@ namespace Grpc.Testing {
public sealed partial class RequestParams : pb::IMessage<RequestParams> {
private static readonly pb::MessageParser<RequestParams> _parser = new pb::MessageParser<RequestParams>(() => new RequestParams());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<RequestParams> Parser { get { return _parser; } }
@@ -413,6 +440,7 @@ namespace Grpc.Testing {
binaryErrorDetails_ = other.binaryErrorDetails_;
ExpectedError = other.expectedError_ != null ? other.ExpectedError.Clone() : null;
serverSleepUs_ = other.serverSleepUs_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -622,7 +650,7 @@ namespace Grpc.Testing {
if (BinaryErrorDetails != other.BinaryErrorDetails) return false;
if (!object.Equals(ExpectedError, other.ExpectedError)) return false;
if (ServerSleepUs != other.ServerSleepUs) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -643,6 +671,9 @@ namespace Grpc.Testing {
if (BinaryErrorDetails.Length != 0) hash ^= BinaryErrorDetails.GetHashCode();
if (expectedError_ != null) hash ^= ExpectedError.GetHashCode();
if (ServerSleepUs != 0) hash ^= ServerSleepUs.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -713,6 +744,9 @@ namespace Grpc.Testing {
output.WriteRawTag(120);
output.WriteInt32(ServerSleepUs);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -763,6 +797,9 @@ namespace Grpc.Testing {
if (ServerSleepUs != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(ServerSleepUs);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -822,6 +859,7 @@ namespace Grpc.Testing {
if (other.ServerSleepUs != 0) {
ServerSleepUs = other.ServerSleepUs;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -830,7 +868,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
EchoDeadline = input.ReadBool();
@@ -906,6 +944,7 @@ namespace Grpc.Testing {
public sealed partial class EchoRequest : pb::IMessage<EchoRequest> {
private static readonly pb::MessageParser<EchoRequest> _parser = new pb::MessageParser<EchoRequest>(() => new EchoRequest());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<EchoRequest> Parser { get { return _parser; } }
@@ -930,6 +969,7 @@ namespace Grpc.Testing {
public EchoRequest(EchoRequest other) : this() {
message_ = other.message_;
Param = other.param_ != null ? other.Param.Clone() : null;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -974,7 +1014,7 @@ namespace Grpc.Testing {
}
if (Message != other.Message) return false;
if (!object.Equals(Param, other.Param)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -982,6 +1022,9 @@ namespace Grpc.Testing {
int hash = 1;
if (Message.Length != 0) hash ^= Message.GetHashCode();
if (param_ != null) hash ^= Param.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -1000,6 +1043,9 @@ namespace Grpc.Testing {
output.WriteRawTag(18);
output.WriteMessage(Param);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1011,6 +1057,9 @@ namespace Grpc.Testing {
if (param_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Param);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1028,6 +1077,7 @@ namespace Grpc.Testing {
}
Param.MergeFrom(other.Param);
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1036,7 +1086,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Message = input.ReadString();
@@ -1057,6 +1107,7 @@ namespace Grpc.Testing {
public sealed partial class ResponseParams : pb::IMessage<ResponseParams> {
private static readonly pb::MessageParser<ResponseParams> _parser = new pb::MessageParser<ResponseParams>(() => new ResponseParams());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ResponseParams> Parser { get { return _parser; } }
@@ -1082,6 +1133,7 @@ namespace Grpc.Testing {
requestDeadline_ = other.requestDeadline_;
host_ = other.host_;
peer_ = other.peer_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1138,7 +1190,7 @@ namespace Grpc.Testing {
if (RequestDeadline != other.RequestDeadline) return false;
if (Host != other.Host) return false;
if (Peer != other.Peer) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1147,6 +1199,9 @@ namespace Grpc.Testing {
if (RequestDeadline != 0L) hash ^= RequestDeadline.GetHashCode();
if (Host.Length != 0) hash ^= Host.GetHashCode();
if (Peer.Length != 0) hash ^= Peer.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -1169,6 +1224,9 @@ namespace Grpc.Testing {
output.WriteRawTag(26);
output.WriteString(Peer);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1183,6 +1241,9 @@ namespace Grpc.Testing {
if (Peer.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Peer);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1200,6 +1261,7 @@ namespace Grpc.Testing {
if (other.Peer.Length != 0) {
Peer = other.Peer;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1208,7 +1270,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
RequestDeadline = input.ReadInt64();
@@ -1230,6 +1292,7 @@ namespace Grpc.Testing {
public sealed partial class EchoResponse : pb::IMessage<EchoResponse> {
private static readonly pb::MessageParser<EchoResponse> _parser = new pb::MessageParser<EchoResponse>(() => new EchoResponse());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<EchoResponse> Parser { get { return _parser; } }
@@ -1254,6 +1317,7 @@ namespace Grpc.Testing {
public EchoResponse(EchoResponse other) : this() {
message_ = other.message_;
Param = other.param_ != null ? other.Param.Clone() : null;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1298,7 +1362,7 @@ namespace Grpc.Testing {
}
if (Message != other.Message) return false;
if (!object.Equals(Param, other.Param)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1306,6 +1370,9 @@ namespace Grpc.Testing {
int hash = 1;
if (Message.Length != 0) hash ^= Message.GetHashCode();
if (param_ != null) hash ^= Param.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -1324,6 +1391,9 @@ namespace Grpc.Testing {
output.WriteRawTag(18);
output.WriteMessage(Param);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1335,6 +1405,9 @@ namespace Grpc.Testing {
if (param_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Param);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1352,6 +1425,7 @@ namespace Grpc.Testing {
}
Param.MergeFrom(other.Param);
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1360,7 +1434,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Message = input.ReadString();
diff --git a/src/csharp/Grpc.IntegrationTesting/Empty.cs b/src/csharp/Grpc.IntegrationTesting/Empty.cs
index 24ffd61741..0d4c28bf7f 100644
--- a/src/csharp/Grpc.IntegrationTesting/Empty.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Empty.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
-// source: src/proto/grpc/testing/empty.proto
+// <auto-generated>
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: src/proto/grpc/testing/empty.proto
+// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
@@ -45,6 +47,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class Empty : pb::IMessage<Empty> {
private static readonly pb::MessageParser<Empty> _parser = new pb::MessageParser<Empty>(() => new Empty());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Empty> Parser { get { return _parser; } }
@@ -67,6 +70,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Empty(Empty other) : this() {
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -87,12 +91,15 @@ namespace Grpc.Testing {
if (ReferenceEquals(other, this)) {
return true;
}
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -103,11 +110,17 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -116,6 +129,7 @@ namespace Grpc.Testing {
if (other == null) {
return;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -124,7 +138,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
}
}
diff --git a/src/csharp/Grpc.IntegrationTesting/Messages.cs b/src/csharp/Grpc.IntegrationTesting/Messages.cs
index 278ef662e4..b5c93babd2 100644
--- a/src/csharp/Grpc.IntegrationTesting/Messages.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Messages.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
-// source: src/proto/grpc/testing/messages.proto
+// <auto-generated>
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: src/proto/grpc/testing/messages.proto
+// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
@@ -95,6 +97,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class BoolValue : pb::IMessage<BoolValue> {
private static readonly pb::MessageParser<BoolValue> _parser = new pb::MessageParser<BoolValue>(() => new BoolValue());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<BoolValue> Parser { get { return _parser; } }
@@ -118,6 +121,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public BoolValue(BoolValue other) : this() {
value_ = other.value_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -153,13 +157,16 @@ namespace Grpc.Testing {
return true;
}
if (Value != other.Value) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Value != false) hash ^= Value.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -174,6 +181,9 @@ namespace Grpc.Testing {
output.WriteRawTag(8);
output.WriteBool(Value);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -182,6 +192,9 @@ namespace Grpc.Testing {
if (Value != false) {
size += 1 + 1;
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -193,6 +206,7 @@ namespace Grpc.Testing {
if (other.Value != false) {
Value = other.Value;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -201,7 +215,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
Value = input.ReadBool();
@@ -218,6 +232,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class Payload : pb::IMessage<Payload> {
private static readonly pb::MessageParser<Payload> _parser = new pb::MessageParser<Payload>(() => new Payload());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Payload> Parser { get { return _parser; } }
@@ -242,6 +257,7 @@ namespace Grpc.Testing {
public Payload(Payload other) : this() {
type_ = other.type_;
body_ = other.body_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -293,7 +309,7 @@ namespace Grpc.Testing {
}
if (Type != other.Type) return false;
if (Body != other.Body) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -301,6 +317,9 @@ namespace Grpc.Testing {
int hash = 1;
if (Type != 0) hash ^= Type.GetHashCode();
if (Body.Length != 0) hash ^= Body.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -319,6 +338,9 @@ namespace Grpc.Testing {
output.WriteRawTag(18);
output.WriteBytes(Body);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -330,6 +352,9 @@ namespace Grpc.Testing {
if (Body.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeBytesSize(Body);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -344,6 +369,7 @@ namespace Grpc.Testing {
if (other.Body.Length != 0) {
Body = other.Body;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -352,7 +378,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
type_ = (global::Grpc.Testing.PayloadType) input.ReadEnum();
@@ -374,6 +400,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class EchoStatus : pb::IMessage<EchoStatus> {
private static readonly pb::MessageParser<EchoStatus> _parser = new pb::MessageParser<EchoStatus>(() => new EchoStatus());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<EchoStatus> Parser { get { return _parser; } }
@@ -398,6 +425,7 @@ namespace Grpc.Testing {
public EchoStatus(EchoStatus other) : this() {
code_ = other.code_;
message_ = other.message_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -442,7 +470,7 @@ namespace Grpc.Testing {
}
if (Code != other.Code) return false;
if (Message != other.Message) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -450,6 +478,9 @@ namespace Grpc.Testing {
int hash = 1;
if (Code != 0) hash ^= Code.GetHashCode();
if (Message.Length != 0) hash ^= Message.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -468,6 +499,9 @@ namespace Grpc.Testing {
output.WriteRawTag(18);
output.WriteString(Message);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -479,6 +513,9 @@ namespace Grpc.Testing {
if (Message.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Message);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -493,6 +530,7 @@ namespace Grpc.Testing {
if (other.Message.Length != 0) {
Message = other.Message;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -501,7 +539,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
Code = input.ReadInt32();
@@ -522,6 +560,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class SimpleRequest : pb::IMessage<SimpleRequest> {
private static readonly pb::MessageParser<SimpleRequest> _parser = new pb::MessageParser<SimpleRequest>(() => new SimpleRequest());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<SimpleRequest> Parser { get { return _parser; } }
@@ -552,6 +591,7 @@ namespace Grpc.Testing {
ResponseCompressed = other.responseCompressed_ != null ? other.ResponseCompressed.Clone() : null;
ResponseStatus = other.responseStatus_ != null ? other.ResponseStatus.Clone() : null;
ExpectCompressed = other.expectCompressed_ != null ? other.ExpectCompressed.Clone() : null;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -697,7 +737,7 @@ namespace Grpc.Testing {
if (!object.Equals(ResponseCompressed, other.ResponseCompressed)) return false;
if (!object.Equals(ResponseStatus, other.ResponseStatus)) return false;
if (!object.Equals(ExpectCompressed, other.ExpectCompressed)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -711,6 +751,9 @@ namespace Grpc.Testing {
if (responseCompressed_ != null) hash ^= ResponseCompressed.GetHashCode();
if (responseStatus_ != null) hash ^= ResponseStatus.GetHashCode();
if (expectCompressed_ != null) hash ^= ExpectCompressed.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -753,6 +796,9 @@ namespace Grpc.Testing {
output.WriteRawTag(66);
output.WriteMessage(ExpectCompressed);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -782,6 +828,9 @@ namespace Grpc.Testing {
if (expectCompressed_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(ExpectCompressed);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -826,6 +875,7 @@ namespace Grpc.Testing {
}
ExpectCompressed.MergeFrom(other.ExpectCompressed);
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -834,7 +884,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
responseType_ = (global::Grpc.Testing.PayloadType) input.ReadEnum();
@@ -891,6 +941,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class SimpleResponse : pb::IMessage<SimpleResponse> {
private static readonly pb::MessageParser<SimpleResponse> _parser = new pb::MessageParser<SimpleResponse>(() => new SimpleResponse());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<SimpleResponse> Parser { get { return _parser; } }
@@ -916,6 +967,7 @@ namespace Grpc.Testing {
Payload = other.payload_ != null ? other.Payload.Clone() : null;
username_ = other.username_;
oauthScope_ = other.oauthScope_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -982,7 +1034,7 @@ namespace Grpc.Testing {
if (!object.Equals(Payload, other.Payload)) return false;
if (Username != other.Username) return false;
if (OauthScope != other.OauthScope) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -991,6 +1043,9 @@ namespace Grpc.Testing {
if (payload_ != null) hash ^= Payload.GetHashCode();
if (Username.Length != 0) hash ^= Username.GetHashCode();
if (OauthScope.Length != 0) hash ^= OauthScope.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -1013,6 +1068,9 @@ namespace Grpc.Testing {
output.WriteRawTag(26);
output.WriteString(OauthScope);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1027,6 +1085,9 @@ namespace Grpc.Testing {
if (OauthScope.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(OauthScope);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1047,6 +1108,7 @@ namespace Grpc.Testing {
if (other.OauthScope.Length != 0) {
OauthScope = other.OauthScope;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1055,7 +1117,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
if (payload_ == null) {
@@ -1083,6 +1145,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class StreamingInputCallRequest : pb::IMessage<StreamingInputCallRequest> {
private static readonly pb::MessageParser<StreamingInputCallRequest> _parser = new pb::MessageParser<StreamingInputCallRequest>(() => new StreamingInputCallRequest());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<StreamingInputCallRequest> Parser { get { return _parser; } }
@@ -1107,6 +1170,7 @@ namespace Grpc.Testing {
public StreamingInputCallRequest(StreamingInputCallRequest other) : this() {
Payload = other.payload_ != null ? other.Payload.Clone() : null;
ExpectCompressed = other.expectCompressed_ != null ? other.ExpectCompressed.Clone() : null;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1160,7 +1224,7 @@ namespace Grpc.Testing {
}
if (!object.Equals(Payload, other.Payload)) return false;
if (!object.Equals(ExpectCompressed, other.ExpectCompressed)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1168,6 +1232,9 @@ namespace Grpc.Testing {
int hash = 1;
if (payload_ != null) hash ^= Payload.GetHashCode();
if (expectCompressed_ != null) hash ^= ExpectCompressed.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -1186,6 +1253,9 @@ namespace Grpc.Testing {
output.WriteRawTag(18);
output.WriteMessage(ExpectCompressed);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1197,6 +1267,9 @@ namespace Grpc.Testing {
if (expectCompressed_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(ExpectCompressed);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1217,6 +1290,7 @@ namespace Grpc.Testing {
}
ExpectCompressed.MergeFrom(other.ExpectCompressed);
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1225,7 +1299,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
if (payload_ == null) {
@@ -1252,6 +1326,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class StreamingInputCallResponse : pb::IMessage<StreamingInputCallResponse> {
private static readonly pb::MessageParser<StreamingInputCallResponse> _parser = new pb::MessageParser<StreamingInputCallResponse>(() => new StreamingInputCallResponse());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<StreamingInputCallResponse> Parser { get { return _parser; } }
@@ -1275,6 +1350,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public StreamingInputCallResponse(StreamingInputCallResponse other) : this() {
aggregatedPayloadSize_ = other.aggregatedPayloadSize_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1310,13 +1386,16 @@ namespace Grpc.Testing {
return true;
}
if (AggregatedPayloadSize != other.AggregatedPayloadSize) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (AggregatedPayloadSize != 0) hash ^= AggregatedPayloadSize.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -1331,6 +1410,9 @@ namespace Grpc.Testing {
output.WriteRawTag(8);
output.WriteInt32(AggregatedPayloadSize);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1339,6 +1421,9 @@ namespace Grpc.Testing {
if (AggregatedPayloadSize != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(AggregatedPayloadSize);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1350,6 +1435,7 @@ namespace Grpc.Testing {
if (other.AggregatedPayloadSize != 0) {
AggregatedPayloadSize = other.AggregatedPayloadSize;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1358,7 +1444,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
AggregatedPayloadSize = input.ReadInt32();
@@ -1375,6 +1461,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class ResponseParameters : pb::IMessage<ResponseParameters> {
private static readonly pb::MessageParser<ResponseParameters> _parser = new pb::MessageParser<ResponseParameters>(() => new ResponseParameters());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ResponseParameters> Parser { get { return _parser; } }
@@ -1400,6 +1487,7 @@ namespace Grpc.Testing {
size_ = other.size_;
intervalUs_ = other.intervalUs_;
Compressed = other.compressed_ != null ? other.Compressed.Clone() : null;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1469,7 +1557,7 @@ namespace Grpc.Testing {
if (Size != other.Size) return false;
if (IntervalUs != other.IntervalUs) return false;
if (!object.Equals(Compressed, other.Compressed)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1478,6 +1566,9 @@ namespace Grpc.Testing {
if (Size != 0) hash ^= Size.GetHashCode();
if (IntervalUs != 0) hash ^= IntervalUs.GetHashCode();
if (compressed_ != null) hash ^= Compressed.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -1500,6 +1591,9 @@ namespace Grpc.Testing {
output.WriteRawTag(26);
output.WriteMessage(Compressed);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1514,6 +1608,9 @@ namespace Grpc.Testing {
if (compressed_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Compressed);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1534,6 +1631,7 @@ namespace Grpc.Testing {
}
Compressed.MergeFrom(other.Compressed);
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1542,7 +1640,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
Size = input.ReadInt32();
@@ -1570,6 +1668,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class StreamingOutputCallRequest : pb::IMessage<StreamingOutputCallRequest> {
private static readonly pb::MessageParser<StreamingOutputCallRequest> _parser = new pb::MessageParser<StreamingOutputCallRequest>(() => new StreamingOutputCallRequest());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<StreamingOutputCallRequest> Parser { get { return _parser; } }
@@ -1596,6 +1695,7 @@ namespace Grpc.Testing {
responseParameters_ = other.responseParameters_.Clone();
Payload = other.payload_ != null ? other.Payload.Clone() : null;
ResponseStatus = other.responseStatus_ != null ? other.ResponseStatus.Clone() : null;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1679,7 +1779,7 @@ namespace Grpc.Testing {
if(!responseParameters_.Equals(other.responseParameters_)) return false;
if (!object.Equals(Payload, other.Payload)) return false;
if (!object.Equals(ResponseStatus, other.ResponseStatus)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1689,6 +1789,9 @@ namespace Grpc.Testing {
hash ^= responseParameters_.GetHashCode();
if (payload_ != null) hash ^= Payload.GetHashCode();
if (responseStatus_ != null) hash ^= ResponseStatus.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -1712,6 +1815,9 @@ namespace Grpc.Testing {
output.WriteRawTag(58);
output.WriteMessage(ResponseStatus);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1727,6 +1833,9 @@ namespace Grpc.Testing {
if (responseStatus_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(ResponseStatus);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1751,6 +1860,7 @@ namespace Grpc.Testing {
}
ResponseStatus.MergeFrom(other.ResponseStatus);
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1759,7 +1869,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
responseType_ = (global::Grpc.Testing.PayloadType) input.ReadEnum();
@@ -1794,6 +1904,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class StreamingOutputCallResponse : pb::IMessage<StreamingOutputCallResponse> {
private static readonly pb::MessageParser<StreamingOutputCallResponse> _parser = new pb::MessageParser<StreamingOutputCallResponse>(() => new StreamingOutputCallResponse());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<StreamingOutputCallResponse> Parser { get { return _parser; } }
@@ -1817,6 +1928,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public StreamingOutputCallResponse(StreamingOutputCallResponse other) : this() {
Payload = other.payload_ != null ? other.Payload.Clone() : null;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1852,13 +1964,16 @@ namespace Grpc.Testing {
return true;
}
if (!object.Equals(Payload, other.Payload)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (payload_ != null) hash ^= Payload.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -1873,6 +1988,9 @@ namespace Grpc.Testing {
output.WriteRawTag(10);
output.WriteMessage(Payload);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1881,6 +1999,9 @@ namespace Grpc.Testing {
if (payload_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1895,6 +2016,7 @@ namespace Grpc.Testing {
}
Payload.MergeFrom(other.Payload);
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1903,7 +2025,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
if (payload_ == null) {
@@ -1924,6 +2046,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class ReconnectParams : pb::IMessage<ReconnectParams> {
private static readonly pb::MessageParser<ReconnectParams> _parser = new pb::MessageParser<ReconnectParams>(() => new ReconnectParams());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ReconnectParams> Parser { get { return _parser; } }
@@ -1947,6 +2070,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ReconnectParams(ReconnectParams other) : this() {
maxReconnectBackoffMs_ = other.maxReconnectBackoffMs_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1979,13 +2103,16 @@ namespace Grpc.Testing {
return true;
}
if (MaxReconnectBackoffMs != other.MaxReconnectBackoffMs) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (MaxReconnectBackoffMs != 0) hash ^= MaxReconnectBackoffMs.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -2000,6 +2127,9 @@ namespace Grpc.Testing {
output.WriteRawTag(8);
output.WriteInt32(MaxReconnectBackoffMs);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2008,6 +2138,9 @@ namespace Grpc.Testing {
if (MaxReconnectBackoffMs != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(MaxReconnectBackoffMs);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -2019,6 +2152,7 @@ namespace Grpc.Testing {
if (other.MaxReconnectBackoffMs != 0) {
MaxReconnectBackoffMs = other.MaxReconnectBackoffMs;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2027,7 +2161,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
MaxReconnectBackoffMs = input.ReadInt32();
@@ -2046,6 +2180,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class ReconnectInfo : pb::IMessage<ReconnectInfo> {
private static readonly pb::MessageParser<ReconnectInfo> _parser = new pb::MessageParser<ReconnectInfo>(() => new ReconnectInfo());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ReconnectInfo> Parser { get { return _parser; } }
@@ -2070,6 +2205,7 @@ namespace Grpc.Testing {
public ReconnectInfo(ReconnectInfo other) : this() {
passed_ = other.passed_;
backoffMs_ = other.backoffMs_.Clone();
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2113,7 +2249,7 @@ namespace Grpc.Testing {
}
if (Passed != other.Passed) return false;
if(!backoffMs_.Equals(other.backoffMs_)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2121,6 +2257,9 @@ namespace Grpc.Testing {
int hash = 1;
if (Passed != false) hash ^= Passed.GetHashCode();
hash ^= backoffMs_.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -2136,6 +2275,9 @@ namespace Grpc.Testing {
output.WriteBool(Passed);
}
backoffMs_.WriteTo(output, _repeated_backoffMs_codec);
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2145,6 +2287,9 @@ namespace Grpc.Testing {
size += 1 + 1;
}
size += backoffMs_.CalculateSize(_repeated_backoffMs_codec);
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -2157,6 +2302,7 @@ namespace Grpc.Testing {
Passed = other.Passed;
}
backoffMs_.Add(other.backoffMs_);
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2165,7 +2311,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
Passed = input.ReadBool();
diff --git a/src/csharp/Grpc.IntegrationTesting/Metrics.cs b/src/csharp/Grpc.IntegrationTesting/Metrics.cs
index 84eb09af4f..b5d8b87a68 100644
--- a/src/csharp/Grpc.IntegrationTesting/Metrics.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Metrics.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
-// source: src/proto/grpc/testing/metrics.proto
+// <auto-generated>
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: src/proto/grpc/testing/metrics.proto
+// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
@@ -48,6 +50,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class GaugeResponse : pb::IMessage<GaugeResponse> {
private static readonly pb::MessageParser<GaugeResponse> _parser = new pb::MessageParser<GaugeResponse>(() => new GaugeResponse());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<GaugeResponse> Parser { get { return _parser; } }
@@ -83,6 +86,7 @@ namespace Grpc.Testing {
break;
}
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -169,10 +173,10 @@ namespace Grpc.Testing {
}
if (Name != other.Name) return false;
if (LongValue != other.LongValue) return false;
- if (DoubleValue != other.DoubleValue) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleValue, other.DoubleValue)) return false;
if (StringValue != other.StringValue) return false;
if (ValueCase != other.ValueCase) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -180,9 +184,12 @@ namespace Grpc.Testing {
int hash = 1;
if (Name.Length != 0) hash ^= Name.GetHashCode();
if (valueCase_ == ValueOneofCase.LongValue) hash ^= LongValue.GetHashCode();
- if (valueCase_ == ValueOneofCase.DoubleValue) hash ^= DoubleValue.GetHashCode();
+ if (valueCase_ == ValueOneofCase.DoubleValue) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleValue);
if (valueCase_ == ValueOneofCase.StringValue) hash ^= StringValue.GetHashCode();
hash ^= (int) valueCase_;
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -209,6 +216,9 @@ namespace Grpc.Testing {
output.WriteRawTag(34);
output.WriteString(StringValue);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -226,6 +236,9 @@ namespace Grpc.Testing {
if (valueCase_ == ValueOneofCase.StringValue) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(StringValue);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -249,6 +262,7 @@ namespace Grpc.Testing {
break;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -257,7 +271,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Name = input.ReadString();
@@ -286,6 +300,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class GaugeRequest : pb::IMessage<GaugeRequest> {
private static readonly pb::MessageParser<GaugeRequest> _parser = new pb::MessageParser<GaugeRequest>(() => new GaugeRequest());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<GaugeRequest> Parser { get { return _parser; } }
@@ -309,6 +324,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public GaugeRequest(GaugeRequest other) : this() {
name_ = other.name_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -341,13 +357,16 @@ namespace Grpc.Testing {
return true;
}
if (Name != other.Name) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Name.Length != 0) hash ^= Name.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -362,6 +381,9 @@ namespace Grpc.Testing {
output.WriteRawTag(10);
output.WriteString(Name);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -370,6 +392,9 @@ namespace Grpc.Testing {
if (Name.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -381,6 +406,7 @@ namespace Grpc.Testing {
if (other.Name.Length != 0) {
Name = other.Name;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -389,7 +415,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Name = input.ReadString();
@@ -403,6 +429,7 @@ namespace Grpc.Testing {
public sealed partial class EmptyMessage : pb::IMessage<EmptyMessage> {
private static readonly pb::MessageParser<EmptyMessage> _parser = new pb::MessageParser<EmptyMessage>(() => new EmptyMessage());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<EmptyMessage> Parser { get { return _parser; } }
@@ -425,6 +452,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public EmptyMessage(EmptyMessage other) : this() {
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -445,12 +473,15 @@ namespace Grpc.Testing {
if (ReferenceEquals(other, this)) {
return true;
}
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -461,11 +492,17 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -474,6 +511,7 @@ namespace Grpc.Testing {
if (other == null) {
return;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -482,7 +520,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
}
}
diff --git a/src/csharp/Grpc.IntegrationTesting/Payloads.cs b/src/csharp/Grpc.IntegrationTesting/Payloads.cs
index fca8cda6f6..25f34ff05e 100644
--- a/src/csharp/Grpc.IntegrationTesting/Payloads.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Payloads.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
-// source: src/proto/grpc/testing/payloads.proto
+// <auto-generated>
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: src/proto/grpc/testing/payloads.proto
+// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
@@ -46,6 +48,7 @@ namespace Grpc.Testing {
#region Messages
public sealed partial class ByteBufferParams : pb::IMessage<ByteBufferParams> {
private static readonly pb::MessageParser<ByteBufferParams> _parser = new pb::MessageParser<ByteBufferParams>(() => new ByteBufferParams());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ByteBufferParams> Parser { get { return _parser; } }
@@ -70,6 +73,7 @@ namespace Grpc.Testing {
public ByteBufferParams(ByteBufferParams other) : this() {
reqSize_ = other.reqSize_;
respSize_ = other.respSize_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -114,7 +118,7 @@ namespace Grpc.Testing {
}
if (ReqSize != other.ReqSize) return false;
if (RespSize != other.RespSize) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -122,6 +126,9 @@ namespace Grpc.Testing {
int hash = 1;
if (ReqSize != 0) hash ^= ReqSize.GetHashCode();
if (RespSize != 0) hash ^= RespSize.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -140,6 +147,9 @@ namespace Grpc.Testing {
output.WriteRawTag(16);
output.WriteInt32(RespSize);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -151,6 +161,9 @@ namespace Grpc.Testing {
if (RespSize != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(RespSize);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -165,6 +178,7 @@ namespace Grpc.Testing {
if (other.RespSize != 0) {
RespSize = other.RespSize;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -173,7 +187,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
ReqSize = input.ReadInt32();
@@ -191,6 +205,7 @@ namespace Grpc.Testing {
public sealed partial class SimpleProtoParams : pb::IMessage<SimpleProtoParams> {
private static readonly pb::MessageParser<SimpleProtoParams> _parser = new pb::MessageParser<SimpleProtoParams>(() => new SimpleProtoParams());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<SimpleProtoParams> Parser { get { return _parser; } }
@@ -215,6 +230,7 @@ namespace Grpc.Testing {
public SimpleProtoParams(SimpleProtoParams other) : this() {
reqSize_ = other.reqSize_;
respSize_ = other.respSize_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -259,7 +275,7 @@ namespace Grpc.Testing {
}
if (ReqSize != other.ReqSize) return false;
if (RespSize != other.RespSize) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -267,6 +283,9 @@ namespace Grpc.Testing {
int hash = 1;
if (ReqSize != 0) hash ^= ReqSize.GetHashCode();
if (RespSize != 0) hash ^= RespSize.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -285,6 +304,9 @@ namespace Grpc.Testing {
output.WriteRawTag(16);
output.WriteInt32(RespSize);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -296,6 +318,9 @@ namespace Grpc.Testing {
if (RespSize != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(RespSize);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -310,6 +335,7 @@ namespace Grpc.Testing {
if (other.RespSize != 0) {
RespSize = other.RespSize;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -318,7 +344,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
ReqSize = input.ReadInt32();
@@ -340,6 +366,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class ComplexProtoParams : pb::IMessage<ComplexProtoParams> {
private static readonly pb::MessageParser<ComplexProtoParams> _parser = new pb::MessageParser<ComplexProtoParams>(() => new ComplexProtoParams());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ComplexProtoParams> Parser { get { return _parser; } }
@@ -362,6 +389,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ComplexProtoParams(ComplexProtoParams other) : this() {
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -382,12 +410,15 @@ namespace Grpc.Testing {
if (ReferenceEquals(other, this)) {
return true;
}
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -398,11 +429,17 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -411,6 +448,7 @@ namespace Grpc.Testing {
if (other == null) {
return;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -419,7 +457,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
}
}
@@ -429,6 +467,7 @@ namespace Grpc.Testing {
public sealed partial class PayloadConfig : pb::IMessage<PayloadConfig> {
private static readonly pb::MessageParser<PayloadConfig> _parser = new pb::MessageParser<PayloadConfig>(() => new PayloadConfig());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<PayloadConfig> Parser { get { return _parser; } }
@@ -463,6 +502,7 @@ namespace Grpc.Testing {
break;
}
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -540,7 +580,7 @@ namespace Grpc.Testing {
if (!object.Equals(SimpleParams, other.SimpleParams)) return false;
if (!object.Equals(ComplexParams, other.ComplexParams)) return false;
if (PayloadCase != other.PayloadCase) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -550,6 +590,9 @@ namespace Grpc.Testing {
if (payloadCase_ == PayloadOneofCase.SimpleParams) hash ^= SimpleParams.GetHashCode();
if (payloadCase_ == PayloadOneofCase.ComplexParams) hash ^= ComplexParams.GetHashCode();
hash ^= (int) payloadCase_;
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -572,6 +615,9 @@ namespace Grpc.Testing {
output.WriteRawTag(26);
output.WriteMessage(ComplexParams);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -586,6 +632,9 @@ namespace Grpc.Testing {
if (payloadCase_ == PayloadOneofCase.ComplexParams) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(ComplexParams);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -615,6 +664,7 @@ namespace Grpc.Testing {
break;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -623,7 +673,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
global::Grpc.Testing.ByteBufferParams subBuilder = new global::Grpc.Testing.ByteBufferParams();
diff --git a/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioService.cs b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioService.cs
index b82cb52e30..707c443497 100644
--- a/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioService.cs
+++ b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioService.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
-// source: src/proto/grpc/testing/report_qps_scenario_service.proto
+// <auto-generated>
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: src/proto/grpc/testing/report_qps_scenario_service.proto
+// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
diff --git a/src/csharp/Grpc.IntegrationTesting/Stats.cs b/src/csharp/Grpc.IntegrationTesting/Stats.cs
index e082ae7719..8160646215 100644
--- a/src/csharp/Grpc.IntegrationTesting/Stats.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Stats.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
-// source: src/proto/grpc/testing/stats.proto
+// <auto-generated>
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: src/proto/grpc/testing/stats.proto
+// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
@@ -55,6 +57,7 @@ namespace Grpc.Testing {
#region Messages
public sealed partial class ServerStats : pb::IMessage<ServerStats> {
private static readonly pb::MessageParser<ServerStats> _parser = new pb::MessageParser<ServerStats>(() => new ServerStats());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ServerStats> Parser { get { return _parser; } }
@@ -84,6 +87,7 @@ namespace Grpc.Testing {
idleCpuTime_ = other.idleCpuTime_;
cqPollCount_ = other.cqPollCount_;
CoreStats = other.coreStats_ != null ? other.CoreStats.Clone() : null;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -203,26 +207,29 @@ namespace Grpc.Testing {
if (ReferenceEquals(other, this)) {
return true;
}
- if (TimeElapsed != other.TimeElapsed) return false;
- if (TimeUser != other.TimeUser) return false;
- if (TimeSystem != other.TimeSystem) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeElapsed, other.TimeElapsed)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeUser, other.TimeUser)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeSystem, other.TimeSystem)) return false;
if (TotalCpuTime != other.TotalCpuTime) return false;
if (IdleCpuTime != other.IdleCpuTime) return false;
if (CqPollCount != other.CqPollCount) return false;
if (!object.Equals(CoreStats, other.CoreStats)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
- if (TimeElapsed != 0D) hash ^= TimeElapsed.GetHashCode();
- if (TimeUser != 0D) hash ^= TimeUser.GetHashCode();
- if (TimeSystem != 0D) hash ^= TimeSystem.GetHashCode();
+ if (TimeElapsed != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeElapsed);
+ if (TimeUser != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeUser);
+ if (TimeSystem != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeSystem);
if (TotalCpuTime != 0UL) hash ^= TotalCpuTime.GetHashCode();
if (IdleCpuTime != 0UL) hash ^= IdleCpuTime.GetHashCode();
if (CqPollCount != 0UL) hash ^= CqPollCount.GetHashCode();
if (coreStats_ != null) hash ^= CoreStats.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -261,6 +268,9 @@ namespace Grpc.Testing {
output.WriteRawTag(58);
output.WriteMessage(CoreStats);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -287,6 +297,9 @@ namespace Grpc.Testing {
if (coreStats_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(CoreStats);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -319,6 +332,7 @@ namespace Grpc.Testing {
}
CoreStats.MergeFrom(other.CoreStats);
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -327,7 +341,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 9: {
TimeElapsed = input.ReadDouble();
@@ -371,6 +385,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class HistogramParams : pb::IMessage<HistogramParams> {
private static readonly pb::MessageParser<HistogramParams> _parser = new pb::MessageParser<HistogramParams>(() => new HistogramParams());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<HistogramParams> Parser { get { return _parser; } }
@@ -395,6 +410,7 @@ namespace Grpc.Testing {
public HistogramParams(HistogramParams other) : this() {
resolution_ = other.resolution_;
maxPossible_ = other.maxPossible_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -443,16 +459,19 @@ namespace Grpc.Testing {
if (ReferenceEquals(other, this)) {
return true;
}
- if (Resolution != other.Resolution) return false;
- if (MaxPossible != other.MaxPossible) return false;
- return true;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Resolution, other.Resolution)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(MaxPossible, other.MaxPossible)) return false;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
- if (Resolution != 0D) hash ^= Resolution.GetHashCode();
- if (MaxPossible != 0D) hash ^= MaxPossible.GetHashCode();
+ if (Resolution != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Resolution);
+ if (MaxPossible != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(MaxPossible);
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -471,6 +490,9 @@ namespace Grpc.Testing {
output.WriteRawTag(17);
output.WriteDouble(MaxPossible);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -482,6 +504,9 @@ namespace Grpc.Testing {
if (MaxPossible != 0D) {
size += 1 + 8;
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -496,6 +521,7 @@ namespace Grpc.Testing {
if (other.MaxPossible != 0D) {
MaxPossible = other.MaxPossible;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -504,7 +530,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 9: {
Resolution = input.ReadDouble();
@@ -525,6 +551,7 @@ namespace Grpc.Testing {
/// </summary>
public sealed partial class HistogramData : pb::IMessage<HistogramData> {
private static readonly pb::MessageParser<HistogramData> _parser = new pb::MessageParser<HistogramData>(() => new HistogramData());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<HistogramData> Parser { get { return _parser; } }
@@ -553,6 +580,7 @@ namespace Grpc.Testing {
sum_ = other.sum_;
sumOfSquares_ = other.sumOfSquares_;
count_ = other.count_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -639,23 +667,26 @@ namespace Grpc.Testing {
return true;
}
if(!bucket_.Equals(other.bucket_)) return false;
- if (MinSeen != other.MinSeen) return false;
- if (MaxSeen != other.MaxSeen) return false;
- if (Sum != other.Sum) return false;
- if (SumOfSquares != other.SumOfSquares) return false;
- if (Count != other.Count) return false;
- return true;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(MinSeen, other.MinSeen)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(MaxSeen, other.MaxSeen)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Sum, other.Sum)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(SumOfSquares, other.SumOfSquares)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Count, other.Count)) return false;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
hash ^= bucket_.GetHashCode();
- if (MinSeen != 0D) hash ^= MinSeen.GetHashCode();
- if (MaxSeen != 0D) hash ^= MaxSeen.GetHashCode();
- if (Sum != 0D) hash ^= Sum.GetHashCode();
- if (SumOfSquares != 0D) hash ^= SumOfSquares.GetHashCode();
- if (Count != 0D) hash ^= Count.GetHashCode();
+ if (MinSeen != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(MinSeen);
+ if (MaxSeen != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(MaxSeen);
+ if (Sum != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Sum);
+ if (SumOfSquares != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(SumOfSquares);
+ if (Count != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Count);
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -687,6 +718,9 @@ namespace Grpc.Testing {
output.WriteRawTag(49);
output.WriteDouble(Count);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -708,6 +742,9 @@ namespace Grpc.Testing {
if (Count != 0D) {
size += 1 + 8;
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -732,6 +769,7 @@ namespace Grpc.Testing {
if (other.Count != 0D) {
Count = other.Count;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -740,7 +778,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10:
case 8: {
@@ -775,6 +813,7 @@ namespace Grpc.Testing {
public sealed partial class RequestResultCount : pb::IMessage<RequestResultCount> {
private static readonly pb::MessageParser<RequestResultCount> _parser = new pb::MessageParser<RequestResultCount>(() => new RequestResultCount());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<RequestResultCount> Parser { get { return _parser; } }
@@ -799,6 +838,7 @@ namespace Grpc.Testing {
public RequestResultCount(RequestResultCount other) : this() {
statusCode_ = other.statusCode_;
count_ = other.count_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -843,7 +883,7 @@ namespace Grpc.Testing {
}
if (StatusCode != other.StatusCode) return false;
if (Count != other.Count) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -851,6 +891,9 @@ namespace Grpc.Testing {
int hash = 1;
if (StatusCode != 0) hash ^= StatusCode.GetHashCode();
if (Count != 0L) hash ^= Count.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -869,6 +912,9 @@ namespace Grpc.Testing {
output.WriteRawTag(16);
output.WriteInt64(Count);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -880,6 +926,9 @@ namespace Grpc.Testing {
if (Count != 0L) {
size += 1 + pb::CodedOutputStream.ComputeInt64Size(Count);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -894,6 +943,7 @@ namespace Grpc.Testing {
if (other.Count != 0L) {
Count = other.Count;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -902,7 +952,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
StatusCode = input.ReadInt32();
@@ -920,6 +970,7 @@ namespace Grpc.Testing {
public sealed partial class ClientStats : pb::IMessage<ClientStats> {
private static readonly pb::MessageParser<ClientStats> _parser = new pb::MessageParser<ClientStats>(() => new ClientStats());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ClientStats> Parser { get { return _parser; } }
@@ -949,6 +1000,7 @@ namespace Grpc.Testing {
requestResults_ = other.requestResults_.Clone();
cqPollCount_ = other.cqPollCount_;
CoreStats = other.coreStats_ != null ? other.CoreStats.Clone() : null;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1061,25 +1113,28 @@ namespace Grpc.Testing {
return true;
}
if (!object.Equals(Latencies, other.Latencies)) return false;
- if (TimeElapsed != other.TimeElapsed) return false;
- if (TimeUser != other.TimeUser) return false;
- if (TimeSystem != other.TimeSystem) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeElapsed, other.TimeElapsed)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeUser, other.TimeUser)) return false;
+ if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeSystem, other.TimeSystem)) return false;
if(!requestResults_.Equals(other.requestResults_)) return false;
if (CqPollCount != other.CqPollCount) return false;
if (!object.Equals(CoreStats, other.CoreStats)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (latencies_ != null) hash ^= Latencies.GetHashCode();
- if (TimeElapsed != 0D) hash ^= TimeElapsed.GetHashCode();
- if (TimeUser != 0D) hash ^= TimeUser.GetHashCode();
- if (TimeSystem != 0D) hash ^= TimeSystem.GetHashCode();
+ if (TimeElapsed != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeElapsed);
+ if (TimeUser != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeUser);
+ if (TimeSystem != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeSystem);
hash ^= requestResults_.GetHashCode();
if (CqPollCount != 0UL) hash ^= CqPollCount.GetHashCode();
if (coreStats_ != null) hash ^= CoreStats.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -1115,6 +1170,9 @@ namespace Grpc.Testing {
output.WriteRawTag(58);
output.WriteMessage(CoreStats);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1139,6 +1197,9 @@ namespace Grpc.Testing {
if (coreStats_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(CoreStats);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1172,6 +1233,7 @@ namespace Grpc.Testing {
}
CoreStats.MergeFrom(other.CoreStats);
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1180,7 +1242,7 @@ namespace Grpc.Testing {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
if (latencies_ == null) {
diff --git a/src/csharp/Grpc.IntegrationTesting/Test.cs b/src/csharp/Grpc.IntegrationTesting/Test.cs
index d2fa9f8013..03f92c7657 100644
--- a/src/csharp/Grpc.IntegrationTesting/Test.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Test.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
-// source: src/proto/grpc/testing/test.proto
+// <auto-generated>
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: src/proto/grpc/testing/test.proto
+// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
diff --git a/src/csharp/Grpc.IntegrationTesting/WorkerService.cs b/src/csharp/Grpc.IntegrationTesting/WorkerService.cs
index 7c829545aa..6de3193d82 100644
--- a/src/csharp/Grpc.IntegrationTesting/WorkerService.cs
+++ b/src/csharp/Grpc.IntegrationTesting/WorkerService.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
-// source: src/proto/grpc/testing/worker_service.proto
+// <auto-generated>
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: src/proto/grpc/testing/worker_service.proto
+// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
diff --git a/src/csharp/Grpc.Reflection/Reflection.cs b/src/csharp/Grpc.Reflection/Reflection.cs
index 60090e5364..84b2a0a842 100644
--- a/src/csharp/Grpc.Reflection/Reflection.cs
+++ b/src/csharp/Grpc.Reflection/Reflection.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
-// source: grpc/reflection/v1alpha/reflection.proto
+// <auto-generated>
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: grpc/reflection/v1alpha/reflection.proto
+// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
@@ -74,6 +76,7 @@ namespace Grpc.Reflection.V1Alpha {
/// </summary>
public sealed partial class ServerReflectionRequest : pb::IMessage<ServerReflectionRequest> {
private static readonly pb::MessageParser<ServerReflectionRequest> _parser = new pb::MessageParser<ServerReflectionRequest>(() => new ServerReflectionRequest());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ServerReflectionRequest> Parser { get { return _parser; } }
@@ -115,6 +118,7 @@ namespace Grpc.Reflection.V1Alpha {
break;
}
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -256,7 +260,7 @@ namespace Grpc.Reflection.V1Alpha {
if (AllExtensionNumbersOfType != other.AllExtensionNumbersOfType) return false;
if (ListServices != other.ListServices) return false;
if (MessageRequestCase != other.MessageRequestCase) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -269,6 +273,9 @@ namespace Grpc.Reflection.V1Alpha {
if (messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType) hash ^= AllExtensionNumbersOfType.GetHashCode();
if (messageRequestCase_ == MessageRequestOneofCase.ListServices) hash ^= ListServices.GetHashCode();
hash ^= (int) messageRequestCase_;
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -303,6 +310,9 @@ namespace Grpc.Reflection.V1Alpha {
output.WriteRawTag(58);
output.WriteString(ListServices);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -326,6 +336,9 @@ namespace Grpc.Reflection.V1Alpha {
if (messageRequestCase_ == MessageRequestOneofCase.ListServices) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(ListServices);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -358,6 +371,7 @@ namespace Grpc.Reflection.V1Alpha {
break;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -366,7 +380,7 @@ namespace Grpc.Reflection.V1Alpha {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Host = input.ReadString();
@@ -409,6 +423,7 @@ namespace Grpc.Reflection.V1Alpha {
/// </summary>
public sealed partial class ExtensionRequest : pb::IMessage<ExtensionRequest> {
private static readonly pb::MessageParser<ExtensionRequest> _parser = new pb::MessageParser<ExtensionRequest>(() => new ExtensionRequest());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ExtensionRequest> Parser { get { return _parser; } }
@@ -433,6 +448,7 @@ namespace Grpc.Reflection.V1Alpha {
public ExtensionRequest(ExtensionRequest other) : this() {
containingType_ = other.containingType_;
extensionNumber_ = other.extensionNumber_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -480,7 +496,7 @@ namespace Grpc.Reflection.V1Alpha {
}
if (ContainingType != other.ContainingType) return false;
if (ExtensionNumber != other.ExtensionNumber) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -488,6 +504,9 @@ namespace Grpc.Reflection.V1Alpha {
int hash = 1;
if (ContainingType.Length != 0) hash ^= ContainingType.GetHashCode();
if (ExtensionNumber != 0) hash ^= ExtensionNumber.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -506,6 +525,9 @@ namespace Grpc.Reflection.V1Alpha {
output.WriteRawTag(16);
output.WriteInt32(ExtensionNumber);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -517,6 +539,9 @@ namespace Grpc.Reflection.V1Alpha {
if (ExtensionNumber != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(ExtensionNumber);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -531,6 +556,7 @@ namespace Grpc.Reflection.V1Alpha {
if (other.ExtensionNumber != 0) {
ExtensionNumber = other.ExtensionNumber;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -539,7 +565,7 @@ namespace Grpc.Reflection.V1Alpha {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
ContainingType = input.ReadString();
@@ -560,6 +586,7 @@ namespace Grpc.Reflection.V1Alpha {
/// </summary>
public sealed partial class ServerReflectionResponse : pb::IMessage<ServerReflectionResponse> {
private static readonly pb::MessageParser<ServerReflectionResponse> _parser = new pb::MessageParser<ServerReflectionResponse>(() => new ServerReflectionResponse());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ServerReflectionResponse> Parser { get { return _parser; } }
@@ -599,6 +626,7 @@ namespace Grpc.Reflection.V1Alpha {
break;
}
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -730,7 +758,7 @@ namespace Grpc.Reflection.V1Alpha {
if (!object.Equals(ListServicesResponse, other.ListServicesResponse)) return false;
if (!object.Equals(ErrorResponse, other.ErrorResponse)) return false;
if (MessageResponseCase != other.MessageResponseCase) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -743,6 +771,9 @@ namespace Grpc.Reflection.V1Alpha {
if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) hash ^= ListServicesResponse.GetHashCode();
if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) hash ^= ErrorResponse.GetHashCode();
hash ^= (int) messageResponseCase_;
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -777,6 +808,9 @@ namespace Grpc.Reflection.V1Alpha {
output.WriteRawTag(58);
output.WriteMessage(ErrorResponse);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -800,6 +834,9 @@ namespace Grpc.Reflection.V1Alpha {
if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(ErrorResponse);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -844,6 +881,7 @@ namespace Grpc.Reflection.V1Alpha {
break;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -852,7 +890,7 @@ namespace Grpc.Reflection.V1Alpha {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
ValidHost = input.ReadString();
@@ -914,6 +952,7 @@ namespace Grpc.Reflection.V1Alpha {
/// </summary>
public sealed partial class FileDescriptorResponse : pb::IMessage<FileDescriptorResponse> {
private static readonly pb::MessageParser<FileDescriptorResponse> _parser = new pb::MessageParser<FileDescriptorResponse>(() => new FileDescriptorResponse());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<FileDescriptorResponse> Parser { get { return _parser; } }
@@ -937,6 +976,7 @@ namespace Grpc.Reflection.V1Alpha {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public FileDescriptorResponse(FileDescriptorResponse other) : this() {
fileDescriptorProto_ = other.fileDescriptorProto_.Clone();
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -973,13 +1013,16 @@ namespace Grpc.Reflection.V1Alpha {
return true;
}
if(!fileDescriptorProto_.Equals(other.fileDescriptorProto_)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
hash ^= fileDescriptorProto_.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -991,12 +1034,18 @@ namespace Grpc.Reflection.V1Alpha {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
fileDescriptorProto_.WriteTo(output, _repeated_fileDescriptorProto_codec);
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
size += fileDescriptorProto_.CalculateSize(_repeated_fileDescriptorProto_codec);
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1006,6 +1055,7 @@ namespace Grpc.Reflection.V1Alpha {
return;
}
fileDescriptorProto_.Add(other.fileDescriptorProto_);
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1014,7 +1064,7 @@ namespace Grpc.Reflection.V1Alpha {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
fileDescriptorProto_.AddEntriesFrom(input, _repeated_fileDescriptorProto_codec);
@@ -1032,6 +1082,7 @@ namespace Grpc.Reflection.V1Alpha {
/// </summary>
public sealed partial class ExtensionNumberResponse : pb::IMessage<ExtensionNumberResponse> {
private static readonly pb::MessageParser<ExtensionNumberResponse> _parser = new pb::MessageParser<ExtensionNumberResponse>(() => new ExtensionNumberResponse());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ExtensionNumberResponse> Parser { get { return _parser; } }
@@ -1056,6 +1107,7 @@ namespace Grpc.Reflection.V1Alpha {
public ExtensionNumberResponse(ExtensionNumberResponse other) : this() {
baseTypeName_ = other.baseTypeName_;
extensionNumber_ = other.extensionNumber_.Clone();
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1103,7 +1155,7 @@ namespace Grpc.Reflection.V1Alpha {
}
if (BaseTypeName != other.BaseTypeName) return false;
if(!extensionNumber_.Equals(other.extensionNumber_)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1111,6 +1163,9 @@ namespace Grpc.Reflection.V1Alpha {
int hash = 1;
if (BaseTypeName.Length != 0) hash ^= BaseTypeName.GetHashCode();
hash ^= extensionNumber_.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -1126,6 +1181,9 @@ namespace Grpc.Reflection.V1Alpha {
output.WriteString(BaseTypeName);
}
extensionNumber_.WriteTo(output, _repeated_extensionNumber_codec);
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1135,6 +1193,9 @@ namespace Grpc.Reflection.V1Alpha {
size += 1 + pb::CodedOutputStream.ComputeStringSize(BaseTypeName);
}
size += extensionNumber_.CalculateSize(_repeated_extensionNumber_codec);
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1147,6 +1208,7 @@ namespace Grpc.Reflection.V1Alpha {
BaseTypeName = other.BaseTypeName;
}
extensionNumber_.Add(other.extensionNumber_);
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1155,7 +1217,7 @@ namespace Grpc.Reflection.V1Alpha {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
BaseTypeName = input.ReadString();
@@ -1177,6 +1239,7 @@ namespace Grpc.Reflection.V1Alpha {
/// </summary>
public sealed partial class ListServiceResponse : pb::IMessage<ListServiceResponse> {
private static readonly pb::MessageParser<ListServiceResponse> _parser = new pb::MessageParser<ListServiceResponse>(() => new ListServiceResponse());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ListServiceResponse> Parser { get { return _parser; } }
@@ -1200,6 +1263,7 @@ namespace Grpc.Reflection.V1Alpha {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ListServiceResponse(ListServiceResponse other) : this() {
service_ = other.service_.Clone();
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1235,13 +1299,16 @@ namespace Grpc.Reflection.V1Alpha {
return true;
}
if(!service_.Equals(other.service_)) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
hash ^= service_.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -1253,12 +1320,18 @@ namespace Grpc.Reflection.V1Alpha {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
service_.WriteTo(output, _repeated_service_codec);
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
size += service_.CalculateSize(_repeated_service_codec);
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1268,6 +1341,7 @@ namespace Grpc.Reflection.V1Alpha {
return;
}
service_.Add(other.service_);
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1276,7 +1350,7 @@ namespace Grpc.Reflection.V1Alpha {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
service_.AddEntriesFrom(input, _repeated_service_codec);
@@ -1294,6 +1368,7 @@ namespace Grpc.Reflection.V1Alpha {
/// </summary>
public sealed partial class ServiceResponse : pb::IMessage<ServiceResponse> {
private static readonly pb::MessageParser<ServiceResponse> _parser = new pb::MessageParser<ServiceResponse>(() => new ServiceResponse());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ServiceResponse> Parser { get { return _parser; } }
@@ -1317,6 +1392,7 @@ namespace Grpc.Reflection.V1Alpha {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ServiceResponse(ServiceResponse other) : this() {
name_ = other.name_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1353,13 +1429,16 @@ namespace Grpc.Reflection.V1Alpha {
return true;
}
if (Name != other.Name) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Name.Length != 0) hash ^= Name.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -1374,6 +1453,9 @@ namespace Grpc.Reflection.V1Alpha {
output.WriteRawTag(10);
output.WriteString(Name);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1382,6 +1464,9 @@ namespace Grpc.Reflection.V1Alpha {
if (Name.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1393,6 +1478,7 @@ namespace Grpc.Reflection.V1Alpha {
if (other.Name.Length != 0) {
Name = other.Name;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1401,7 +1487,7 @@ namespace Grpc.Reflection.V1Alpha {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Name = input.ReadString();
@@ -1418,6 +1504,7 @@ namespace Grpc.Reflection.V1Alpha {
/// </summary>
public sealed partial class ErrorResponse : pb::IMessage<ErrorResponse> {
private static readonly pb::MessageParser<ErrorResponse> _parser = new pb::MessageParser<ErrorResponse>(() => new ErrorResponse());
+ private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ErrorResponse> Parser { get { return _parser; } }
@@ -1442,6 +1529,7 @@ namespace Grpc.Reflection.V1Alpha {
public ErrorResponse(ErrorResponse other) : this() {
errorCode_ = other.errorCode_;
errorMessage_ = other.errorMessage_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1489,7 +1577,7 @@ namespace Grpc.Reflection.V1Alpha {
}
if (ErrorCode != other.ErrorCode) return false;
if (ErrorMessage != other.ErrorMessage) return false;
- return true;
+ return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1497,6 +1585,9 @@ namespace Grpc.Reflection.V1Alpha {
int hash = 1;
if (ErrorCode != 0) hash ^= ErrorCode.GetHashCode();
if (ErrorMessage.Length != 0) hash ^= ErrorMessage.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
return hash;
}
@@ -1515,6 +1606,9 @@ namespace Grpc.Reflection.V1Alpha {
output.WriteRawTag(18);
output.WriteString(ErrorMessage);
}
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1526,6 +1620,9 @@ namespace Grpc.Reflection.V1Alpha {
if (ErrorMessage.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(ErrorMessage);
}
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
return size;
}
@@ -1540,6 +1637,7 @@ namespace Grpc.Reflection.V1Alpha {
if (other.ErrorMessage.Length != 0) {
ErrorMessage = other.ErrorMessage;
}
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1548,7 +1646,7 @@ namespace Grpc.Reflection.V1Alpha {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
- input.SkipLastField();
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
ErrorCode = input.ReadInt32();
diff --git a/src/csharp/README.md b/src/csharp/README.md
index 6821ad225e..e117e66afd 100644
--- a/src/csharp/README.md
+++ b/src/csharp/README.md
@@ -16,16 +16,17 @@ PREREQUISITES
When using gRPC C# under .NET Core you only need to [install .NET Core](https://www.microsoft.com/net/core).
-- Windows: .NET Framework 4.5+, Visual Studio 2013, 2015, 2017
-- Linux: Mono 4+, MonoDevelop 5.9+ (with NuGet add-in installed)
-- Mac OS X: Xamarin Studio 5.9+
+In addition to that, you can also use gRPC C# with these runtimes / IDEs
+- Windows: .NET Framework 4.5+, Visual Studio 2013, 2015, 2017, Visual Studio Code
+- Linux: Mono 4+, Visual Studio Code, MonoDevelop 5.9+
+- Mac OS X: Mono 4+, Visual Studio Code, Xamarin Studio 5.9+
HOW TO USE
--------------
**Windows, Linux, Mac OS X**
-- Open Visual Studio / MonoDevelop / Xamarin Studio and start a new project/solution.
+- Open Visual Studio / MonoDevelop / Xamarin Studio and start a new project/solution (alternatively, you can create a new project from command line with `dotnet` SDK)
- Add the [Grpc](https://www.nuget.org/packages/Grpc/) NuGet package as a dependency (Project options -> Manage NuGet Packages).
@@ -37,12 +38,23 @@ BUILD FROM SOURCE
You only need to go through these steps if you are planning to develop gRPC C#.
If you are a user of gRPC C#, go to Usage section above.
+**Prerequisites for contributors**
+
+- [dotnet SDK](https://www.microsoft.com/net/core)
+- [Mono 4+](https://www.mono-project.com/) (only needed for Linux and MacOS)
+- Prerequisites mentioned in [INSTALL.md](../../INSTALL.md#pre-requisites)
+ to be able to compile the native code.
+
**Windows, Linux or Mac OS X**
-- The easiest way to build is using the `run_tests.py` script that will take care of building the `grpc_csharp_ext` native library:
+- The easiest way to build is using the `run_tests.py` script that will take care of building the `grpc_csharp_ext` native library.
+
```
+ # NOTE: make sure all necessary git submodules with dependencies
+ # are available by running "git submodule update --init"
+
# from the gRPC repository root
- $ python tools/run_tests/run_tests.py -c dbg -l csharp --build_only
+ $ python tools/run_tests/run_tests.py -l csharp -c dbg --build_only
```
- Use Visual Studio 2017 (on Windows) to open the solution `Grpc.sln` or use Visual Studio Code with C# extension (on Linux and Mac). gRPC C# code has been migrated to
@@ -57,11 +69,12 @@ gRPC C# is using NUnit as the testing framework.
Under Visual Studio, make sure NUnit test adapter is installed (under "Extensions and Updates").
Then you should be able to run all the tests using Test Explorer.
-gRPC team uses a Python script to simplify facilitate running tests for
+gRPC team uses a Python script to facilitate running tests for
different languages.
```
-tools/run_tests/run_tests.py -l csharp
+# from the gRPC repository root
+$ python tools/run_tests/run_tests.py -l csharp -c dbg
```
DOCUMENTATION
diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat
index 0d65748697..924d7b1697 100755
--- a/src/csharp/build_packages_dotnetcli.bat
+++ b/src/csharp/build_packages_dotnetcli.bat
@@ -13,7 +13,7 @@
@rem limitations under the License.
@rem Current package versions
-set VERSION=1.12.0-dev
+set VERSION=1.13.0-dev
@rem Adjust the location of nuget.exe
set NUGET=C:\nuget\nuget.exe
diff --git a/src/csharp/build_packages_dotnetcli.sh b/src/csharp/build_packages_dotnetcli.sh
index 66aba36089..5c73a8f95f 100755
--- a/src/csharp/build_packages_dotnetcli.sh
+++ b/src/csharp/build_packages_dotnetcli.sh
@@ -45,7 +45,7 @@ dotnet pack --configuration Release Grpc.Auth --output ../../../artifacts
dotnet pack --configuration Release Grpc.HealthCheck --output ../../../artifacts
dotnet pack --configuration Release Grpc.Reflection --output ../../../artifacts
-nuget pack Grpc.nuspec -Version "1.12.0-dev" -OutputDirectory ../../artifacts
-nuget pack Grpc.Tools.nuspec -Version "1.12.0-dev" -OutputDirectory ../../artifacts
+nuget pack Grpc.nuspec -Version "1.13.0-dev" -OutputDirectory ../../artifacts
+nuget pack Grpc.Tools.nuspec -Version "1.13.0-dev" -OutputDirectory ../../artifacts
(cd ../../artifacts && zip csharp_nugets_dotnetcli.zip *.nupkg)
diff --git a/src/csharp/experimental/build_native_ext_for_android.sh b/src/csharp/experimental/build_native_ext_for_android.sh
index 958778e929..8197df7c53 100755
--- a/src/csharp/experimental/build_native_ext_for_android.sh
+++ b/src/csharp/experimental/build_native_ext_for_android.sh
@@ -23,7 +23,7 @@ mkdir -p build
cd build
# set to the location where Android SDK is installed
-ANDROID_NDK_PATH="$HOME/android-ndk-r16b"
+# e.g. ANDROID_NDK_PATH="$HOME/android-ndk-r16b"
cmake ../.. \
-DCMAKE_SYSTEM_NAME=Android \
diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
index f06312bea9..515dc917d1 100644
--- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
+++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
@@ -42,7 +42,7 @@ Pod::Spec.new do |s|
# exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
# before them.
s.name = '!ProtoCompiler-gRPCPlugin'
- v = '1.12.0-dev'
+ v = '1.13.0-dev'
s.version = v
s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.'
s.description = <<-DESC
diff --git a/src/objective-c/BoringSSL.podspec b/src/objective-c/BoringSSL.podspec
index 8a32e9735d..5741a1ac39 100644
--- a/src/objective-c/BoringSSL.podspec
+++ b/src/objective-c/BoringSSL.podspec
@@ -31,7 +31,7 @@
Pod::Spec.new do |s|
s.name = 'BoringSSL'
- version = '10.0'
+ version = '10.0.3'
s.version = version
s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google’s needs.'
# Adapted from the homepage:
@@ -67,11 +67,9 @@ Pod::Spec.new do |s|
# "The name and email addresses of the library maintainers, not the Podspec maintainer."
s.authors = 'Adam Langley', 'David Benjamin', 'Matt Braithwaite'
- versions = version.split('.')
- major_version = versions[0] + '.0'
s.source = {
- :git => 'https://boringssl.googlesource.com/boringssl',
- :tag => "version_for_cocoapods_#{major_version}",
+ :git => 'https://github.com/google/boringssl.git',
+ :commit => "a20bb7ff8bb5057065a2e7941249773f9676cf45",
}
s.ios.deployment_target = '5.0'
@@ -123,7 +121,8 @@ Pod::Spec.new do |s|
'ssl/**/*.{h,cc}',
'*.{h,c}',
'crypto/*.{h,c}',
- 'crypto/**/*.{h,c}'
+ 'crypto/**/*.{h,c}',
+ 'third_party/fiat/*.{h,c}'
ss.private_header_files = 'ssl/*.h',
'ssl/**/*.h',
'*.h',
diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m
index a49a489ea8..b1f6ea270e 100644
--- a/src/objective-c/GRPCClient/private/GRPCChannel.m
+++ b/src/objective-c/GRPCClient/private/GRPCChannel.m
@@ -56,6 +56,7 @@ static void FreeChannelArgs(grpc_channel_args *channel_args) {
gpr_free(arg->value.string);
}
}
+ gpr_free(channel_args->args);
gpr_free(channel_args);
}
diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m
index bfb1fd352c..c3ea9afc37 100644
--- a/src/objective-c/GRPCClient/private/GRPCHost.m
+++ b/src/objective-c/GRPCClient/private/GRPCHost.m
@@ -50,6 +50,7 @@ static NSMutableDictionary *kHostCache;
if (_channelCreds != nil) {
grpc_channel_credentials_release(_channelCreds);
}
+ [GRPCConnectivityMonitor unregisterObserver:self];
}
// Default initializer.
@@ -278,7 +279,7 @@ static NSMutableDictionary *kHostCache;
// and Cellular data, so that a new call will use a new channel. Otherwise, a new call will still
// use the cached channel which is no longer available and will cause gRPC to hang.
- (void)connectivityChange:(NSNotification *)note {
- [GRPCHost flushChannelCache];
+ [self disconnect];
}
@end
diff --git a/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m
index af1ce0bf23..730a1436e4 100644
--- a/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m
+++ b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m
@@ -54,7 +54,7 @@
+ (instancetype)grpc_stringFromMetadataValue:(grpc_metadata *)metadata {
return [[self alloc] initWithBytes:GRPC_SLICE_START_PTR(metadata->value)
length:GRPC_SLICE_LENGTH(metadata->value)
- encoding:NSASCIIStringEncoding];
+ encoding:NSUTF8StringEncoding];
}
// Precondition: This object contains only ASCII characters.
diff --git a/src/objective-c/GRPCClient/private/NSError+GRPC.m b/src/objective-c/GRPCClient/private/NSError+GRPC.m
index 74cfa943cc..c2e65e4d8a 100644
--- a/src/objective-c/GRPCClient/private/NSError+GRPC.m
+++ b/src/objective-c/GRPCClient/private/NSError+GRPC.m
@@ -27,7 +27,7 @@ NSString *const kGRPCErrorDomain = @"io.grpc";
if (statusCode == GRPC_STATUS_OK) {
return nil;
}
- NSString *message = [NSString stringWithCString:details encoding:NSASCIIStringEncoding];
+ NSString *message = [NSString stringWithCString:details encoding:NSUTF8StringEncoding];
return [NSError errorWithDomain:kGRPCErrorDomain
code:statusCode
userInfo:@{NSLocalizedDescriptionKey : message}];
diff --git a/src/objective-c/GRPCClient/private/version.h b/src/objective-c/GRPCClient/private/version.h
index 1298e7e191..6fe4a7d051 100644
--- a/src/objective-c/GRPCClient/private/version.h
+++ b/src/objective-c/GRPCClient/private/version.h
@@ -22,4 +22,4 @@
// instead. This file can be regenerated from the template by running
// `tools/buildgen/generate_projects.sh`.
-#define GRPC_OBJC_VERSION_STRING @"1.12.0-dev"
+#define GRPC_OBJC_VERSION_STRING @"1.13.0-dev"
diff --git a/src/objective-c/tests/version.h b/src/objective-c/tests/version.h
index d36545fced..e9637099d9 100644
--- a/src/objective-c/tests/version.h
+++ b/src/objective-c/tests/version.h
@@ -22,5 +22,5 @@
// instead. This file can be regenerated from the template by running
// `tools/buildgen/generate_projects.sh`.
-#define GRPC_OBJC_VERSION_STRING @"1.12.0-dev"
+#define GRPC_OBJC_VERSION_STRING @"1.13.0-dev"
#define GRPC_C_VERSION_STRING @"6.0.0-dev"
diff --git a/src/php/bin/run_tests.sh b/src/php/bin/run_tests.sh
index b913166ca2..295bcb2430 100755
--- a/src/php/bin/run_tests.sh
+++ b/src/php/bin/run_tests.sh
@@ -23,4 +23,8 @@ source ./determine_extension_dir.sh
# in some jenkins macos machine, somehow the PHP build script can't find libgrpc.dylib
export DYLD_LIBRARY_PATH=$root/libs/$CONFIG
php $extension_dir -d max_execution_time=300 $(which phpunit) -v --debug \
- ../tests/unit_tests
+ --exclude-group persistent_list_bound_tests ../tests/unit_tests
+
+php $extension_dir -d max_execution_time=300 $(which phpunit) -v --debug \
+ ../tests/unit_tests/PersistentChannelTests
+
diff --git a/src/php/composer.json b/src/php/composer.json
index 57d911db79..03dffb40ab 100644
--- a/src/php/composer.json
+++ b/src/php/composer.json
@@ -2,7 +2,7 @@
"name": "grpc/grpc-dev",
"description": "gRPC library for PHP - for Developement use only",
"license": "Apache-2.0",
- "version": "1.12.0",
+ "version": "1.13.0",
"require": {
"php": ">=5.5.0",
"google/protobuf": "^v3.3.0"
diff --git a/src/php/ext/grpc/byte_buffer.c b/src/php/ext/grpc/byte_buffer.c
index 810cc81151..9c9a6fc3a0 100644
--- a/src/php/ext/grpc/byte_buffer.c
+++ b/src/php/ext/grpc/byte_buffer.c
@@ -16,23 +16,13 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include <php.h>
-#include <php_ini.h>
-#include <ext/standard/info.h>
-#include <ext/spl/spl_exceptions.h>
-#include "php_grpc.h"
-
-#include <string.h>
+// The include file must place here under <php.h> for fixing compile error.
+// See: https://github.com/grpc/grpc/pull/12360#issuecomment-326484589
#include "byte_buffer.h"
-#include <grpc/grpc.h>
#include <grpc/byte_buffer_reader.h>
-#include <grpc/slice.h>
grpc_byte_buffer *string_to_byte_buffer(char *string, size_t length) {
grpc_slice slice = grpc_slice_from_copied_buffer(string, length);
diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c
index b802f04f53..a794226298 100644
--- a/src/php/ext/grpc/call.c
+++ b/src/php/ext/grpc/call.c
@@ -18,34 +18,19 @@
#include "call.h"
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <php.h>
-#include <php_ini.h>
-#include <ext/standard/info.h>
#include <ext/spl/spl_exceptions.h>
-#include "php_grpc.h"
-#include "call_credentials.h"
-
#include <zend_exceptions.h>
-#include <zend_hash.h>
-
-#include <stdbool.h>
#include <grpc/support/alloc.h>
-#include <grpc/grpc.h>
+#include "call_credentials.h"
#include "completion_queue.h"
#include "timeval.h"
#include "channel.h"
#include "byte_buffer.h"
zend_class_entry *grpc_ce_call;
-#if PHP_MAJOR_VERSION >= 7
-static zend_object_handlers call_ce_handlers;
-#endif
+PHP_GRPC_DECLARE_OBJECT_HANDLER(call_ce_handlers)
/* Frees and destroys an instance of wrapped_grpc_call */
PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_call)
@@ -195,7 +180,8 @@ zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned TSRMLS_DC) {
zval *call_object;
PHP_GRPC_MAKE_STD_ZVAL(call_object);
object_init_ex(call_object, grpc_ce_call);
- wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(call_object);
+ wrapped_grpc_call *call = PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_call,
+ call_object);
call->wrapped = wrapped;
call->owned = owned;
return call_object;
@@ -216,7 +202,8 @@ PHP_METHOD(Call, __construct) {
zval *deadline_obj;
char *host_override = NULL;
php_grpc_int host_override_len = 0;
- wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis());
+ wrapped_grpc_call *call = PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_call,
+ getThis());
/* "OsO|s" == 1 Object, 1 string, 1 Object, 1 optional string */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OsO|s", &channel_obj,
@@ -228,9 +215,10 @@ PHP_METHOD(Call, __construct) {
"an optional String", 1 TSRMLS_CC);
return;
}
- wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(channel_obj);
+ wrapped_grpc_channel *channel =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel, channel_obj);
gpr_mu_lock(&channel->wrapper->mu);
- if (channel->wrapper->wrapped == NULL) {
+ if (channel->wrapper == NULL || channel->wrapper->wrapped == NULL) {
zend_throw_exception(spl_ce_InvalidArgumentException,
"Call cannot be constructed from a closed Channel",
1 TSRMLS_CC);
@@ -238,7 +226,8 @@ PHP_METHOD(Call, __construct) {
return;
}
add_property_zval(getThis(), "channel", channel_obj);
- wrapped_grpc_timeval *deadline = Z_WRAPPED_GRPC_TIMEVAL_P(deadline_obj);
+ wrapped_grpc_timeval *deadline =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, deadline_obj);
grpc_slice method_slice = grpc_slice_from_copied_string(method);
grpc_slice host_slice = host_override != NULL ?
grpc_slice_from_copied_string(host_override) : grpc_empty_slice();
@@ -251,6 +240,7 @@ PHP_METHOD(Call, __construct) {
grpc_slice_unref(method_slice);
grpc_slice_unref(host_slice);
call->owned = true;
+ call->channel = channel;
gpr_mu_unlock(&channel->wrapper->mu);
}
@@ -269,7 +259,17 @@ PHP_METHOD(Call, startBatch) {
zval *inner_value;
zval *message_value;
zval *message_flags;
- wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis());
+ wrapped_grpc_call *call = PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_call,
+ getThis());
+ if (call->channel) {
+ // startBatch in gRPC PHP server doesn't have channel in it.
+ if (call->channel->wrapper == NULL ||
+ call->channel->wrapper->wrapped == NULL) {
+ zend_throw_exception(spl_ce_RuntimeException,
+ "startBatch Error. Channel is closed",
+ 1 TSRMLS_CC);
+ }
+ }
grpc_op ops[8];
size_t op_num = 0;
@@ -542,7 +542,8 @@ cleanup:
* @return string The URI of the endpoint
*/
PHP_METHOD(Call, getPeer) {
- wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis());
+ wrapped_grpc_call *call = PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_call,
+ getThis());
char *peer = grpc_call_get_peer(call->wrapped);
PHP_GRPC_RETVAL_STRING(peer, 1);
gpr_free(peer);
@@ -554,7 +555,8 @@ PHP_METHOD(Call, getPeer) {
* @return void
*/
PHP_METHOD(Call, cancel) {
- wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis());
+ wrapped_grpc_call *call = PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_call,
+ getThis());
grpc_call_cancel(call->wrapped, NULL);
}
@@ -576,8 +578,9 @@ PHP_METHOD(Call, setCredentials) {
}
wrapped_grpc_call_credentials *creds =
- Z_WRAPPED_GRPC_CALL_CREDS_P(creds_obj);
- wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis());
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_call_credentials, creds_obj);
+ wrapped_grpc_call *call = PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_call,
+ getThis());
grpc_call_error error = GRPC_CALL_ERROR;
error = grpc_call_set_credentials(call->wrapped, creds->wrapped);
diff --git a/src/php/ext/grpc/call.h b/src/php/ext/grpc/call.h
index 104ac301c1..7abc8fa0e8 100644
--- a/src/php/ext/grpc/call.h
+++ b/src/php/ext/grpc/call.h
@@ -19,16 +19,9 @@
#ifndef NET_GRPC_PHP_GRPC_CALL_H_
#define NET_GRPC_PHP_GRPC_CALL_H_
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <php.h>
-#include <php_ini.h>
-#include <ext/standard/info.h>
#include "php_grpc.h"
-#include <grpc/grpc.h>
+#include "channel.h"
/* Class entry for the Call PHP class */
extern zend_class_entry *grpc_ce_call;
@@ -37,25 +30,15 @@ extern zend_class_entry *grpc_ce_call;
PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_call)
bool owned;
grpc_call *wrapped;
+ wrapped_grpc_channel* channel;
PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_call)
-#if PHP_MAJOR_VERSION < 7
-
-#define Z_WRAPPED_GRPC_CALL_P(zv) \
- (wrapped_grpc_call *)zend_object_store_get_object(zv TSRMLS_CC)
-
-#else
-
static inline wrapped_grpc_call
*wrapped_grpc_call_from_obj(zend_object *obj) {
return (wrapped_grpc_call*)((char*)(obj) -
XtOffsetOf(wrapped_grpc_call, std));
}
-#define Z_WRAPPED_GRPC_CALL_P(zv) wrapped_grpc_call_from_obj(Z_OBJ_P((zv)))
-
-#endif /* PHP_MAJOR_VERSION */
-
/* Creates and returns a PHP associative array of metadata from a C array of
* call metadata */
zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array TSRMLS_DC);
diff --git a/src/php/ext/grpc/call_credentials.c b/src/php/ext/grpc/call_credentials.c
index d96dc7f3b7..fabb12a751 100644
--- a/src/php/ext/grpc/call_credentials.c
+++ b/src/php/ext/grpc/call_credentials.c
@@ -16,32 +16,18 @@
*
*/
-#include "channel_credentials.h"
#include "call_credentials.h"
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <php.h>
-#include <php_ini.h>
-#include <ext/standard/info.h>
#include <ext/spl/spl_exceptions.h>
-#include "php_grpc.h"
-#include "call.h"
-
#include <zend_exceptions.h>
-#include <zend_hash.h>
-#include <grpc/grpc.h>
-#include <grpc/grpc_security.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
+#include "call.h"
+
zend_class_entry *grpc_ce_call_credentials;
-#if PHP_MAJOR_VERSION >= 7
-static zend_object_handlers call_credentials_ce_handlers;
-#endif
+PHP_GRPC_DECLARE_OBJECT_HANDLER(call_credentials_ce_handlers)
/* Frees and destroys an instance of wrapped_grpc_call_credentials */
PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_call_credentials)
@@ -67,7 +53,8 @@ zval *grpc_php_wrap_call_credentials(grpc_call_credentials
PHP_GRPC_MAKE_STD_ZVAL(credentials_object);
object_init_ex(credentials_object, grpc_ce_call_credentials);
wrapped_grpc_call_credentials *credentials =
- Z_WRAPPED_GRPC_CALL_CREDS_P(credentials_object);
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_call_credentials,
+ credentials_object);
credentials->wrapped = wrapped;
return credentials_object;
}
@@ -92,12 +79,12 @@ PHP_METHOD(CallCredentials, createComposite) {
return;
}
wrapped_grpc_call_credentials *cred1 =
- Z_WRAPPED_GRPC_CALL_CREDS_P(cred1_obj);
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_call_credentials, cred1_obj);
wrapped_grpc_call_credentials *cred2 =
- Z_WRAPPED_GRPC_CALL_CREDS_P(cred2_obj);
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_call_credentials, cred2_obj);
grpc_call_credentials *creds =
- grpc_composite_call_credentials_create(cred1->wrapped, cred2->wrapped,
- NULL);
+ grpc_composite_call_credentials_create(cred1->wrapped, cred2->wrapped,
+ NULL);
zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC);
RETURN_DESTROY_ZVAL(creds_object);
}
diff --git a/src/php/ext/grpc/call_credentials.h b/src/php/ext/grpc/call_credentials.h
index 663cc6858d..e0cc863853 100644
--- a/src/php/ext/grpc/call_credentials.h
+++ b/src/php/ext/grpc/call_credentials.h
@@ -19,17 +19,9 @@
#ifndef NET_GRPC_PHP_GRPC_CALL_CREDENTIALS_H_
#define NET_GRPC_PHP_GRPC_CALL_CREDENTIALS_H_
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php.h"
-#include "php_ini.h"
-#include "ext/standard/info.h"
#include "php_grpc.h"
-#include "grpc/grpc.h"
-#include "grpc/grpc_security.h"
+#include <grpc/grpc_security.h>
/* Class entry for the CallCredentials PHP class */
extern zend_class_entry *grpc_ce_call_credentials;
@@ -40,24 +32,12 @@ PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_call_credentials)
grpc_call_credentials *wrapped;
PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_call_credentials)
-#if PHP_MAJOR_VERSION < 7
-
-#define Z_WRAPPED_GRPC_CALL_CREDS_P(zv) \
- (wrapped_grpc_call_credentials *)zend_object_store_get_object(zv TSRMLS_CC)
-
-#else
-
static inline wrapped_grpc_call_credentials
*wrapped_grpc_call_credentials_from_obj(zend_object *obj) {
return (wrapped_grpc_call_credentials*)(
(char*)(obj) - XtOffsetOf(wrapped_grpc_call_credentials, std));
}
-#define Z_WRAPPED_GRPC_CALL_CREDS_P(zv) \
- wrapped_grpc_call_credentials_from_obj(Z_OBJ_P((zv)))
-
-#endif /* PHP_MAJOR_VERSION */
-
/* Struct to hold callback function for plugin creds API */
typedef struct plugin_state {
zend_fcall_info *fci;
diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c
index f3a03ace09..b17f3d9a61 100644
--- a/src/php/ext/grpc/channel.c
+++ b/src/php/ext/grpc/channel.c
@@ -18,13 +18,6 @@
#include "channel.h"
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <php.h>
-#include <php_ini.h>
-#include <ext/standard/info.h>
#include <ext/standard/php_var.h>
#include <ext/standard/sha1.h>
#if PHP_MAJOR_VERSION < 7
@@ -33,68 +26,64 @@
#include <zend_smart_str.h>
#endif
#include <ext/spl/spl_exceptions.h>
-#include "php_grpc.h"
-
#include <zend_exceptions.h>
-#include <stdbool.h>
-
-#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/support/alloc.h>
#include "completion_queue.h"
#include "channel_credentials.h"
-#include "server.h"
#include "timeval.h"
zend_class_entry *grpc_ce_channel;
-#if PHP_MAJOR_VERSION >= 7
-static zend_object_handlers channel_ce_handlers;
-#endif
+PHP_GRPC_DECLARE_OBJECT_HANDLER(channel_ce_handlers)
static gpr_mu global_persistent_list_mu;
int le_plink;
+int le_bound;
extern HashTable grpc_persistent_list;
+extern HashTable grpc_target_upper_bound_map;
+
+void free_grpc_channel_wrapper(grpc_channel_wrapper* channel, bool free_channel) {
+ if (free_channel) {
+ grpc_channel_destroy(channel->wrapped);
+ channel->wrapped = NULL;
+ }
+ free(channel->target);
+ free(channel->args_hashstr);
+ free(channel->creds_hashstr);
+ free(channel->key);
+ channel->target = NULL;
+ channel->args_hashstr = NULL;
+ channel->creds_hashstr = NULL;
+ channel->key = NULL;
+}
+
+void php_grpc_channel_ref(grpc_channel_wrapper* wrapper) {
+ gpr_mu_lock(&wrapper->mu);
+ wrapper->ref_count += 1;
+ gpr_mu_unlock(&wrapper->mu);
+}
+
+void php_grpc_channel_unref(grpc_channel_wrapper* wrapper) {
+ gpr_mu_lock(&wrapper->mu);
+ wrapper->ref_count -= 1;
+ if (wrapper->ref_count == 0) {
+ free_grpc_channel_wrapper(wrapper, true);
+ gpr_mu_unlock(&wrapper->mu);
+ free(wrapper);
+ wrapper = NULL;
+ return;
+ }
+ gpr_mu_unlock(&wrapper->mu);
+}
/* Frees and destroys an instance of wrapped_grpc_channel */
PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_channel)
// In_persistent_list is used when the user don't close the channel,
// In this case, channels not in the list should be freed.
- bool in_persistent_list = true;
if (p->wrapper != NULL) {
- gpr_mu_lock(&p->wrapper->mu);
- if (p->wrapper->wrapped != NULL) {
- if (p->wrapper->is_valid) {
- php_grpc_zend_resource *rsrc;
- php_grpc_int key_len = strlen(p->wrapper->key);
- // only destroy the channel here if not found in the persistent list
- gpr_mu_lock(&global_persistent_list_mu);
- if (!(PHP_GRPC_PERSISTENT_LIST_FIND(&grpc_persistent_list, p->wrapper->key,
- key_len, rsrc))) {
- in_persistent_list = false;
- grpc_channel_destroy(p->wrapper->wrapped);
- free(p->wrapper->target);
- free(p->wrapper->args_hashstr);
- if (p->wrapper->creds_hashstr != NULL) {
- free(p->wrapper->creds_hashstr);
- p->wrapper->creds_hashstr = NULL;
- }
- free(p->wrapper->key);
- p->wrapper->wrapped = NULL;
- p->wrapper->target = NULL;
- p->wrapper->args_hashstr = NULL;
- p->wrapper->key = NULL;
- }
- gpr_mu_unlock(&global_persistent_list_mu);
- }
- }
- p->wrapper->ref_count -= 1;
- gpr_mu_unlock(&p->wrapper->mu);
- if (!in_persistent_list) {
- gpr_mu_destroy(&p->wrapper->mu);
- free(p->wrapper);
- p->wrapper = NULL;
- }
+ php_grpc_channel_unref(p->wrapper);
+ p->wrapper = NULL;
}
PHP_GRPC_FREE_WRAPPED_FUNC_END()
@@ -162,6 +151,67 @@ void generate_sha1_str(char *sha1str, char *str, php_grpc_int len) {
make_sha1_digest(sha1str, digest);
}
+bool php_grpc_persistent_list_delete_unused_channel(
+ char* target,
+ target_bound_le_t* target_bound_status TSRMLS_DC) {
+ zval *data;
+ PHP_GRPC_HASH_FOREACH_VAL_START(&grpc_persistent_list, data)
+ php_grpc_zend_resource *rsrc = (php_grpc_zend_resource*) PHP_GRPC_HASH_VALPTR_TO_VAL(data)
+ if (rsrc == NULL) {
+ break;
+ }
+ channel_persistent_le_t* le = rsrc->ptr;
+ // Find the channel sharing the same target.
+ if (strcmp(le->channel->target, target) == 0) {
+ // ref_count=1 means that only the map holds the reference to the channel.
+ if (le->channel->ref_count == 1) {
+ php_grpc_delete_persistent_list_entry(le->channel->key,
+ strlen(le->channel->key)
+ TSRMLS_CC);
+ target_bound_status->current_count -= 1;
+ if (target_bound_status->current_count < target_bound_status->upper_bound) {
+ return true;
+ }
+ }
+ }
+ PHP_GRPC_HASH_FOREACH_END()
+ return false;
+}
+
+target_bound_le_t* update_and_get_target_upper_bound(char* target, int bound) {
+ php_grpc_zend_resource *rsrc;
+ target_bound_le_t* target_bound_status;
+ php_grpc_int key_len = strlen(target);
+ if (!(PHP_GRPC_PERSISTENT_LIST_FIND(&grpc_target_upper_bound_map, target,
+ key_len, rsrc))) {
+ // Target is not not persisted.
+ php_grpc_zend_resource new_rsrc;
+ target_bound_status = malloc(sizeof(target_bound_le_t));
+ if (bound == -1) {
+ // If the bound is not set, use 1 as default.s
+ bound = 1;
+ }
+ target_bound_status->upper_bound = bound;
+ // Init current_count with 1. It should be add 1 when the channel is successfully
+ // created and minus 1 when it is removed from the persistent list.
+ target_bound_status->current_count = 0;
+ new_rsrc.type = le_bound;
+ new_rsrc.ptr = target_bound_status;
+ gpr_mu_lock(&global_persistent_list_mu);
+ PHP_GRPC_PERSISTENT_LIST_UPDATE(&grpc_target_upper_bound_map,
+ target, key_len, (void *)&new_rsrc);
+ gpr_mu_unlock(&global_persistent_list_mu);
+ } else {
+ // The target already in the map recording the upper bound.
+ // If no newer bound set, use the original now.
+ target_bound_status = (target_bound_le_t *)rsrc->ptr;
+ if (bound != -1) {
+ target_bound_status->upper_bound = bound;
+ }
+ }
+ return target_bound_status;
+}
+
void create_channel(
wrapped_grpc_channel *channel,
char *target,
@@ -174,6 +224,8 @@ void create_channel(
channel->wrapper->wrapped =
grpc_secure_channel_create(creds->wrapped, target, &args, NULL);
}
+ // There is an Grpc\Channel object refer to it.
+ php_grpc_channel_ref(channel->wrapper);
efree(args.args);
}
@@ -183,7 +235,28 @@ void create_and_add_channel_to_persistent_list(
grpc_channel_args args,
wrapped_grpc_channel_credentials *creds,
char *key,
- php_grpc_int key_len TSRMLS_DC) {
+ php_grpc_int key_len,
+ int target_upper_bound TSRMLS_DC) {
+ target_bound_le_t* target_bound_status =
+ update_and_get_target_upper_bound(target, target_upper_bound);
+ // Check the upper bound status before inserting to the persistent map.
+ if (target_bound_status->current_count >=
+ target_bound_status->upper_bound) {
+ if (!php_grpc_persistent_list_delete_unused_channel(
+ target, target_bound_status TSRMLS_CC)) {
+ // If no channel can be deleted from the persistent map,
+ // do not persist this one.
+ create_channel(channel, target, args, creds);
+ php_printf("[Warning] The number of channel for the"
+ " target %s is maxed out bounded.\n", target);
+ php_printf("[Warning] Target upper bound: %d. Current size: %d.\n",
+ target_bound_status->upper_bound,
+ target_bound_status->current_count);
+ php_printf("[Warning] Target %s will not be persisted.\n", target);
+ return;
+ }
+ }
+ // There is space in the persistent map.
php_grpc_zend_resource new_rsrc;
channel_persistent_le_t *le;
// this links each persistent list entry to a destructor
@@ -191,13 +264,15 @@ void create_and_add_channel_to_persistent_list(
le = malloc(sizeof(channel_persistent_le_t));
create_channel(channel, target, args, creds);
+ target_bound_status->current_count += 1;
le->channel = channel->wrapper;
- le->ref_count = 1;
new_rsrc.ptr = le;
gpr_mu_lock(&global_persistent_list_mu);
PHP_GRPC_PERSISTENT_LIST_UPDATE(&grpc_persistent_list, key, key_len,
(void *)&new_rsrc);
+ // Persistent map refer to it.
+ php_grpc_channel_ref(channel->wrapper);
gpr_mu_unlock(&global_persistent_list_mu);
}
@@ -220,7 +295,8 @@ void create_and_add_channel_to_persistent_list(
* @param array $args_array The arguments to pass to the Channel
*/
PHP_METHOD(Channel, __construct) {
- wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
+ wrapped_grpc_channel *channel =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel, getThis());
zval *creds_obj = NULL;
char *target;
php_grpc_int target_length;
@@ -231,6 +307,7 @@ PHP_METHOD(Channel, __construct) {
php_grpc_zend_resource *rsrc;
bool force_new = false;
zval *force_new_obj = NULL;
+ int target_upper_bound = -1;
/* "sa" == 1 string, 1 array */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa", &target,
@@ -252,7 +329,8 @@ PHP_METHOD(Channel, __construct) {
1 TSRMLS_CC);
return;
} else {
- creds = Z_WRAPPED_GRPC_CHANNEL_CREDS_P(creds_obj);
+ creds = PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel_credentials,
+ creds_obj);
php_grpc_zend_hash_del(array_hash, "credentials", sizeof("credentials"));
}
}
@@ -264,6 +342,19 @@ PHP_METHOD(Channel, __construct) {
php_grpc_zend_hash_del(array_hash, "force_new", sizeof("force_new"));
}
+ if (php_grpc_zend_hash_find(array_hash, "grpc_target_persist_bound",
+ sizeof("grpc_target_persist_bound"),
+ (void **)&force_new_obj) == SUCCESS) {
+ if (Z_TYPE_P(force_new_obj) != IS_LONG) {
+ zend_throw_exception(spl_ce_InvalidArgumentException,
+ "plist_bound must be a number",
+ 1 TSRMLS_CC);
+ }
+ target_upper_bound = (int)Z_LVAL_P(force_new_obj);
+ php_grpc_zend_hash_del(array_hash, "grpc_target_persist_bound",
+ sizeof("grpc_target_persist_bound"));
+ }
+
// parse the rest of the channel args array
if (php_grpc_read_args_array(args_array, &args TSRMLS_CC) == FAILURE) {
efree(args.args);
@@ -297,12 +388,11 @@ PHP_METHOD(Channel, __construct) {
strcat(key, creds->hashstr);
}
channel->wrapper = malloc(sizeof(grpc_channel_wrapper));
+ channel->wrapper->ref_count = 0;
channel->wrapper->key = key;
channel->wrapper->target = strdup(target);
channel->wrapper->args_hashstr = strdup(sha1str);
channel->wrapper->creds_hashstr = NULL;
- channel->wrapper->ref_count = 1;
- channel->wrapper->is_valid = true;
if (creds != NULL && creds->hashstr != NULL) {
php_grpc_int creds_hashstr_len = strlen(creds->hashstr);
char *channel_creds_hashstr = malloc(creds_hashstr_len + 1);
@@ -320,7 +410,7 @@ PHP_METHOD(Channel, __construct) {
} else if (!(PHP_GRPC_PERSISTENT_LIST_FIND(&grpc_persistent_list, key,
key_len, rsrc))) {
create_and_add_channel_to_persistent_list(
- channel, target, args, creds, key, key_len TSRMLS_CC);
+ channel, target, args, creds, key, key_len, target_upper_bound TSRMLS_CC);
} else {
// Found a previously stored channel in the persistent list
channel_persistent_le_t *le = (channel_persistent_le_t *)rsrc->ptr;
@@ -330,21 +420,17 @@ PHP_METHOD(Channel, __construct) {
strcmp(creds->hashstr, le->channel->creds_hashstr) != 0)) {
// somehow hash collision
create_and_add_channel_to_persistent_list(
- channel, target, args, creds, key, key_len TSRMLS_CC);
+ channel, target, args, creds, key, key_len, target_upper_bound TSRMLS_CC);
} else {
efree(args.args);
- if (channel->wrapper->creds_hashstr != NULL) {
- free(channel->wrapper->creds_hashstr);
- channel->wrapper->creds_hashstr = NULL;
- }
- free(channel->wrapper->creds_hashstr);
- free(channel->wrapper->key);
- free(channel->wrapper->target);
- free(channel->wrapper->args_hashstr);
+ free_grpc_channel_wrapper(channel->wrapper, false);
+ gpr_mu_destroy(&channel->wrapper->mu);
free(channel->wrapper);
- le->ref_count += 1;
+ channel->wrapper = NULL;
channel->wrapper = le->channel;
- channel->wrapper->ref_count += 1;
+ // One more Grpc\Channel object refer to it.
+ php_grpc_channel_ref(channel->wrapper);
+ update_and_get_target_upper_bound(target, target_upper_bound);
}
}
}
@@ -354,14 +440,15 @@ PHP_METHOD(Channel, __construct) {
* @return string The URI of the endpoint
*/
PHP_METHOD(Channel, getTarget) {
- wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
- gpr_mu_lock(&channel->wrapper->mu);
- if (channel->wrapper->wrapped == NULL) {
+ wrapped_grpc_channel *channel =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel, getThis());
+ if (channel->wrapper == NULL) {
zend_throw_exception(spl_ce_RuntimeException,
- "Channel already closed", 1 TSRMLS_CC);
- gpr_mu_unlock(&channel->wrapper->mu);
+ "getTarget error."
+ "Channel is already closed.", 1 TSRMLS_CC);
return;
}
+ gpr_mu_lock(&channel->wrapper->mu);
char *target = grpc_channel_get_target(channel->wrapper->wrapped);
gpr_mu_unlock(&channel->wrapper->mu);
PHP_GRPC_RETVAL_STRING(target, 1);
@@ -374,17 +461,16 @@ PHP_METHOD(Channel, getTarget) {
* @return long The grpc connectivity state
*/
PHP_METHOD(Channel, getConnectivityState) {
- wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
- gpr_mu_lock(&channel->wrapper->mu);
- if (channel->wrapper->wrapped == NULL) {
+ wrapped_grpc_channel *channel =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel, getThis());
+ if (channel->wrapper == NULL) {
zend_throw_exception(spl_ce_RuntimeException,
- "Channel already closed", 1 TSRMLS_CC);
- gpr_mu_unlock(&channel->wrapper->mu);
+ "getConnectivityState error."
+ "Channel is already closed.", 1 TSRMLS_CC);
return;
}
-
+ gpr_mu_lock(&channel->wrapper->mu);
bool try_to_connect = false;
-
/* "|b" == 1 optional bool */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &try_to_connect)
== FAILURE) {
@@ -395,11 +481,6 @@ PHP_METHOD(Channel, getConnectivityState) {
}
int state = grpc_channel_check_connectivity_state(channel->wrapper->wrapped,
(int)try_to_connect);
- // this can happen if another shared Channel object close the underlying
- // channel
- if (state == GRPC_CHANNEL_SHUTDOWN) {
- channel->wrapper->wrapped = NULL;
- }
gpr_mu_unlock(&channel->wrapper->mu);
RETURN_LONG(state);
}
@@ -412,15 +493,15 @@ PHP_METHOD(Channel, getConnectivityState) {
* before deadline
*/
PHP_METHOD(Channel, watchConnectivityState) {
- wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
- gpr_mu_lock(&channel->wrapper->mu);
- if (channel->wrapper->wrapped == NULL) {
+ wrapped_grpc_channel *channel =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel, getThis());
+ if (channel->wrapper == NULL) {
zend_throw_exception(spl_ce_RuntimeException,
- "Channel already closed", 1 TSRMLS_CC);
- gpr_mu_unlock(&channel->wrapper->mu);
+ "watchConnectivityState error"
+ "Channel is already closed.", 1 TSRMLS_CC);
return;
}
-
+ gpr_mu_lock(&channel->wrapper->mu);
php_grpc_long last_state;
zval *deadline_obj;
@@ -435,7 +516,8 @@ PHP_METHOD(Channel, watchConnectivityState) {
return;
}
- wrapped_grpc_timeval *deadline = Z_WRAPPED_GRPC_TIMEVAL_P(deadline_obj);
+ wrapped_grpc_timeval *deadline =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, deadline_obj);
grpc_channel_watch_connectivity_state(channel->wrapper->wrapped,
(grpc_connectivity_state)last_state,
deadline->wrapped, completion_queue,
@@ -452,47 +534,12 @@ PHP_METHOD(Channel, watchConnectivityState) {
* @return void
*/
PHP_METHOD(Channel, close) {
- wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
- bool is_last_wrapper = false;
+ wrapped_grpc_channel *channel =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel, getThis());
if (channel->wrapper != NULL) {
- // Channel_wrapper hasn't call close before.
- gpr_mu_lock(&channel->wrapper->mu);
- if (channel->wrapper->wrapped != NULL) {
- if (channel->wrapper->is_valid) {
- // Wrapped channel hasn't been destoryed by other wrapper.
- grpc_channel_destroy(channel->wrapper->wrapped);
- free(channel->wrapper->target);
- free(channel->wrapper->args_hashstr);
- free(channel->wrapper->creds_hashstr);
- channel->wrapper->creds_hashstr = NULL;
- channel->wrapper->target = NULL;
- channel->wrapper->args_hashstr = NULL;
- channel->wrapper->wrapped = NULL;
- channel->wrapper->is_valid = false;
-
- php_grpc_delete_persistent_list_entry(channel->wrapper->key,
- strlen(channel->wrapper->key)
- TSRMLS_CC);
- }
- }
- channel->wrapper->ref_count -= 1;
- if (channel->wrapper->ref_count == 0) {
- // Mark that the wrapper can be freed because mu should be
- // destroyed outside the lock.
- is_last_wrapper = true;
- }
- gpr_mu_unlock(&channel->wrapper->mu);
- }
- gpr_mu_lock(&global_persistent_list_mu);
- if (is_last_wrapper) {
- gpr_mu_destroy(&channel->wrapper->mu);
- free(channel->wrapper->key);
- free(channel->wrapper);
+ php_grpc_channel_unref(channel->wrapper);
+ channel->wrapper = NULL;
}
- // Set channel->wrapper to NULL to avoid call close twice for the same
- // channel.
- channel->wrapper = NULL;
- gpr_mu_unlock(&global_persistent_list_mu);
}
// Delete an entry from the persistent list
@@ -503,11 +550,7 @@ void php_grpc_delete_persistent_list_entry(char *key, php_grpc_int key_len
gpr_mu_lock(&global_persistent_list_mu);
if (PHP_GRPC_PERSISTENT_LIST_FIND(&grpc_persistent_list, key,
key_len, rsrc)) {
- channel_persistent_le_t *le;
- le = (channel_persistent_le_t *)rsrc->ptr;
- le->channel = NULL;
php_grpc_zend_hash_del(&grpc_persistent_list, key, key_len+1);
- free(le);
}
gpr_mu_unlock(&global_persistent_list_mu);
}
@@ -520,32 +563,93 @@ static void php_grpc_channel_plink_dtor(php_grpc_zend_resource *rsrc
return;
}
if (le->channel != NULL) {
- gpr_mu_lock(&le->channel->mu);
- if (le->channel->wrapped != NULL) {
- grpc_channel_destroy(le->channel->wrapped);
- free(le->channel->args_hashstr);
- le->channel->wrapped = NULL;
- le->channel->target = NULL;
- le->channel->args_hashstr = NULL;
- free(le->channel->key);
- le->channel->key = NULL;
- }
- gpr_mu_unlock(&le->channel->mu);
+ php_grpc_channel_unref(le->channel);
+ le->channel = NULL;
+ }
+ free(le);
+ le = NULL;
+}
+
+// A destructor associated with each list entry from the target_bound map
+static void php_grpc_target_bound_dtor(php_grpc_zend_resource *rsrc
+ TSRMLS_DC) {
+ target_bound_le_t *le = (target_bound_le_t *) rsrc->ptr;
+ if (le == NULL) {
+ return;
}
+ free(le);
+ le = NULL;
}
+#ifdef GRPC_PHP_DEBUG
+
/**
- * Clean all channels in the persistent.
- * @return void
- */
+* Clean all channels in the persistent. Test only.
+* @return void
+*/
PHP_METHOD(Channel, cleanPersistentList) {
zend_hash_clean(&grpc_persistent_list);
+ zend_hash_clean(&grpc_target_upper_bound_map);
+}
+
+char *grpc_connectivity_state_name(grpc_connectivity_state state) {
+ switch (state) {
+ case GRPC_CHANNEL_IDLE:
+ return "IDLE";
+ case GRPC_CHANNEL_CONNECTING:
+ return "CONNECTING";
+ case GRPC_CHANNEL_READY:
+ return "READY";
+ case GRPC_CHANNEL_TRANSIENT_FAILURE:
+ return "TRANSIENT_FAILURE";
+ case GRPC_CHANNEL_SHUTDOWN:
+ return "SHUTDOWN";
+ }
+ return "UNKNOWN";
}
/**
- * Return an array of persistent list.
- * @return array
- */
+* Return the info about the current channel. Test only.
+* @return array
+*/
+PHP_METHOD(Channel, getChannelInfo) {
+ wrapped_grpc_channel *channel =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel, getThis());
+ array_init(return_value);
+ // Info about the target
+ PHP_GRPC_ADD_STRING_TO_ARRAY(return_value, "target",
+ sizeof("target"), channel->wrapper->target, true);
+ // Info about the upper bound for the target
+ target_bound_le_t* target_bound_status =
+ update_and_get_target_upper_bound(channel->wrapper->target, -1);
+ PHP_GRPC_ADD_LONG_TO_ARRAY(return_value, "target_upper_bound",
+ sizeof("target_upper_bound"), target_bound_status->upper_bound);
+ PHP_GRPC_ADD_LONG_TO_ARRAY(return_value, "target_current_size",
+ sizeof("target_current_size"), target_bound_status->current_count);
+ // Info about key
+ PHP_GRPC_ADD_STRING_TO_ARRAY(return_value, "key",
+ sizeof("key"), channel->wrapper->key, true);
+ // Info about persistent channel ref_count
+ PHP_GRPC_ADD_LONG_TO_ARRAY(return_value, "ref_count",
+ sizeof("ref_count"), channel->wrapper->ref_count);
+ // Info about connectivity status
+ int state =
+ grpc_channel_check_connectivity_state(channel->wrapper->wrapped, (int)0);
+ // It should be set to 'true' in PHP 5.6.33
+ PHP_GRPC_ADD_LONG_TO_ARRAY(return_value, "connectivity_status",
+ sizeof("connectivity_status"), state);
+ PHP_GRPC_ADD_STRING_TO_ARRAY(return_value, "ob",
+ sizeof("ob"),
+ grpc_connectivity_state_name(state), true);
+ // Info about the channel is closed or not
+ PHP_GRPC_ADD_BOOL_TO_ARRAY(return_value, "is_valid",
+ sizeof("is_valid"), (channel->wrapper == NULL));
+}
+
+/**
+* Return an array of all channels in the persistent list. Test only.
+* @return array
+*/
PHP_METHOD(Channel, getPersistentList) {
array_init(return_value);
zval *data;
@@ -562,24 +666,34 @@ PHP_METHOD(Channel, getPersistentList) {
// Info about the target
PHP_GRPC_ADD_STRING_TO_ARRAY(ret_arr, "target",
sizeof("target"), le->channel->target, true);
+ // Info about the upper bound for the target
+ target_bound_le_t* target_bound_status =
+ update_and_get_target_upper_bound(le->channel->target, -1);
+ PHP_GRPC_ADD_LONG_TO_ARRAY(ret_arr, "target_upper_bound",
+ sizeof("target_upper_bound"), target_bound_status->upper_bound);
+ PHP_GRPC_ADD_LONG_TO_ARRAY(ret_arr, "target_current_size",
+ sizeof("target_current_size"), target_bound_status->current_count);
// Info about key
PHP_GRPC_ADD_STRING_TO_ARRAY(ret_arr, "key",
sizeof("key"), le->channel->key, true);
// Info about persistent channel ref_count
PHP_GRPC_ADD_LONG_TO_ARRAY(ret_arr, "ref_count",
- sizeof("ref_count"), le->ref_count);
+ sizeof("ref_count"), le->channel->ref_count);
// Info about connectivity status
int state =
grpc_channel_check_connectivity_state(le->channel->wrapped, (int)0);
// It should be set to 'true' in PHP 5.6.33
PHP_GRPC_ADD_LONG_TO_ARRAY(ret_arr, "connectivity_status",
sizeof("connectivity_status"), state);
- // Info about the channel is closed or not
- PHP_GRPC_ADD_BOOL_TO_ARRAY(ret_arr, "is_valid",
- sizeof("is_valid"), le->channel->is_valid);
- add_assoc_zval(return_value, le->channel->target, ret_arr);
+ PHP_GRPC_ADD_STRING_TO_ARRAY(ret_arr, "ob",
+ sizeof("ob"),
+ grpc_connectivity_state_name(state), true);
+ add_assoc_zval(return_value, le->channel->key, ret_arr);
+ PHP_GRPC_FREE_STD_ZVAL(ret_arr);
PHP_GRPC_HASH_FOREACH_END()
}
+#endif
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 2)
ZEND_ARG_INFO(0, target)
@@ -601,11 +715,17 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_close, 0, 0, 0)
ZEND_END_ARG_INFO()
+#ifdef GRPC_PHP_DEBUG
+ZEND_BEGIN_ARG_INFO_EX(arginfo_getChannelInfo, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_cleanPersistentList, 0, 0, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_getPersistentList, 0, 0, 0)
ZEND_END_ARG_INFO()
+#endif
+
static zend_function_entry channel_methods[] = {
PHP_ME(Channel, __construct, arginfo_construct,
@@ -618,10 +738,14 @@ static zend_function_entry channel_methods[] = {
ZEND_ACC_PUBLIC)
PHP_ME(Channel, close, arginfo_close,
ZEND_ACC_PUBLIC)
+ #ifdef GRPC_PHP_DEBUG
+ PHP_ME(Channel, getChannelInfo, arginfo_getChannelInfo,
+ ZEND_ACC_PUBLIC)
PHP_ME(Channel, cleanPersistentList, arginfo_cleanPersistentList,
ZEND_ACC_PUBLIC)
PHP_ME(Channel, getPersistentList, arginfo_getPersistentList,
ZEND_ACC_PUBLIC)
+ #endif
PHP_FE_END
};
@@ -635,6 +759,12 @@ GRPC_STARTUP_FUNCTION(channel) {
NULL, php_grpc_channel_plink_dtor, "Persistent Channel", module_number);
zend_hash_init_ex(&grpc_persistent_list, 20, NULL,
EG(persistent_list).pDestructor, 1, 0);
+ // Register the target->upper_bound map.
+ le_bound = zend_register_list_destructors_ex(
+ NULL, php_grpc_target_bound_dtor, "Target Bound", module_number);
+ zend_hash_init_ex(&grpc_target_upper_bound_map, 20, NULL,
+ EG(persistent_list).pDestructor, 1, 0);
+
PHP_GRPC_INIT_HANDLER(wrapped_grpc_channel, channel_ce_handlers);
return SUCCESS;
}
diff --git a/src/php/ext/grpc/channel.h b/src/php/ext/grpc/channel.h
index 807880534e..27752c9a3f 100644
--- a/src/php/ext/grpc/channel.h
+++ b/src/php/ext/grpc/channel.h
@@ -19,17 +19,8 @@
#ifndef NET_GRPC_PHP_GRPC_CHANNEL_H_
#define NET_GRPC_PHP_GRPC_CHANNEL_H_
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <php.h>
-#include <php_ini.h>
-#include <ext/standard/info.h>
#include "php_grpc.h"
-#include <grpc/grpc.h>
-
/* Class entry for the PHP Channel class */
extern zend_class_entry *grpc_ce_channel;
@@ -39,12 +30,8 @@ typedef struct _grpc_channel_wrapper {
char *target;
char *args_hashstr;
char *creds_hashstr;
- gpr_mu mu;
- // is_valid is used to check the wrapped channel has been freed
- // before to avoid double free.
- bool is_valid;
- // ref_count is used to let the last wrapper free related channel and key.
size_t ref_count;
+ gpr_mu mu;
} grpc_channel_wrapper;
/* Wrapper struct for grpc_channel that can be associated with a PHP object */
@@ -52,24 +39,12 @@ PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_channel)
grpc_channel_wrapper *wrapper;
PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_channel)
-#if PHP_MAJOR_VERSION < 7
-
-#define Z_WRAPPED_GRPC_CHANNEL_P(zv) \
- (wrapped_grpc_channel *)zend_object_store_get_object(zv TSRMLS_CC)
-
-#else
-
static inline wrapped_grpc_channel
*wrapped_grpc_channel_from_obj(zend_object *obj) {
return (wrapped_grpc_channel*)((char*)(obj) -
XtOffsetOf(wrapped_grpc_channel, std));
}
-#define Z_WRAPPED_GRPC_CHANNEL_P(zv) \
- wrapped_grpc_channel_from_obj(Z_OBJ_P((zv)))
-
-#endif /* PHP_MAJOR_VERSION */
-
/* Initializes the Channel class */
GRPC_STARTUP_FUNCTION(channel);
@@ -84,8 +59,11 @@ void php_grpc_delete_persistent_list_entry(char *key, php_grpc_int key_len
typedef struct _channel_persistent_le {
grpc_channel_wrapper *channel;
- size_t ref_count;
} channel_persistent_le_t;
+typedef struct _target_bound_le {
+ int upper_bound;
+ int current_count;
+} target_bound_le_t;
#endif /* NET_GRPC_PHP_GRPC_CHANNEL_H_ */
diff --git a/src/php/ext/grpc/channel_credentials.c b/src/php/ext/grpc/channel_credentials.c
index 624d7cc75c..10d7380ca1 100644
--- a/src/php/ext/grpc/channel_credentials.c
+++ b/src/php/ext/grpc/channel_credentials.c
@@ -17,32 +17,19 @@
*/
#include "channel_credentials.h"
-#include "call_credentials.h"
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <php.h>
-#include <php_ini.h>
-#include <ext/standard/info.h>
#include <ext/standard/sha1.h>
#include <ext/spl/spl_exceptions.h>
-#include "channel.h"
-#include "php_grpc.h"
-
#include <zend_exceptions.h>
-#include <zend_hash.h>
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
-#include <grpc/grpc.h>
-#include <grpc/grpc_security.h>
+
+#include "call_credentials.h"
+#include "channel.h"
zend_class_entry *grpc_ce_channel_credentials;
-#if PHP_MAJOR_VERSION >= 7
-static zend_object_handlers channel_credentials_ce_handlers;
-#endif
+PHP_GRPC_DECLARE_OBJECT_HANDLER(channel_credentials_ce_handlers)
static char *default_pem_root_certs = NULL;
static grpc_ssl_roots_override_result get_ssl_roots_override(
@@ -85,7 +72,8 @@ zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped,
PHP_GRPC_MAKE_STD_ZVAL(credentials_object);
object_init_ex(credentials_object, grpc_ce_channel_credentials);
wrapped_grpc_channel_credentials *credentials =
- Z_WRAPPED_GRPC_CHANNEL_CREDS_P(credentials_object);
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel_credentials,
+ credentials_object);
credentials->wrapped = wrapped;
credentials->hashstr = hashstr;
credentials->has_call_creds = has_call_creds;
@@ -198,20 +186,19 @@ PHP_METHOD(ChannelCredentials, createComposite) {
return;
}
wrapped_grpc_channel_credentials *cred1 =
- Z_WRAPPED_GRPC_CHANNEL_CREDS_P(cred1_obj);
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel_credentials, cred1_obj);
wrapped_grpc_call_credentials *cred2 =
- Z_WRAPPED_GRPC_CALL_CREDS_P(cred2_obj);
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_call_credentials, cred2_obj);
grpc_channel_credentials *creds =
- grpc_composite_channel_credentials_create(cred1->wrapped, cred2->wrapped,
- NULL);
+ grpc_composite_channel_credentials_create(cred1->wrapped, cred2->wrapped,
+ NULL);
// wrapped_grpc_channel_credentials object should keeps it's own
// allocation. Otherwise it conflicts free hashstr with call.c.
php_grpc_int cred1_len = strlen(cred1->hashstr);
char *cred1_hashstr = malloc(cred1_len+1);
strcpy(cred1_hashstr, cred1->hashstr);
zval *creds_object =
- grpc_php_wrap_channel_credentials(creds, cred1_hashstr, true
- TSRMLS_CC);
+ grpc_php_wrap_channel_credentials(creds, cred1_hashstr, true TSRMLS_CC);
RETURN_DESTROY_ZVAL(creds_object);
}
diff --git a/src/php/ext/grpc/channel_credentials.h b/src/php/ext/grpc/channel_credentials.h
index 357d732642..7c6cf30367 100644
--- a/src/php/ext/grpc/channel_credentials.h
+++ b/src/php/ext/grpc/channel_credentials.h
@@ -19,17 +19,9 @@
#ifndef NET_GRPC_PHP_GRPC_CHANNEL_CREDENTIALS_H_
#define NET_GRPC_PHP_GRPC_CHANNEL_CREDENTIALS_H_
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php.h"
-#include "php_ini.h"
-#include "ext/standard/info.h"
#include "php_grpc.h"
-#include "grpc/grpc.h"
-#include "grpc/grpc_security.h"
+#include <grpc/grpc_security.h>
/* Class entry for the ChannelCredentials PHP class */
extern zend_class_entry *grpc_ce_channel_credentials;
@@ -42,24 +34,12 @@ PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_channel_credentials)
zend_bool has_call_creds;
PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_channel_credentials)
-#if PHP_MAJOR_VERSION < 7
-
-#define Z_WRAPPED_GRPC_CHANNEL_CREDS_P(zv) \
- (wrapped_grpc_channel_credentials *)zend_object_store_get_object(zv TSRMLS_CC)
-
-#else
-
static inline wrapped_grpc_channel_credentials
*wrapped_grpc_channel_credentials_from_obj(zend_object *obj) {
return (wrapped_grpc_channel_credentials *)(
(char*)(obj) - XtOffsetOf(wrapped_grpc_channel_credentials, std));
}
-#define Z_WRAPPED_GRPC_CHANNEL_CREDS_P(zv) \
- wrapped_grpc_channel_credentials_from_obj(Z_OBJ_P((zv)))
-
-#endif /* PHP_MAJOR_VERSION */
-
/* Initializes the ChannelCredentials PHP class */
void grpc_init_channel_credentials(TSRMLS_D);
diff --git a/src/php/ext/grpc/completion_queue.c b/src/php/ext/grpc/completion_queue.c
index f54089b3a0..e7a2fa6d2a 100644
--- a/src/php/ext/grpc/completion_queue.c
+++ b/src/php/ext/grpc/completion_queue.c
@@ -18,8 +18,6 @@
#include "completion_queue.h"
-#include <php.h>
-
grpc_completion_queue *completion_queue;
void grpc_php_init_completion_queue(TSRMLS_D) {
diff --git a/src/php/ext/grpc/config.m4 b/src/php/ext/grpc/config.m4
index 0fb843d51f..fa54ebd920 100755
--- a/src/php/ext/grpc/config.m4
+++ b/src/php/ext/grpc/config.m4
@@ -4,6 +4,14 @@ PHP_ARG_ENABLE(grpc, whether to enable grpc support,
PHP_ARG_ENABLE(coverage, whether to include code coverage symbols,
[ --enable-coverage Enable coverage support], no, no)
+PHP_ARG_ENABLE(tests, whether to compile helper methods for tests,
+[ --enable-tests Enable tests methods], no, no)
+
+dnl Check whether to enable tests
+if test "$PHP_TESTS" != "no"; then
+ CPPFLAGS="$CPPFLAGS -DGRPC_PHP_DEBUG"
+fi
+
if test "$PHP_GRPC" != "no"; then
dnl Write more examples of tests here...
diff --git a/src/php/ext/grpc/php7_wrapper.h b/src/php/ext/grpc/php7_wrapper.h
index d4fa859249..5afe656062 100644
--- a/src/php/ext/grpc/php7_wrapper.h
+++ b/src/php/ext/grpc/php7_wrapper.h
@@ -30,6 +30,8 @@
add_property_string(arg, name, context, b)
#define php_grpc_add_property_stringl(res, name, str, len, b) \
add_property_stringl(res, name, str, len, b)
+#define php_grpc_add_property_zval(res, name, val) \
+ add_property_zval(res, name, val)
#define php_grpc_add_next_index_stringl(data, str, len, b) \
add_next_index_stringl(data, str, len, b)
@@ -44,6 +46,8 @@
add_assoc_long_ex(val, key, key_len, str);
#define PHP_GRPC_ADD_BOOL_TO_ARRAY(val, key, key_len, str) \
add_assoc_bool_ex(val, key, key_len, str);
+#define PHP_GRPC_ADD_LONG_TO_RETVAL(val, key, key_len, str) \
+ add_assoc_long_ex(val, key, key_len+1, str);
#define RETURN_DESTROY_ZVAL(val) \
RETURN_ZVAL(val, false /* Don't execute copy constructor */, \
@@ -138,12 +142,17 @@ static inline int php_grpc_zend_hash_find(HashTable *ht, char *key, int len,
zend_hash_update(plist, key, len+1, rsrc, sizeof(php_grpc_zend_resource), \
NULL)
#define PHP_GRPC_PERSISTENT_LIST_SIZE(plist) \
- plist.nTableSize
+ *plist.nNumOfElements
#define PHP_GRPC_GET_CLASS_ENTRY(object) zend_get_class_entry(object TSRMLS_CC)
#define PHP_GRPC_INIT_HANDLER(class_object, handler_name)
+#define PHP_GRPC_DECLARE_OBJECT_HANDLER(handler_name)
+
+#define PHP_GRPC_GET_WRAPPED_OBJECT(class_object, zv) \
+ (class_object *)zend_object_store_get_object(zv TSRMLS_CC)
+
#else
#define php_grpc_int size_t
@@ -154,6 +163,11 @@ static inline int php_grpc_zend_hash_find(HashTable *ht, char *key, int len,
add_property_string(arg, name, context)
#define php_grpc_add_property_stringl(res, name, str, len, b) \
add_property_stringl(res, name, str, len)
+#define php_grpc_add_property_zval(res, name, val) do { \
+ zval tmp; \
+ tmp = *val; \
+ add_property_zval(res, name, &tmp); \
+ } while(0)
#define php_grpc_add_next_index_stringl(data, str, len, b) \
add_next_index_stringl(data, str, len)
@@ -169,6 +183,8 @@ static inline int php_grpc_zend_hash_find(HashTable *ht, char *key, int len,
add_assoc_long_ex(val, key, key_len - 1, str);
#define PHP_GRPC_ADD_BOOL_TO_ARRAY(val, key, key_len, str) \
add_assoc_bool_ex(val, key, key_len - 1, str);
+#define PHP_GRPC_ADD_LONG_TO_RETVAL(val, key, key_len, str) \
+ add_assoc_long_ex(val, key, key_len, str);
#define RETURN_DESTROY_ZVAL(val) \
RETVAL_ZVAL(val, false /* Don't execute copy constructor */, \
@@ -261,6 +277,12 @@ static inline int php_grpc_zend_hash_del(HashTable *ht, char *key, int len) {
handler_name.offset = XtOffsetOf(class_object, std); \
handler_name.free_obj = free_##class_object
+#define PHP_GRPC_DECLARE_OBJECT_HANDLER(handler_name) \
+ static zend_object_handlers handler_name;
+
+#define PHP_GRPC_GET_WRAPPED_OBJECT(class_object, zv) \
+ class_object##_from_obj(Z_OBJ_P((zv)))
+
#endif /* PHP_MAJOR_VERSION */
#endif /* PHP7_WRAPPER_GRPC_H */
diff --git a/src/php/ext/grpc/php_grpc.c b/src/php/ext/grpc/php_grpc.c
index 883ee6f3e5..fabd98975d 100644
--- a/src/php/ext/grpc/php_grpc.c
+++ b/src/php/ext/grpc/php_grpc.c
@@ -16,6 +16,8 @@
*
*/
+#include "php_grpc.h"
+
#include "call.h"
#include "channel.h"
#include "server.h"
@@ -25,18 +27,10 @@
#include "server_credentials.h"
#include "completion_queue.h"
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <php.h>
-#include <php_ini.h>
-#include <ext/standard/info.h>
-#include "php_grpc.h"
-
ZEND_DECLARE_MODULE_GLOBALS(grpc)
static PHP_GINIT_FUNCTION(grpc);
HashTable grpc_persistent_list;
+HashTable grpc_target_upper_bound_map;
/* {{{ grpc_functions[]
*
* Every user visible function must have an entry in grpc_functions[].
@@ -242,6 +236,8 @@ PHP_MSHUTDOWN_FUNCTION(grpc) {
if (GRPC_G(initialized)) {
zend_hash_clean(&grpc_persistent_list);
zend_hash_destroy(&grpc_persistent_list);
+ zend_hash_clean(&grpc_target_upper_bound_map);
+ zend_hash_destroy(&grpc_target_upper_bound_map);
grpc_shutdown_timeval(TSRMLS_C);
grpc_php_shutdown_completion_queue(TSRMLS_C);
grpc_shutdown();
diff --git a/src/php/ext/grpc/php_grpc.h b/src/php/ext/grpc/php_grpc.h
index e30f011c39..ecf5ebaa05 100644
--- a/src/php/ext/grpc/php_grpc.h
+++ b/src/php/ext/grpc/php_grpc.h
@@ -20,8 +20,21 @@
#ifndef PHP_GRPC_H
#define PHP_GRPC_H
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include <stdbool.h>
+#include <php.h>
+#include <php_ini.h>
+#include <ext/standard/info.h>
+
+#include <grpc/grpc.h>
+
+#include "php7_wrapper.h"
+#include "version.h"
+
extern zend_module_entry grpc_module_entry;
#define phpext_grpc_ptr &grpc_module_entry
@@ -37,11 +50,6 @@ extern zend_module_entry grpc_module_entry;
#include "TSRM.h"
#endif
-#include "php.h"
-#include "php7_wrapper.h"
-#include "grpc/grpc.h"
-#include "version.h"
-
/* These are all function declarations */
/* Code that runs at module initialization */
PHP_MINIT_FUNCTION(grpc);
diff --git a/src/php/ext/grpc/server.c b/src/php/ext/grpc/server.c
index a65d233017..cb7b188b0e 100644
--- a/src/php/ext/grpc/server.c
+++ b/src/php/ext/grpc/server.c
@@ -16,37 +16,23 @@
*
*/
-#include "call.h"
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include "server.h"
-#include <php.h>
-#include <php_ini.h>
-#include <ext/standard/info.h>
#include <ext/spl/spl_exceptions.h>
-#include "php_grpc.h"
-
#include <zend_exceptions.h>
-#include <stdbool.h>
-
-#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/slice.h>
#include <grpc/support/alloc.h>
+#include "call.h"
#include "completion_queue.h"
-#include "server.h"
#include "channel.h"
#include "server_credentials.h"
#include "timeval.h"
zend_class_entry *grpc_ce_server;
-#if PHP_MAJOR_VERSION >= 7
-static zend_object_handlers server_ce_handlers;
-#endif
+PHP_GRPC_DECLARE_OBJECT_HANDLER(server_ce_handlers)
/* Frees and destroys an instance of wrapped_grpc_server */
PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_server)
@@ -74,7 +60,8 @@ php_grpc_zend_object create_wrapped_grpc_server(zend_class_entry *class_type
* @param array $args_array The arguments to pass to the server (optional)
*/
PHP_METHOD(Server, __construct) {
- wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis());
+ wrapped_grpc_server *server =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_server, getThis());
zval *args_array = NULL;
grpc_channel_args args;
@@ -82,15 +69,12 @@ PHP_METHOD(Server, __construct) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a", &args_array) ==
FAILURE) {
zend_throw_exception(spl_ce_InvalidArgumentException,
- "Server expects an array",
- 1 TSRMLS_CC);
+ "Server expects an array", 1 TSRMLS_CC);
return;
}
if (args_array == NULL) {
server->wrapped = grpc_server_create(NULL, NULL);
} else {
- //TODO(thinkerou): deal it if key of array is long, crash now on php7
- // and update unit test case
php_grpc_read_args_array(args_array, &args TSRMLS_CC);
server->wrapped = grpc_server_create(&args, NULL);
efree(args.args);
@@ -110,7 +94,8 @@ PHP_METHOD(Server, requestCall) {
grpc_metadata_array metadata;
grpc_event event;
- wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis());
+ wrapped_grpc_server *server =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_server, getThis());
zval *result;
PHP_GRPC_MAKE_STD_ZVAL(result);
object_init(result);
@@ -118,8 +103,8 @@ PHP_METHOD(Server, requestCall) {
grpc_call_details_init(&details);
grpc_metadata_array_init(&metadata);
error_code =
- grpc_server_request_call(server->wrapped, &call, &details, &metadata,
- completion_queue, completion_queue, NULL);
+ grpc_server_request_call(server->wrapped, &call, &details, &metadata,
+ completion_queue, completion_queue, NULL);
if (error_code != GRPC_CALL_OK) {
zend_throw_exception(spl_ce_LogicException, "request_call failed",
(long)error_code TSRMLS_CC);
@@ -140,25 +125,12 @@ PHP_METHOD(Server, requestCall) {
php_grpc_add_property_string(result, "host", host_text, true);
gpr_free(method_text);
gpr_free(host_text);
-#if PHP_MAJOR_VERSION < 7
- add_property_zval(result, "call", grpc_php_wrap_call(call, true TSRMLS_CC));
- add_property_zval(result, "absolute_deadline",
- grpc_php_wrap_timeval(details.deadline TSRMLS_CC));
- add_property_zval(result, "metadata", grpc_parse_metadata_array(&metadata
- TSRMLS_CC));
-#else
- zval zv_call;
- zval zv_timeval;
- zval zv_md;
- //TODO(thinkerou): why use zval* to unit test error?
- zv_call = *grpc_php_wrap_call(call, true);
- zv_timeval = *grpc_php_wrap_timeval(details.deadline);
- zv_md = *grpc_parse_metadata_array(&metadata);
-
- add_property_zval(result, "call", &zv_call);
- add_property_zval(result, "absolute_deadline", &zv_timeval);
- add_property_zval(result, "metadata", &zv_md);
-#endif
+ php_grpc_add_property_zval(result, "call",
+ grpc_php_wrap_call(call, true TSRMLS_CC));
+ php_grpc_add_property_zval(result, "absolute_deadline",
+ grpc_php_wrap_timeval(details.deadline TSRMLS_CC));
+ php_grpc_add_property_zval(result, "metadata",
+ grpc_parse_metadata_array(&metadata TSRMLS_CC));
cleanup:
grpc_call_details_destroy(&details);
@@ -174,7 +146,8 @@ PHP_METHOD(Server, requestCall) {
PHP_METHOD(Server, addHttp2Port) {
const char *addr;
php_grpc_int addr_len;
- wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis());
+ wrapped_grpc_server *server =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_server, getThis());
/* "s" == 1 string */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &addr, &addr_len)
@@ -196,19 +169,20 @@ PHP_METHOD(Server, addSecureHttp2Port) {
const char *addr;
php_grpc_int addr_len;
zval *creds_obj;
- wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis());
+ wrapped_grpc_server *server =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_server, getThis());
/* "sO" == 1 string, 1 object */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO", &addr, &addr_len,
&creds_obj, grpc_ce_server_credentials) ==
FAILURE) {
- zend_throw_exception(
- spl_ce_InvalidArgumentException,
- "add_http2_port expects a string and a ServerCredentials", 1 TSRMLS_CC);
+ zend_throw_exception(spl_ce_InvalidArgumentException,
+ "add_http2_port expects a string and a "
+ "ServerCredentials", 1 TSRMLS_CC);
return;
}
wrapped_grpc_server_credentials *creds =
- Z_WRAPPED_GRPC_SERVER_CREDS_P(creds_obj);
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_server_credentials, creds_obj);
RETURN_LONG(grpc_server_add_secure_http2_port(server->wrapped, addr,
creds->wrapped));
}
@@ -218,7 +192,8 @@ PHP_METHOD(Server, addSecureHttp2Port) {
* @return void
*/
PHP_METHOD(Server, start) {
- wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis());
+ wrapped_grpc_server *server =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_server, getThis());
grpc_server_start(server->wrapped);
}
diff --git a/src/php/ext/grpc/server.h b/src/php/ext/grpc/server.h
index 366f5d05a4..fb1030ba32 100644
--- a/src/php/ext/grpc/server.h
+++ b/src/php/ext/grpc/server.h
@@ -19,17 +19,8 @@
#ifndef NET_GRPC_PHP_GRPC_SERVER_H_
#define NET_GRPC_PHP_GRPC_SERVER_H_
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <php.h>
-#include <php_ini.h>
-#include <ext/standard/info.h>
#include "php_grpc.h"
-#include <grpc/grpc.h>
-
/* Class entry for the Server PHP class */
extern zend_class_entry *grpc_ce_server;
@@ -38,23 +29,12 @@ PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_server)
grpc_server *wrapped;
PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_server)
-#if PHP_MAJOR_VERSION < 7
-
-#define Z_WRAPPED_GRPC_SERVER_P(zv) \
- (wrapped_grpc_server *)zend_object_store_get_object(zv TSRMLS_CC)
-
-#else
-
static inline wrapped_grpc_server
*wrapped_grpc_server_from_obj(zend_object *obj) {
return (wrapped_grpc_server*)((char*)(obj) -
XtOffsetOf(wrapped_grpc_server, std));
}
-#define Z_WRAPPED_GRPC_SERVER_P(zv) wrapped_grpc_server_from_obj(Z_OBJ_P((zv)))
-
-#endif /* PHP_MAJOR_VERSION */
-
/* Initializes the Server class */
void grpc_init_server(TSRMLS_D);
diff --git a/src/php/ext/grpc/server_credentials.c b/src/php/ext/grpc/server_credentials.c
index 212486e2e1..72ce50fff7 100644
--- a/src/php/ext/grpc/server_credentials.c
+++ b/src/php/ext/grpc/server_credentials.c
@@ -18,26 +18,11 @@
#include "server_credentials.h"
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <php.h>
-#include <php_ini.h>
-#include <ext/standard/info.h>
#include <ext/spl/spl_exceptions.h>
-#include "php_grpc.h"
-
#include <zend_exceptions.h>
-#include <zend_hash.h>
-
-#include <grpc/grpc.h>
-#include <grpc/grpc_security.h>
zend_class_entry *grpc_ce_server_credentials;
-#if PHP_MAJOR_VERSION >= 7
-static zend_object_handlers server_credentials_ce_handlers;
-#endif
+PHP_GRPC_DECLARE_OBJECT_HANDLER(server_credentials_ce_handlers)
/* Frees and destroys an instace of wrapped_grpc_server_credentials */
PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_server_credentials)
@@ -63,7 +48,8 @@ zval *grpc_php_wrap_server_credentials(grpc_server_credentials
PHP_GRPC_MAKE_STD_ZVAL(server_credentials_object);
object_init_ex(server_credentials_object, grpc_ce_server_credentials);
wrapped_grpc_server_credentials *server_credentials =
- Z_WRAPPED_GRPC_SERVER_CREDS_P(server_credentials_object);
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_server_credentials,
+ server_credentials_object);
server_credentials->wrapped = wrapped;
return server_credentials_object;
}
diff --git a/src/php/ext/grpc/server_credentials.h b/src/php/ext/grpc/server_credentials.h
index 310c28db76..6a1af3603e 100644
--- a/src/php/ext/grpc/server_credentials.h
+++ b/src/php/ext/grpc/server_credentials.h
@@ -19,16 +19,8 @@
#ifndef NET_GRPC_PHP_GRPC_SERVER_CREDENTIALS_H_
#define NET_GRPC_PHP_GRPC_SERVER_CREDENTIALS_H_
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <php.h>
-#include <php_ini.h>
-#include <ext/standard/info.h>
#include "php_grpc.h"
-#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
/* Class entry for the Server_Credentials PHP class */
@@ -40,24 +32,12 @@ PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_server_credentials)
grpc_server_credentials *wrapped;
PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_server_credentials)
-#if PHP_MAJOR_VERSION < 7
-
-#define Z_WRAPPED_GRPC_SERVER_CREDS_P(zv) \
- (wrapped_grpc_server_credentials *)zend_object_store_get_object(zv TSRMLS_CC)
-
-#else
-
static inline wrapped_grpc_server_credentials
*wrapped_grpc_server_credentials_from_obj(zend_object *obj) {
return (wrapped_grpc_server_credentials*)(
(char*)(obj) - XtOffsetOf(wrapped_grpc_server_credentials, std));
}
-#define Z_WRAPPED_GRPC_SERVER_CREDS_P(zv) \
- wrapped_grpc_server_credentials_from_obj(Z_OBJ_P((zv)))
-
-#endif /* PHP_MAJOR_VERSION */
-
/* Initializes the Server_Credentials PHP class */
void grpc_init_server_credentials(TSRMLS_D);
diff --git a/src/php/ext/grpc/timeval.c b/src/php/ext/grpc/timeval.c
index 7280dde30b..8f0048def6 100644
--- a/src/php/ext/grpc/timeval.c
+++ b/src/php/ext/grpc/timeval.c
@@ -18,27 +18,11 @@
#include "timeval.h"
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <php.h>
-#include <php_ini.h>
-#include <ext/standard/info.h>
#include <ext/spl/spl_exceptions.h>
-#include "php_grpc.h"
-
#include <zend_exceptions.h>
-#include <stdbool.h>
-
-#include <grpc/grpc.h>
-#include <grpc/support/time.h>
-
zend_class_entry *grpc_ce_timeval;
-#if PHP_MAJOR_VERSION >= 7
-static zend_object_handlers timeval_ce_handlers;
-#endif
+PHP_GRPC_DECLARE_OBJECT_HANDLER(timeval_ce_handlers)
/* Frees and destroys an instance of wrapped_grpc_call */
PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_timeval)
@@ -58,7 +42,8 @@ zval *grpc_php_wrap_timeval(gpr_timespec wrapped TSRMLS_DC) {
zval *timeval_object;
PHP_GRPC_MAKE_STD_ZVAL(timeval_object);
object_init_ex(timeval_object, grpc_ce_timeval);
- wrapped_grpc_timeval *timeval = Z_WRAPPED_GRPC_TIMEVAL_P(timeval_object);
+ wrapped_grpc_timeval *timeval =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, timeval_object);
memcpy(&timeval->wrapped, &wrapped, sizeof(gpr_timespec));
return timeval_object;
}
@@ -68,7 +53,8 @@ zval *grpc_php_wrap_timeval(gpr_timespec wrapped TSRMLS_DC) {
* @param long $microseconds The number of microseconds in the interval
*/
PHP_METHOD(Timeval, __construct) {
- wrapped_grpc_timeval *timeval = Z_WRAPPED_GRPC_TIMEVAL_P(getThis());
+ wrapped_grpc_timeval *timeval =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, getThis());
php_grpc_long microseconds;
/* "l" == 1 long */
@@ -98,8 +84,10 @@ PHP_METHOD(Timeval, add) {
"add expects a Timeval", 1 TSRMLS_CC);
return;
}
- wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis());
- wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj);
+ wrapped_grpc_timeval *self =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, getThis());
+ wrapped_grpc_timeval *other =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, other_obj);
zval *sum =
grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped)
TSRMLS_CC);
@@ -122,8 +110,10 @@ PHP_METHOD(Timeval, subtract) {
"subtract expects a Timeval", 1 TSRMLS_CC);
return;
}
- wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis());
- wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj);
+ wrapped_grpc_timeval *self =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, getThis());
+ wrapped_grpc_timeval *other =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, other_obj);
zval *diff =
grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped)
TSRMLS_CC);
@@ -149,8 +139,10 @@ PHP_METHOD(Timeval, compare) {
"compare expects two Timevals", 1 TSRMLS_CC);
return;
}
- wrapped_grpc_timeval *a = Z_WRAPPED_GRPC_TIMEVAL_P(a_obj);
- wrapped_grpc_timeval *b = Z_WRAPPED_GRPC_TIMEVAL_P(b_obj);
+ wrapped_grpc_timeval *a =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, a_obj);
+ wrapped_grpc_timeval *b =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, b_obj);
long result = gpr_time_cmp(a->wrapped, b->wrapped);
RETURN_LONG(result);
}
@@ -175,9 +167,12 @@ PHP_METHOD(Timeval, similar) {
"compare expects three Timevals", 1 TSRMLS_CC);
return;
}
- wrapped_grpc_timeval *a = Z_WRAPPED_GRPC_TIMEVAL_P(a_obj);
- wrapped_grpc_timeval *b = Z_WRAPPED_GRPC_TIMEVAL_P(b_obj);
- wrapped_grpc_timeval *thresh = Z_WRAPPED_GRPC_TIMEVAL_P(thresh_obj);
+ wrapped_grpc_timeval *a =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, a_obj);
+ wrapped_grpc_timeval *b =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, b_obj);
+ wrapped_grpc_timeval *thresh =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, thresh_obj);
int result = gpr_time_similar(a->wrapped, b->wrapped, thresh->wrapped);
RETURN_BOOL(result);
}
@@ -226,7 +221,8 @@ PHP_METHOD(Timeval, infPast) {
* @return void
*/
PHP_METHOD(Timeval, sleepUntil) {
- wrapped_grpc_timeval *this = Z_WRAPPED_GRPC_TIMEVAL_P(getThis());
+ wrapped_grpc_timeval *this =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, getThis());
gpr_sleep_until(this->wrapped);
}
diff --git a/src/php/ext/grpc/timeval.h b/src/php/ext/grpc/timeval.h
index f4d267f907..6f8cc62264 100644
--- a/src/php/ext/grpc/timeval.h
+++ b/src/php/ext/grpc/timeval.h
@@ -19,18 +19,8 @@
#ifndef NET_GRPC_PHP_GRPC_TIMEVAL_H_
#define NET_GRPC_PHP_GRPC_TIMEVAL_H_
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <php.h>
-#include <php_ini.h>
-#include <ext/standard/info.h>
#include "php_grpc.h"
-#include <grpc/grpc.h>
-#include <grpc/support/time.h>
-
/* Class entry for the Timeval PHP Class */
extern zend_class_entry *grpc_ce_timeval;
@@ -39,24 +29,12 @@ PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_timeval)
gpr_timespec wrapped;
PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_timeval)
-#if PHP_MAJOR_VERSION < 7
-
-#define Z_WRAPPED_GRPC_TIMEVAL_P(zv) \
- (wrapped_grpc_timeval *)zend_object_store_get_object(zv TSRMLS_CC)
-
-#else
-
static inline wrapped_grpc_timeval
*wrapped_grpc_timeval_from_obj(zend_object *obj) {
return (wrapped_grpc_timeval*)((char*)(obj) -
XtOffsetOf(wrapped_grpc_timeval, std));
}
-#define Z_WRAPPED_GRPC_TIMEVAL_P(zv) \
- wrapped_grpc_timeval_from_obj(Z_OBJ_P((zv)))
-
-#endif /* PHP_MAJOR_VERSION */
-
/* Initialize the Timeval PHP class */
void grpc_init_timeval(TSRMLS_D);
diff --git a/src/php/ext/grpc/version.h b/src/php/ext/grpc/version.h
index 37df2768bf..407d6347e6 100644
--- a/src/php/ext/grpc/version.h
+++ b/src/php/ext/grpc/version.h
@@ -20,6 +20,6 @@
#ifndef VERSION_H
#define VERSION_H
-#define PHP_GRPC_VERSION "1.12.0dev"
+#define PHP_GRPC_VERSION "1.13.0dev"
#endif /* VERSION_H */
diff --git a/src/php/lib/Grpc/BaseStub.php b/src/php/lib/Grpc/BaseStub.php
index 5f3a96feaa..b9c50b1da6 100644
--- a/src/php/lib/Grpc/BaseStub.php
+++ b/src/php/lib/Grpc/BaseStub.php
@@ -38,12 +38,13 @@ class BaseStub
* - 'update_metadata': (optional) a callback function which takes in a
* metadata array, and returns an updated metadata array
* - 'grpc.primary_user_agent': (optional) a user-agent string
- * @param Channel $channel An already created Channel object (optional)
+ * @param Channel|InterceptorChannel $channel An already created Channel or InterceptorChannel object (optional)
*/
- public function __construct($hostname, $opts, Channel $channel = null)
+ public function __construct($hostname, $opts, $channel = null)
{
$ssl_roots = file_get_contents(
- dirname(__FILE__).'/../../../../etc/roots.pem');
+ dirname(__FILE__).'/../../../../etc/roots.pem'
+ );
ChannelCredentials::setDefaultRootsPem($ssl_roots);
$this->hostname = $hostname;
@@ -58,16 +59,32 @@ class BaseStub
$this->hostname_override = $opts['grpc.ssl_target_name_override'];
}
if ($channel) {
- if (!is_a($channel, 'Grpc\Channel')) {
- throw new \Exception('The channel argument is not a'.
- 'Channel object');
+ if (!is_a($channel, 'Grpc\Channel') &&
+ !is_a($channel, 'Grpc\Internal\InterceptorChannel')) {
+ throw new \Exception('The channel argument is not a Channel object '.
+ 'or an InterceptorChannel object created by '.
+ 'Interceptor::intercept($channel, Interceptor|Interceptor[] $interceptors)');
}
$this->channel = $channel;
return;
}
+ $this->channel = static::getDefaultChannel($hostname, $opts);
+ }
+
+ /**
+ * Creates and returns the default Channel
+ *
+ * @param array $opts Channel constructor options
+ *
+ * @return Channel The channel
+ */
+ public static function getDefaultChannel($hostname, array $opts)
+ {
$package_config = json_decode(
- file_get_contents(dirname(__FILE__).'/../../composer.json'), true);
+ file_get_contents(dirname(__FILE__).'/../../composer.json'),
+ true
+ );
if (!empty($opts['grpc.primary_user_agent'])) {
$opts['grpc.primary_user_agent'] .= ' ';
} else {
@@ -77,10 +94,10 @@ class BaseStub
'grpc-php/'.$package_config['version'];
if (!array_key_exists('credentials', $opts)) {
throw new \Exception("The opts['credentials'] key is now ".
- 'required. Please see one of the '.
- 'ChannelCredentials::create methods');
+ 'required. Please see one of the '.
+ 'ChannelCredentials::create methods');
}
- $this->channel = new Channel($hostname, $opts);
+ return new Channel($hostname, $opts);
}
/**
@@ -169,7 +186,8 @@ class BaseStub
$last_slash_idx = strrpos($method, '/');
if ($last_slash_idx === false) {
throw new \InvalidArgumentException(
- 'service name must have a slash');
+ 'service name must have a slash'
+ );
}
$service_name = substr($method, 0, $last_slash_idx);
@@ -197,7 +215,8 @@ class BaseStub
if (!preg_match('/^[A-Za-z\d_-]+$/', $key)) {
throw new \InvalidArgumentException(
'Metadata keys must be nonempty strings containing only '.
- 'alphanumeric characters, hyphens and underscores');
+ 'alphanumeric characters, hyphens and underscores'
+ );
}
$metadata_copy[strtolower($key)] = $value;
}
@@ -205,9 +224,255 @@ class BaseStub
return $metadata_copy;
}
+ /**
+ * Create a function which can be used to create UnaryCall
+ *
+ * @param Channel|InterceptorChannel $channel
+ * @param callable $deserialize A function that deserializes the response
+ *
+ * @return \Closure
+ */
+ private function _GrpcUnaryUnary($channel, $deserialize)
+ {
+ return function ($method,
+ $argument,
+ array $metadata = [],
+ array $options = []) use ($channel, $deserialize) {
+ $call = new UnaryCall(
+ $channel,
+ $method,
+ $deserialize,
+ $options
+ );
+ $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
+ if (is_callable($this->update_metadata)) {
+ $metadata = call_user_func(
+ $this->update_metadata,
+ $metadata,
+ $jwt_aud_uri
+ );
+ }
+ $metadata = $this->_validate_and_normalize_metadata(
+ $metadata
+ );
+ $call->start($argument, $metadata, $options);
+ return $call;
+ };
+ }
+
+ /**
+ * Create a function which can be used to create ServerStreamingCall
+ *
+ * @param Channel|InterceptorChannel $channel
+ * @param callable $deserialize A function that deserializes the response
+ *
+ * @return \Closure
+ */
+ private function _GrpcStreamUnary($channel, $deserialize)
+ {
+ return function ($method,
+ array $metadata = [],
+ array $options = []) use ($channel, $deserialize) {
+ $call = new ClientStreamingCall(
+ $channel,
+ $method,
+ $deserialize,
+ $options
+ );
+ $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
+ if (is_callable($this->update_metadata)) {
+ $metadata = call_user_func(
+ $this->update_metadata,
+ $metadata,
+ $jwt_aud_uri
+ );
+ }
+ $metadata = $this->_validate_and_normalize_metadata(
+ $metadata
+ );
+ $call->start($metadata);
+ return $call;
+ };
+ }
+
+ /**
+ * Create a function which can be used to create ClientStreamingCall
+ *
+ * @param Channel|InterceptorChannel $channel
+ * @param callable $deserialize A function that deserializes the response
+ *
+ * @return \Closure
+ */
+ private function _GrpcUnaryStream($channel, $deserialize)
+ {
+ return function ($method,
+ $argument,
+ array $metadata = [],
+ array $options = []) use ($channel, $deserialize) {
+ $call = new ServerStreamingCall(
+ $channel,
+ $method,
+ $deserialize,
+ $options
+ );
+ $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
+ if (is_callable($this->update_metadata)) {
+ $metadata = call_user_func(
+ $this->update_metadata,
+ $metadata,
+ $jwt_aud_uri
+ );
+ }
+ $metadata = $this->_validate_and_normalize_metadata(
+ $metadata
+ );
+ $call->start($argument, $metadata, $options);
+ return $call;
+ };
+ }
+
+ /**
+ * Create a function which can be used to create BidiStreamingCall
+ *
+ * @param Channel|InterceptorChannel $channel
+ * @param callable $deserialize A function that deserializes the response
+ *
+ * @return \Closure
+ */
+ private function _GrpcStreamStream($channel, $deserialize)
+ {
+ return function ($method,
+ array $metadata = [],
+ array $options = []) use ($channel ,$deserialize) {
+ $call = new BidiStreamingCall(
+ $channel,
+ $method,
+ $deserialize,
+ $options
+ );
+ $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
+ if (is_callable($this->update_metadata)) {
+ $metadata = call_user_func(
+ $this->update_metadata,
+ $metadata,
+ $jwt_aud_uri
+ );
+ }
+ $metadata = $this->_validate_and_normalize_metadata(
+ $metadata
+ );
+ $call->start($metadata);
+
+ return $call;
+ };
+ }
+
+ /**
+ * Create a function which can be used to create UnaryCall
+ *
+ * @param Channel|InterceptorChannel $channel
+ * @param callable $deserialize A function that deserializes the response
+ *
+ * @return \Closure
+ */
+ private function _UnaryUnaryCallFactory($channel, $deserialize)
+ {
+ if (is_a($channel, 'Grpc\Internal\InterceptorChannel')) {
+ return function ($method,
+ $argument,
+ array $metadata = [],
+ array $options = []) use ($channel, $deserialize) {
+ return $channel->getInterceptor()->interceptUnaryUnary(
+ $method,
+ $argument,
+ $metadata,
+ $options,
+ $this->_UnaryUnaryCallFactory($channel->getNext(), $deserialize)
+ );
+ };
+ }
+ return $this->_GrpcUnaryUnary($channel, $deserialize);
+ }
+
+ /**
+ * Create a function which can be used to create ServerStreamingCall
+ *
+ * @param Channel|InterceptorChannel $channel
+ * @param callable $deserialize A function that deserializes the response
+ *
+ * @return \Closure
+ */
+ private function _UnaryStreamCallFactory($channel, $deserialize)
+ {
+ if (is_a($channel, 'Grpc\Internal\InterceptorChannel')) {
+ return function ($method,
+ $argument,
+ array $metadata = [],
+ array $options = []) use ($channel, $deserialize) {
+ return $channel->getInterceptor()->interceptUnaryStream(
+ $method,
+ $argument,
+ $metadata,
+ $options,
+ $this->_UnaryStreamCallFactory($channel->getNext(), $deserialize)
+ );
+ };
+ }
+ return $this->_GrpcUnaryStream($channel, $deserialize);
+ }
+
+ /**
+ * Create a function which can be used to create ClientStreamingCall
+ *
+ * @param Channel|InterceptorChannel $channel
+ * @param callable $deserialize A function that deserializes the response
+ *
+ * @return \Closure
+ */
+ private function _StreamUnaryCallFactory($channel, $deserialize)
+ {
+ if (is_a($channel, 'Grpc\Internal\InterceptorChannel')) {
+ return function ($method,
+ array $metadata = [],
+ array $options = []) use ($channel, $deserialize) {
+ return $channel->getInterceptor()->interceptStreamUnary(
+ $method,
+ $metadata,
+ $options,
+ $this->_StreamUnaryCallFactory($channel->getNext(), $deserialize)
+ );
+ };
+ }
+ return $this->_GrpcStreamUnary($channel, $deserialize);
+ }
+
+ /**
+ * Create a function which can be used to create BidiStreamingCall
+ *
+ * @param Channel|InterceptorChannel $channel
+ * @param callable $deserialize A function that deserializes the response
+ *
+ * @return \Closure
+ */
+ private function _StreamStreamCallFactory($channel, $deserialize)
+ {
+ if (is_a($channel, 'Grpc\Internal\InterceptorChannel')) {
+ return function ($method,
+ array $metadata = [],
+ array $options = []) use ($channel, $deserialize) {
+ return $channel->getInterceptor()->interceptStreamStream(
+ $method,
+ $metadata,
+ $options,
+ $this->_StreamStreamCallFactory($channel->getNext(), $deserialize)
+ );
+ };
+ }
+ return $this->_GrpcStreamStream($channel, $deserialize);
+ }
+
/* This class is intended to be subclassed by generated code, so
* all functions begin with "_" to avoid name collisions. */
-
/**
* Call a remote method that takes a single argument and has a
* single output.
@@ -221,26 +486,15 @@ class BaseStub
*
* @return UnaryCall The active call object
*/
- protected function _simpleRequest($method,
- $argument,
- $deserialize,
- array $metadata = [],
- array $options = [])
- {
- $call = new UnaryCall($this->channel,
- $method,
- $deserialize,
- $options);
- $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
- if (is_callable($this->update_metadata)) {
- $metadata = call_user_func($this->update_metadata,
- $metadata,
- $jwt_aud_uri);
- }
- $metadata = $this->_validate_and_normalize_metadata(
- $metadata);
- $call->start($argument, $metadata, $options);
-
+ protected function _simpleRequest(
+ $method,
+ $argument,
+ $deserialize,
+ array $metadata = [],
+ array $options = []
+ ) {
+ $call_factory = $this->_UnaryUnaryCallFactory($this->channel, $deserialize);
+ $call = $call_factory($method, $argument, $metadata, $options);
return $call;
}
@@ -256,25 +510,14 @@ class BaseStub
*
* @return ClientStreamingCall The active call object
*/
- protected function _clientStreamRequest($method,
- $deserialize,
- array $metadata = [],
- array $options = [])
- {
- $call = new ClientStreamingCall($this->channel,
- $method,
- $deserialize,
- $options);
- $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
- if (is_callable($this->update_metadata)) {
- $metadata = call_user_func($this->update_metadata,
- $metadata,
- $jwt_aud_uri);
- }
- $metadata = $this->_validate_and_normalize_metadata(
- $metadata);
- $call->start($metadata);
-
+ protected function _clientStreamRequest(
+ $method,
+ $deserialize,
+ array $metadata = [],
+ array $options = []
+ ) {
+ $call_factory = $this->_StreamUnaryCallFactory($this->channel, $deserialize);
+ $call = $call_factory($method, $metadata, $options);
return $call;
}
@@ -291,26 +534,15 @@ class BaseStub
*
* @return ServerStreamingCall The active call object
*/
- protected function _serverStreamRequest($method,
- $argument,
- $deserialize,
- array $metadata = [],
- array $options = [])
- {
- $call = new ServerStreamingCall($this->channel,
- $method,
- $deserialize,
- $options);
- $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
- if (is_callable($this->update_metadata)) {
- $metadata = call_user_func($this->update_metadata,
- $metadata,
- $jwt_aud_uri);
- }
- $metadata = $this->_validate_and_normalize_metadata(
- $metadata);
- $call->start($argument, $metadata, $options);
-
+ protected function _serverStreamRequest(
+ $method,
+ $argument,
+ $deserialize,
+ array $metadata = [],
+ array $options = []
+ ) {
+ $call_factory = $this->_UnaryStreamCallFactory($this->channel, $deserialize);
+ $call = $call_factory($method, $argument, $metadata, $options);
return $call;
}
@@ -325,25 +557,14 @@ class BaseStub
*
* @return BidiStreamingCall The active call object
*/
- protected function _bidiRequest($method,
- $deserialize,
- array $metadata = [],
- array $options = [])
- {
- $call = new BidiStreamingCall($this->channel,
- $method,
- $deserialize,
- $options);
- $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
- if (is_callable($this->update_metadata)) {
- $metadata = call_user_func($this->update_metadata,
- $metadata,
- $jwt_aud_uri);
- }
- $metadata = $this->_validate_and_normalize_metadata(
- $metadata);
- $call->start($metadata);
-
+ protected function _bidiRequest(
+ $method,
+ $deserialize,
+ array $metadata = [],
+ array $options = []
+ ) {
+ $call_factory = $this->_StreamStreamCallFactory($this->channel, $deserialize);
+ $call = $call_factory($method, $metadata, $options);
return $call;
}
}
diff --git a/src/php/lib/Grpc/Interceptor.php b/src/php/lib/Grpc/Interceptor.php
new file mode 100644
index 0000000000..e1b97f2a84
--- /dev/null
+++ b/src/php/lib/Grpc/Interceptor.php
@@ -0,0 +1,86 @@
+<?php
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Grpc;
+
+/**
+ * Represents an interceptor that intercept RPC invocations before call starts.
+ * This is an EXPERIMENTAL API.
+ */
+class Interceptor
+{
+ public function interceptUnaryUnary(
+ $method,
+ $argument,
+ array $metadata = [],
+ array $options = [],
+ $continuation
+ ) {
+ return $continuation($method, $argument, $metadata, $options);
+ }
+
+ public function interceptStreamUnary(
+ $method,
+ array $metadata = [],
+ array $options = [],
+ $continuation
+ ) {
+ return $continuation($method, $metadata, $options);
+ }
+
+ public function interceptUnaryStream(
+ $method,
+ $argument,
+ array $metadata = [],
+ array $options = [],
+ $continuation
+ ) {
+ return $continuation($method, $argument, $metadata, $options);
+ }
+
+ public function interceptStreamStream(
+ $method,
+ array $metadata = [],
+ array $options = [],
+ $continuation
+ ) {
+ return $continuation($method, $metadata, $options);
+ }
+
+ /**
+ * Intercept the methods with Channel
+ *
+ * @param Channel|InterceptorChannel $channel An already created Channel or InterceptorChannel object (optional)
+ * @param Interceptor|Interceptor[] $interceptors interceptors to be added
+ *
+ * @return InterceptorChannel
+ */
+ public static function intercept($channel, $interceptors)
+ {
+ if (is_array($interceptors)) {
+ for ($i = count($interceptors) - 1; $i >= 0; $i--) {
+ $channel = new Internal\InterceptorChannel($channel, $interceptors[$i]);
+ }
+ } else {
+ $channel = new Internal\InterceptorChannel($channel, $interceptors);
+ }
+ return $channel;
+ }
+}
+
diff --git a/src/php/lib/Grpc/Internal/InterceptorChannel.php b/src/php/lib/Grpc/Internal/InterceptorChannel.php
new file mode 100644
index 0000000000..2f85c35fe0
--- /dev/null
+++ b/src/php/lib/Grpc/Internal/InterceptorChannel.php
@@ -0,0 +1,76 @@
+<?php
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Grpc\Internal;
+
+/**
+ * This is a PRIVATE API and can change without notice.
+ */
+class InterceptorChannel extends \Grpc\Channel
+{
+ private $next = null;
+ private $interceptor;
+
+ /**
+ * @param Channel|InterceptorChannel $channel An already created Channel
+ * or InterceptorChannel object (optional)
+ * @param Interceptor $interceptor
+ */
+ public function __construct($channel, $interceptor)
+ {
+ if (!is_a($channel, 'Grpc\Channel') &&
+ !is_a($channel, 'Grpc\Internal\InterceptorChannel')) {
+ throw new \Exception('The channel argument is not a Channel object '.
+ 'or an InterceptorChannel object created by '.
+ 'Interceptor::intercept($channel, Interceptor|Interceptor[] $interceptors)');
+ }
+ $this->interceptor = $interceptor;
+ $this->next = $channel;
+ }
+
+ public function getNext()
+ {
+ return $this->next;
+ }
+
+ public function getInterceptor()
+ {
+ return $this->interceptor;
+ }
+
+ public function getTarget()
+ {
+ return $this->getNext()->getTarget();
+ }
+
+ public function watchConnectivityState($new_state, $deadline)
+ {
+ return $this->getNext()->watchConnectivityState($new_state, $deadline);
+ }
+
+ public function getConnectivityState($try_to_connect = false)
+ {
+ return $this->getNext()->getConnectivityState($try_to_connect);
+ }
+
+ public function close()
+ {
+ return $this->getNext()->close();
+ }
+}
diff --git a/src/php/tests/unit_tests/CallCredentials2Test.php b/src/php/tests/unit_tests/CallCredentials2Test.php
index a462bfff56..1c7e0c0ff6 100644
--- a/src/php/tests/unit_tests/CallCredentials2Test.php
+++ b/src/php/tests/unit_tests/CallCredentials2Test.php
@@ -46,9 +46,6 @@ class CallCredentials2Test extends PHPUnit_Framework_TestCase
{
unset($this->channel);
unset($this->server);
- $channel_clean_persistent =
- new Grpc\Channel('localhost:50010', []);
- $channel_clean_persistent->cleanPersistentList();
}
public function callbackFunc($context)
diff --git a/src/php/tests/unit_tests/CallCredentialsTest.php b/src/php/tests/unit_tests/CallCredentialsTest.php
index 31046e6395..4b5721d76a 100644
--- a/src/php/tests/unit_tests/CallCredentialsTest.php
+++ b/src/php/tests/unit_tests/CallCredentialsTest.php
@@ -52,9 +52,6 @@ class CallCredentialsTest extends PHPUnit_Framework_TestCase
{
unset($this->channel);
unset($this->server);
- $channel_clean_persistent =
- new Grpc\Channel('localhost:50010', []);
- $channel_clean_persistent->cleanPersistentList();
}
public function callbackFunc($context)
diff --git a/src/php/tests/unit_tests/CallTest.php b/src/php/tests/unit_tests/CallTest.php
index 38c36ed19a..c5e1890a98 100644
--- a/src/php/tests/unit_tests/CallTest.php
+++ b/src/php/tests/unit_tests/CallTest.php
@@ -38,9 +38,6 @@ class CallTest extends PHPUnit_Framework_TestCase
public function tearDown()
{
$this->channel->close();
- $channel_clean_persistent =
- new Grpc\Channel('localhost:50010', []);
- $channel_clean_persistent->cleanPersistentList();
}
public function testConstructor()
diff --git a/src/php/tests/unit_tests/ChannelTest.php b/src/php/tests/unit_tests/ChannelTest.php
index 63d4193a8b..49b0e350f7 100644
--- a/src/php/tests/unit_tests/ChannelTest.php
+++ b/src/php/tests/unit_tests/ChannelTest.php
@@ -1,7 +1,7 @@
<?php
/*
*
- * Copyright 2015 gRPC authors.
+ * Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,21 +28,18 @@ class ChannelTest extends PHPUnit_Framework_TestCase
if (!empty($this->channel)) {
$this->channel->close();
}
- $channel_clean_persistent =
- new Grpc\Channel('localhost:50010', []);
- $channel_clean_persistent->cleanPersistentList();
}
public function testInsecureCredentials()
{
- $this->channel = new Grpc\Channel('localhost:0',
+ $this->channel = new Grpc\Channel('localhost:50000',
['credentials' => Grpc\ChannelCredentials::createInsecure()]);
$this->assertSame('Grpc\Channel', get_class($this->channel));
}
public function testGetConnectivityState()
{
- $this->channel = new Grpc\Channel('localhost:0',
+ $this->channel = new Grpc\Channel('localhost:50001',
['credentials' => Grpc\ChannelCredentials::createInsecure()]);
$state = $this->channel->getConnectivityState();
$this->assertEquals(0, $state);
@@ -50,7 +47,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase
public function testGetConnectivityStateWithInt()
{
- $this->channel = new Grpc\Channel('localhost:0',
+ $this->channel = new Grpc\Channel('localhost:50002',
['credentials' => Grpc\ChannelCredentials::createInsecure()]);
$state = $this->channel->getConnectivityState(123);
$this->assertEquals(0, $state);
@@ -58,7 +55,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase
public function testGetConnectivityStateWithString()
{
- $this->channel = new Grpc\Channel('localhost:0',
+ $this->channel = new Grpc\Channel('localhost:50003',
['credentials' => Grpc\ChannelCredentials::createInsecure()]);
$state = $this->channel->getConnectivityState('hello');
$this->assertEquals(0, $state);
@@ -66,7 +63,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase
public function testGetConnectivityStateWithBool()
{
- $this->channel = new Grpc\Channel('localhost:0',
+ $this->channel = new Grpc\Channel('localhost:50004',
['credentials' => Grpc\ChannelCredentials::createInsecure()]);
$state = $this->channel->getConnectivityState(true);
$this->assertEquals(0, $state);
@@ -74,7 +71,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase
public function testGetTarget()
{
- $this->channel = new Grpc\Channel('localhost:8888',
+ $this->channel = new Grpc\Channel('localhost:50005',
['credentials' => Grpc\ChannelCredentials::createInsecure()]);
$target = $this->channel->getTarget();
$this->assertTrue(is_string($target));
@@ -82,7 +79,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase
public function testWatchConnectivityState()
{
- $this->channel = new Grpc\Channel('localhost:0',
+ $this->channel = new Grpc\Channel('localhost:50006',
['credentials' => Grpc\ChannelCredentials::createInsecure()]);
$now = Grpc\Timeval::now();
$deadline = $now->add(new Grpc\Timeval(100*1000)); // 100ms
@@ -96,7 +93,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase
public function testClose()
{
- $this->channel = new Grpc\Channel('localhost:0',
+ $this->channel = new Grpc\Channel('localhost:50007',
['credentials' => Grpc\ChannelCredentials::createInsecure()]);
$this->assertNotNull($this->channel);
$this->channel->close();
@@ -116,7 +113,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase
*/
public function testInvalidConstructorWith()
{
- $this->channel = new Grpc\Channel('localhost:0', 'invalid');
+ $this->channel = new Grpc\Channel('localhost:50008', 'invalid');
$this->assertNull($this->channel);
}
@@ -125,7 +122,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase
*/
public function testInvalidCredentials()
{
- $this->channel = new Grpc\Channel('localhost:0',
+ $this->channel = new Grpc\Channel('localhost:50009',
['credentials' => new Grpc\Timeval(100)]);
}
@@ -134,7 +131,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase
*/
public function testInvalidOptionsArray()
{
- $this->channel = new Grpc\Channel('localhost:0',
+ $this->channel = new Grpc\Channel('localhost:50010',
['abc' => []]);
}
@@ -143,7 +140,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase
*/
public function testInvalidGetConnectivityStateWithArray()
{
- $this->channel = new Grpc\Channel('localhost:0',
+ $this->channel = new Grpc\Channel('localhost:50011',
['credentials' => Grpc\ChannelCredentials::createInsecure()]);
$this->channel->getConnectivityState([]);
}
@@ -153,7 +150,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase
*/
public function testInvalidWatchConnectivityState()
{
- $this->channel = new Grpc\Channel('localhost:0',
+ $this->channel = new Grpc\Channel('localhost:50012',
['credentials' => Grpc\ChannelCredentials::createInsecure()]);
$this->channel->watchConnectivityState([]);
}
@@ -163,7 +160,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase
*/
public function testInvalidWatchConnectivityState2()
{
- $this->channel = new Grpc\Channel('localhost:0',
+ $this->channel = new Grpc\Channel('localhost:50013',
['credentials' => Grpc\ChannelCredentials::createInsecure()]);
$this->channel->watchConnectivityState(1, 'hi');
}
@@ -188,10 +185,12 @@ class ChannelTest extends PHPUnit_Framework_TestCase
public function testPersistentChannelSameHost()
{
- $this->channel1 = new Grpc\Channel('localhost:1', []);
+ $this->channel1 = new Grpc\Channel('localhost:50014', [
+ "grpc_target_persist_bound" => 3,
+ ]);
// the underlying grpc channel is the same by default
// when connecting to the same host
- $this->channel2 = new Grpc\Channel('localhost:1', []);
+ $this->channel2 = new Grpc\Channel('localhost:50014', []);
// both channels should be IDLE
$state = $this->channel1->getConnectivityState();
@@ -216,8 +215,10 @@ class ChannelTest extends PHPUnit_Framework_TestCase
public function testPersistentChannelDifferentHost()
{
// two different underlying channels because different hostname
- $this->channel1 = new Grpc\Channel('localhost:1', []);
- $this->channel2 = new Grpc\Channel('localhost:2', []);
+ $this->channel1 = new Grpc\Channel('localhost:50015', [
+ "grpc_target_persist_bound" => 3,
+ ]);
+ $this->channel2 = new Grpc\Channel('localhost:50016', []);
// both channels should be IDLE
$state = $this->channel1->getConnectivityState();
@@ -242,8 +243,11 @@ class ChannelTest extends PHPUnit_Framework_TestCase
public function testPersistentChannelSameArgs()
{
- $this->channel1 = new Grpc\Channel('localhost:1', ["abc" => "def"]);
- $this->channel2 = new Grpc\Channel('localhost:1', ["abc" => "def"]);
+ $this->channel1 = new Grpc\Channel('localhost:50017', [
+ "grpc_target_persist_bound" => 3,
+ "abc" => "def",
+ ]);
+ $this->channel2 = new Grpc\Channel('localhost:50017', ["abc" => "def"]);
// try to connect on channel1
$state = $this->channel1->getConnectivityState(true);
@@ -260,8 +264,10 @@ class ChannelTest extends PHPUnit_Framework_TestCase
public function testPersistentChannelDifferentArgs()
{
- $this->channel1 = new Grpc\Channel('localhost:1', []);
- $this->channel2 = new Grpc\Channel('localhost:1', ["abc" => "def"]);
+ $this->channel1 = new Grpc\Channel('localhost:50018', [
+ "grpc_target_persist_bound" => 3,
+ ]);
+ $this->channel2 = new Grpc\Channel('localhost:50018', ["abc" => "def"]);
// try to connect on channel1
$state = $this->channel1->getConnectivityState(true);
@@ -281,9 +287,11 @@ class ChannelTest extends PHPUnit_Framework_TestCase
$creds1 = Grpc\ChannelCredentials::createSsl();
$creds2 = Grpc\ChannelCredentials::createSsl();
- $this->channel1 = new Grpc\Channel('localhost:1',
- ["credentials" => $creds1]);
- $this->channel2 = new Grpc\Channel('localhost:1',
+ $this->channel1 = new Grpc\Channel('localhost:50019',
+ ["credentials" => $creds1,
+ "grpc_target_persist_bound" => 3,
+ ]);
+ $this->channel2 = new Grpc\Channel('localhost:50019',
["credentials" => $creds2]);
// try to connect on channel1
@@ -305,9 +313,11 @@ class ChannelTest extends PHPUnit_Framework_TestCase
$creds2 = Grpc\ChannelCredentials::createSsl(
file_get_contents(dirname(__FILE__).'/../data/ca.pem'));
- $this->channel1 = new Grpc\Channel('localhost:1',
- ["credentials" => $creds1]);
- $this->channel2 = new Grpc\Channel('localhost:1',
+ $this->channel1 = new Grpc\Channel('localhost:50020',
+ ["credentials" => $creds1,
+ "grpc_target_persist_bound" => 3,
+ ]);
+ $this->channel2 = new Grpc\Channel('localhost:50020',
["credentials" => $creds2]);
// try to connect on channel1
@@ -330,9 +340,11 @@ class ChannelTest extends PHPUnit_Framework_TestCase
$creds2 = Grpc\ChannelCredentials::createSsl(
file_get_contents(dirname(__FILE__).'/../data/ca.pem'));
- $this->channel1 = new Grpc\Channel('localhost:1',
- ["credentials" => $creds1]);
- $this->channel2 = new Grpc\Channel('localhost:1',
+ $this->channel1 = new Grpc\Channel('localhost:50021',
+ ["credentials" => $creds1,
+ "grpc_target_persist_bound" => 3,
+ ]);
+ $this->channel2 = new Grpc\Channel('localhost:50021',
["credentials" => $creds2]);
// try to connect on channel1
@@ -353,9 +365,11 @@ class ChannelTest extends PHPUnit_Framework_TestCase
$creds1 = Grpc\ChannelCredentials::createSsl();
$creds2 = Grpc\ChannelCredentials::createInsecure();
- $this->channel1 = new Grpc\Channel('localhost:1',
- ["credentials" => $creds1]);
- $this->channel2 = new Grpc\Channel('localhost:1',
+ $this->channel1 = new Grpc\Channel('localhost:50022',
+ ["credentials" => $creds1,
+ "grpc_target_persist_bound" => 3,
+ ]);
+ $this->channel2 = new Grpc\Channel('localhost:50022',
["credentials" => $creds2]);
// try to connect on channel1
@@ -371,34 +385,55 @@ class ChannelTest extends PHPUnit_Framework_TestCase
$this->channel2->close();
}
+ public function testPersistentChannelSharedChannelClose1()
+ {
+ // same underlying channel
+ $this->channel1 = new Grpc\Channel('localhost:50123', [
+ "grpc_target_persist_bound" => 3,
+ ]);
+ $this->channel2 = new Grpc\Channel('localhost:50123', []);
+
+ // close channel1
+ $this->channel1->close();
+
+ // channel2 can still be use. We need to exclude the possible that
+ // in testPersistentChannelSharedChannelClose2, the exception is thrown
+ // by channel1.
+ $state = $this->channel2->getConnectivityState();
+ $this->assertEquals(GRPC\CHANNEL_IDLE, $state);
+ }
+
/**
* @expectedException RuntimeException
*/
- public function testPersistentChannelSharedChannelClose()
+ public function testPersistentChannelSharedChannelClose2()
{
// same underlying channel
- $this->channel1 = new Grpc\Channel('localhost:1', []);
- $this->channel2 = new Grpc\Channel('localhost:1', []);
+ $this->channel1 = new Grpc\Channel('localhost:50223', [
+ "grpc_target_persist_bound" => 3,
+ ]);
+ $this->channel2 = new Grpc\Channel('localhost:50223', []);
// close channel1
$this->channel1->close();
- // channel2 is now in SHUTDOWN state
+ // channel2 can still be use
$state = $this->channel2->getConnectivityState();
- $this->assertEquals(GRPC\CHANNEL_FATAL_FAILURE, $state);
+ $this->assertEquals(GRPC\CHANNEL_IDLE, $state);
- // calling it again will result in an exception because the
- // channel is already closed
- $state = $this->channel2->getConnectivityState();
+ // channel 1 is closed
+ $state = $this->channel1->getConnectivityState();
}
public function testPersistentChannelCreateAfterClose()
{
- $this->channel1 = new Grpc\Channel('localhost:1', []);
+ $this->channel1 = new Grpc\Channel('localhost:50024', [
+ "grpc_target_persist_bound" => 3,
+ ]);
$this->channel1->close();
- $this->channel2 = new Grpc\Channel('localhost:1', []);
+ $this->channel2 = new Grpc\Channel('localhost:50024', []);
$state = $this->channel2->getConnectivityState();
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
@@ -407,9 +442,11 @@ class ChannelTest extends PHPUnit_Framework_TestCase
public function testPersistentChannelSharedMoreThanTwo()
{
- $this->channel1 = new Grpc\Channel('localhost:1', []);
- $this->channel2 = new Grpc\Channel('localhost:1', []);
- $this->channel3 = new Grpc\Channel('localhost:1', []);
+ $this->channel1 = new Grpc\Channel('localhost:50025', [
+ "grpc_target_persist_bound" => 3,
+ ]);
+ $this->channel2 = new Grpc\Channel('localhost:50025', []);
+ $this->channel3 = new Grpc\Channel('localhost:50025', []);
// try to connect on channel1
$state = $this->channel1->getConnectivityState(true);
@@ -447,10 +484,12 @@ class ChannelTest extends PHPUnit_Framework_TestCase
// If a ChannelCredentials object is composed with a
// CallCredentials object, the underlying grpc channel will
// always be created new and NOT persisted.
- $this->channel1 = new Grpc\Channel('localhost:1',
+ $this->channel1 = new Grpc\Channel('localhost:50026',
["credentials" =>
- $credsWithCallCreds]);
- $this->channel2 = new Grpc\Channel('localhost:1',
+ $credsWithCallCreds,
+ "grpc_target_persist_bound" => 3,
+ ]);
+ $this->channel2 = new Grpc\Channel('localhost:50026',
["credentials" =>
$credsWithCallCreds]);
@@ -484,11 +523,13 @@ class ChannelTest extends PHPUnit_Framework_TestCase
// object is composed with a CallCredentials object, the
// underlying grpc channel will always be separate and not
// persisted
- $this->channel1 = new Grpc\Channel('localhost:1',
- ["credentials" => $creds1]);
- $this->channel2 = new Grpc\Channel('localhost:1',
+ $this->channel1 = new Grpc\Channel('localhost:50027',
+ ["credentials" => $creds1,
+ "grpc_target_persist_bound" => 3,
+ ]);
+ $this->channel2 = new Grpc\Channel('localhost:50027',
["credentials" => $creds2]);
- $this->channel3 = new Grpc\Channel('localhost:1',
+ $this->channel3 = new Grpc\Channel('localhost:50027',
["credentials" => $creds3]);
// try to connect on channel1
@@ -509,10 +550,12 @@ class ChannelTest extends PHPUnit_Framework_TestCase
public function testPersistentChannelForceNew()
{
- $this->channel1 = new Grpc\Channel('localhost:1', []);
+ $this->channel1 = new Grpc\Channel('localhost:50028', [
+ "grpc_target_persist_bound" => 2,
+ ]);
// even though all the channel params are the same, channel2
// has a new and different underlying channel
- $this->channel2 = new Grpc\Channel('localhost:1',
+ $this->channel2 = new Grpc\Channel('localhost:50028',
["force_new" => true]);
// try to connect on channel1
@@ -528,19 +571,20 @@ class ChannelTest extends PHPUnit_Framework_TestCase
$this->channel2->close();
}
- public function testPersistentChannelForceNewOldChannelIdle()
+ public function testPersistentChannelForceNewOldChannelIdle1()
{
- $this->channel1 = new Grpc\Channel('localhost:1', []);
- $this->channel2 = new Grpc\Channel('localhost:1',
+ $this->channel1 = new Grpc\Channel('localhost:50029', [
+ "grpc_target_persist_bound" => 2,
+ ]);
+ $this->channel2 = new Grpc\Channel('localhost:50029',
["force_new" => true]);
// channel3 shares with channel1
- $this->channel3 = new Grpc\Channel('localhost:1', []);
+ $this->channel3 = new Grpc\Channel('localhost:50029', []);
// try to connect on channel2
$state = $this->channel2->getConnectivityState(true);
$this->waitUntilNotIdle($this->channel2);
-
$state = $this->channel1->getConnectivityState();
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
$state = $this->channel2->getConnectivityState();
@@ -552,34 +596,85 @@ class ChannelTest extends PHPUnit_Framework_TestCase
$this->channel2->close();
}
+ public function testPersistentChannelForceNewOldChannelIdle2()
+ {
+
+ $this->channel1 = new Grpc\Channel('localhost:50029', [
+ "grpc_target_persist_bound" => 2,
+ ]);
+ $this->channel2 = new Grpc\Channel('localhost:50029', []);
+
+ // try to connect on channel2
+ $state = $this->channel1->getConnectivityState(true);
+ $this->waitUntilNotIdle($this->channel2);
+ $state = $this->channel1->getConnectivityState();
+ $this->assertConnecting($state);
+ $state = $this->channel2->getConnectivityState();
+ $this->assertConnecting($state);
+
+ $this->channel1->close();
+ $this->channel2->close();
+ }
+
+ public function testPersistentChannelForceNewOldChannelClose1()
+ {
+
+ $this->channel1 = new Grpc\Channel('localhost:50130', [
+ "grpc_target_persist_bound" => 2,
+ ]);
+ $this->channel2 = new Grpc\Channel('localhost:50130',
+ ["force_new" => true]);
+ // channel3 shares with channel1
+ $this->channel3 = new Grpc\Channel('localhost:50130', []);
+
+ $this->channel1->close();
+
+ $state = $this->channel2->getConnectivityState();
+ $this->assertEquals(GRPC\CHANNEL_IDLE, $state);
+
+ // channel3 is still usable. We need to exclude the possibility that in
+ // testPersistentChannelForceNewOldChannelClose2, the exception is thrown
+ // by channel1 and channel2.
+ $state = $this->channel3->getConnectivityState();
+ $this->assertEquals(GRPC\CHANNEL_IDLE, $state);
+ }
+
/**
* @expectedException RuntimeException
*/
- public function testPersistentChannelForceNewOldChannelClose()
+ public function testPersistentChannelForceNewOldChannelClose2()
{
- $this->channel1 = new Grpc\Channel('localhost:1', []);
- $this->channel2 = new Grpc\Channel('localhost:1',
- ["force_new" => true]);
+ $this->channel1 = new Grpc\Channel('localhost:50230', [
+ "grpc_target_persist_bound" => 2,
+ ]);
+ $this->channel2 = new Grpc\Channel('localhost:50230',
+ ["force_new" => true]);
// channel3 shares with channel1
- $this->channel3 = new Grpc\Channel('localhost:1', []);
+ $this->channel3 = new Grpc\Channel('localhost:50230', []);
$this->channel1->close();
$state = $this->channel2->getConnectivityState();
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
- // channel3 already closed
+ // channel3 is still usable
$state = $this->channel3->getConnectivityState();
+ $this->assertEquals(GRPC\CHANNEL_IDLE, $state);
+
+ // channel 1 is closed
+ $this->channel1->getConnectivityState();
}
public function testPersistentChannelForceNewNewChannelClose()
{
- $this->channel1 = new Grpc\Channel('localhost:1', []);
- $this->channel2 = new Grpc\Channel('localhost:1',
+ $this->channel1 = new Grpc\Channel('localhost:50031', [
+ "grpc_target_persist_bound" => 2,
+ ]);
+ $this->channel2 = new Grpc\Channel('localhost:50031',
["force_new" => true]);
- $this->channel3 = new Grpc\Channel('localhost:1', []);
+ $this->channel3 = new Grpc\Channel('localhost:50031', []);
$this->channel2->close();
diff --git a/src/php/tests/unit_tests/EndToEndTest.php b/src/php/tests/unit_tests/EndToEndTest.php
index 71a56d2b6e..b54f1d87c9 100644
--- a/src/php/tests/unit_tests/EndToEndTest.php
+++ b/src/php/tests/unit_tests/EndToEndTest.php
@@ -29,9 +29,6 @@ class EndToEndTest extends PHPUnit_Framework_TestCase
public function tearDown()
{
$this->channel->close();
- $channel_clean_persistent =
- new Grpc\Channel('localhost:50010', []);
- $channel_clean_persistent->cleanPersistentList();
}
public function testSimpleRequestBody()
diff --git a/src/php/tests/unit_tests/InterceptorTest.php b/src/php/tests/unit_tests/InterceptorTest.php
new file mode 100644
index 0000000000..11c5b4325a
--- /dev/null
+++ b/src/php/tests/unit_tests/InterceptorTest.php
@@ -0,0 +1,423 @@
+<?php
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+/**
+ * Interface exported by the server.
+ */
+require_once(dirname(__FILE__).'/../../lib/Grpc/BaseStub.php');
+require_once(dirname(__FILE__).'/../../lib/Grpc/AbstractCall.php');
+require_once(dirname(__FILE__).'/../../lib/Grpc/UnaryCall.php');
+require_once(dirname(__FILE__).'/../../lib/Grpc/ClientStreamingCall.php');
+require_once(dirname(__FILE__).'/../../lib/Grpc/Interceptor.php');
+require_once(dirname(__FILE__).'/../../lib/Grpc/Internal/InterceptorChannel.php');
+
+class SimpleRequest
+{
+ private $data;
+ public function __construct($data)
+ {
+ $this->data = $data;
+ }
+ public function setData($data)
+ {
+ $this->data = $data;
+ }
+ public function serializeToString()
+ {
+ return $this->data;
+ }
+}
+
+class InterceptorClient extends Grpc\BaseStub
+{
+
+ /**
+ * @param string $hostname hostname
+ * @param array $opts channel options
+ * @param Channel|InterceptorChannel $channel (optional) re-use channel object
+ */
+ public function __construct($hostname, $opts, $channel = null)
+ {
+ parent::__construct($hostname, $opts, $channel);
+ }
+
+ /**
+ * A simple RPC.
+ * @param SimpleRequest $argument input argument
+ * @param array $metadata metadata
+ * @param array $options call options
+ */
+ public function UnaryCall(
+ SimpleRequest $argument,
+ $metadata = [],
+ $options = []
+ ) {
+ return $this->_simpleRequest(
+ '/dummy_method',
+ $argument,
+ [],
+ $metadata,
+ $options
+ );
+ }
+
+ /**
+ * A client-to-server streaming RPC.
+ * @param array $metadata metadata
+ * @param array $options call options
+ */
+ public function StreamCall(
+ $metadata = [],
+ $options = []
+ ) {
+ return $this->_clientStreamRequest('/dummy_method', [], $metadata, $options);
+ }
+}
+
+
+class ChangeMetadataInterceptor extends Grpc\Interceptor
+{
+ public function interceptUnaryUnary($method,
+ $argument,
+ array $metadata = [],
+ array $options = [],
+ $continuation)
+ {
+ $metadata["foo"] = array('interceptor_from_unary_request');
+ return $continuation($method, $argument, $metadata, $options);
+ }
+ public function interceptStreamUnary($method, array $metadata = [], array $options = [], $continuation)
+ {
+ $metadata["foo"] = array('interceptor_from_stream_request');
+ return $continuation($method, $metadata, $options);
+ }
+}
+
+class ChangeMetadataInterceptor2 extends Grpc\Interceptor
+{
+ public function interceptUnaryUnary($method,
+ $argument,
+ array $metadata = [],
+ array $options = [],
+ $continuation)
+ {
+ if (array_key_exists('foo', $metadata)) {
+ $metadata['bar'] = array('ChangeMetadataInterceptor should be executed first');
+ } else {
+ $metadata["bar"] = array('interceptor_from_unary_request');
+ }
+ return $continuation($method, $argument, $metadata, $options);
+ }
+ public function interceptStreamUnary($method,
+ array $metadata = [],
+ array $options = [],
+ $continuation)
+ {
+ if (array_key_exists('foo', $metadata)) {
+ $metadata['bar'] = array('ChangeMetadataInterceptor should be executed first');
+ } else {
+ $metadata["bar"] = array('interceptor_from_stream_request');
+ }
+ return $continuation($method, $metadata, $options);
+ }
+}
+
+class ChangeRequestCall
+{
+ private $call;
+
+ public function __construct($call)
+ {
+ $this->call = $call;
+ }
+ public function getCall()
+ {
+ return $this->call;
+ }
+
+ public function write($request)
+ {
+ $request->setData('intercepted_stream_request');
+ $this->getCall()->write($request);
+ }
+
+ public function wait()
+ {
+ return $this->getCall()->wait();
+ }
+}
+
+class ChangeRequestInterceptor extends Grpc\Interceptor
+{
+ public function interceptUnaryUnary($method,
+ $argument,
+ array $metadata = [],
+ array $options = [],
+ $continuation)
+ {
+ $argument->setData('intercepted_unary_request');
+ return $continuation($method, $argument, $metadata, $options);
+ }
+ public function interceptStreamUnary($method, array $metadata = [], array $options = [], $continuation)
+ {
+ return new ChangeRequestCall(
+ $continuation($method, $metadata, $options)
+ );
+ }
+}
+
+class StopCallInterceptor extends Grpc\Interceptor
+{
+ public function interceptUnaryUnary($method,
+ $argument,
+ array $metadata = [],
+ array $options = [],
+ $continuation)
+ {
+ $metadata["foo"] = array('interceptor_from_request_response');
+ }
+ public function interceptStreamUnary($method,
+ array $metadata = [],
+ array $options = [],
+ $continuation)
+ {
+ $metadata["foo"] = array('interceptor_from_request_response');
+ }
+}
+
+class InterceptorTest extends PHPUnit_Framework_TestCase
+{
+ public function setUp()
+ {
+ $this->server = new Grpc\Server([]);
+ $this->port = $this->server->addHttp2Port('0.0.0.0:0');
+ $this->channel = new Grpc\Channel('localhost:'.$this->port, ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
+ $this->server->start();
+ }
+
+ public function tearDown()
+ {
+ $this->channel->close();
+ }
+
+
+ public function testClientChangeMetadataOneInterceptor()
+ {
+ $req_text = 'client_request';
+ $channel_matadata_interceptor = new ChangeMetadataInterceptor();
+ $intercept_channel = Grpc\Interceptor::intercept($this->channel, $channel_matadata_interceptor);
+ $client = new InterceptorClient('localhost:'.$this->port, [
+ 'credentials' => Grpc\ChannelCredentials::createInsecure(),
+ ], $intercept_channel);
+ $req = new SimpleRequest($req_text);
+ $unary_call = $client->UnaryCall($req);
+ $event = $this->server->requestCall();
+ $this->assertSame('/dummy_method', $event->method);
+ $this->assertSame(['interceptor_from_unary_request'], $event->metadata['foo']);
+
+ $stream_call = $client->StreamCall();
+ $stream_call->write($req);
+ $event = $this->server->requestCall();
+ $this->assertSame('/dummy_method', $event->method);
+ $this->assertSame(['interceptor_from_stream_request'], $event->metadata['foo']);
+
+ unset($unary_call);
+ unset($stream_call);
+ unset($server_call);
+ }
+
+ public function testClientChangeMetadataTwoInterceptor()
+ {
+ $req_text = 'client_request';
+ $channel_matadata_interceptor = new ChangeMetadataInterceptor();
+ $channel_matadata_intercepto2 = new ChangeMetadataInterceptor2();
+ // test intercept separately.
+ $intercept_channel1 = Grpc\Interceptor::intercept($this->channel, $channel_matadata_interceptor);
+ $intercept_channel2 = Grpc\Interceptor::intercept($intercept_channel1, $channel_matadata_intercepto2);
+ $client = new InterceptorClient('localhost:'.$this->port, [
+ 'credentials' => Grpc\ChannelCredentials::createInsecure(),
+ ], $intercept_channel2);
+
+ $req = new SimpleRequest($req_text);
+ $unary_call = $client->UnaryCall($req);
+ $event = $this->server->requestCall();
+ $this->assertSame('/dummy_method', $event->method);
+ $this->assertSame(['interceptor_from_unary_request'], $event->metadata['foo']);
+ $this->assertSame(['interceptor_from_unary_request'], $event->metadata['bar']);
+
+ $stream_call = $client->StreamCall();
+ $stream_call->write($req);
+ $event = $this->server->requestCall();
+ $this->assertSame('/dummy_method', $event->method);
+ $this->assertSame(['interceptor_from_stream_request'], $event->metadata['foo']);
+ $this->assertSame(['interceptor_from_stream_request'], $event->metadata['bar']);
+
+ unset($unary_call);
+ unset($stream_call);
+ unset($server_call);
+
+ // test intercept by array.
+ $intercept_channel3 = Grpc\Interceptor::intercept($this->channel,
+ [$channel_matadata_intercepto2, $channel_matadata_interceptor]);
+ $client = new InterceptorClient('localhost:'.$this->port, [
+ 'credentials' => Grpc\ChannelCredentials::createInsecure(),
+ ], $intercept_channel3);
+
+ $req = new SimpleRequest($req_text);
+ $unary_call = $client->UnaryCall($req);
+ $event = $this->server->requestCall();
+ $this->assertSame('/dummy_method', $event->method);
+ $this->assertSame(['interceptor_from_unary_request'], $event->metadata['foo']);
+ $this->assertSame(['interceptor_from_unary_request'], $event->metadata['bar']);
+
+ $stream_call = $client->StreamCall();
+ $stream_call->write($req);
+ $event = $this->server->requestCall();
+ $this->assertSame('/dummy_method', $event->method);
+ $this->assertSame(['interceptor_from_stream_request'], $event->metadata['foo']);
+ $this->assertSame(['interceptor_from_stream_request'], $event->metadata['bar']);
+
+ unset($unary_call);
+ unset($stream_call);
+ unset($server_call);
+ }
+
+ public function testClientChangeRequestInterceptor()
+ {
+ $req_text = 'client_request';
+ $change_request_interceptor = new ChangeRequestInterceptor();
+ $intercept_channel = Grpc\Interceptor::intercept($this->channel,
+ $change_request_interceptor);
+ $client = new InterceptorClient('localhost:'.$this->port, [
+ 'credentials' => Grpc\ChannelCredentials::createInsecure(),
+ ], $intercept_channel);
+
+ $req = new SimpleRequest($req_text);
+ $unary_call = $client->UnaryCall($req);
+
+ $event = $this->server->requestCall();
+ $this->assertSame('/dummy_method', $event->method);
+ $server_call = $event->call;
+ $event = $server_call->startBatch([
+ Grpc\OP_SEND_INITIAL_METADATA => [],
+ Grpc\OP_SEND_STATUS_FROM_SERVER => [
+ 'metadata' => [],
+ 'code' => Grpc\STATUS_OK,
+ 'details' => '',
+ ],
+ Grpc\OP_RECV_MESSAGE => true,
+ Grpc\OP_RECV_CLOSE_ON_SERVER => true,
+ ]);
+ $this->assertSame('intercepted_unary_request', $event->message);
+
+ $stream_call = $client->StreamCall();
+ $stream_call->write($req);
+ $event = $this->server->requestCall();
+ $this->assertSame('/dummy_method', $event->method);
+ $server_call = $event->call;
+ $event = $server_call->startBatch([
+ Grpc\OP_SEND_INITIAL_METADATA => [],
+ Grpc\OP_SEND_STATUS_FROM_SERVER => [
+ 'metadata' => [],
+ 'code' => Grpc\STATUS_OK,
+ 'details' => '',
+ ],
+ Grpc\OP_RECV_MESSAGE => true,
+ Grpc\OP_RECV_CLOSE_ON_SERVER => true,
+ ]);
+ $this->assertSame('intercepted_stream_request', $event->message);
+
+ unset($unary_call);
+ unset($stream_call);
+ unset($server_call);
+ }
+
+ public function testClientChangeStopCallInterceptor()
+ {
+ $req_text = 'client_request';
+ $channel_request_interceptor = new StopCallInterceptor();
+ $intercept_channel = Grpc\Interceptor::intercept($this->channel,
+ $channel_request_interceptor);
+ $client = new InterceptorClient('localhost:'.$this->port, [
+ 'credentials' => Grpc\ChannelCredentials::createInsecure(),
+ ], $intercept_channel);
+
+ $req = new SimpleRequest($req_text);
+ $unary_call = $client->UnaryCall($req);
+ $this->assertNull($unary_call);
+
+
+ $stream_call = $client->StreamCall();
+ $this->assertNull($stream_call);
+
+ unset($unary_call);
+ unset($stream_call);
+ unset($server_call);
+ }
+
+ public function testGetInterceptorChannelConnectivityState()
+ {
+ $channel = new Grpc\Channel(
+ 'localhost:0',
+ ['credentials' => Grpc\ChannelCredentials::createInsecure()]
+ );
+ $interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor());
+ $state = $interceptor_channel->getConnectivityState();
+ $this->assertEquals(0, $state);
+ $channel->close();
+ }
+
+ public function testInterceptorChannelWatchConnectivityState()
+ {
+ $channel = new Grpc\Channel(
+ 'localhost:0',
+ ['credentials' => Grpc\ChannelCredentials::createInsecure()]
+ );
+ $interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor());
+ $now = Grpc\Timeval::now();
+ $deadline = $now->add(new Grpc\Timeval(100*1000));
+ $state = $interceptor_channel->watchConnectivityState(1, $deadline);
+ $this->assertTrue($state);
+ unset($time);
+ unset($deadline);
+ $channel->close();
+ }
+
+ public function testInterceptorChannelClose()
+ {
+ $channel = new Grpc\Channel(
+ 'localhost:0',
+ ['credentials' => Grpc\ChannelCredentials::createInsecure()]
+ );
+ $interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor());
+ $this->assertNotNull($interceptor_channel);
+ $channel->close();
+ }
+
+ public function testInterceptorChannelGetTarget()
+ {
+ $channel = new Grpc\Channel(
+ 'localhost:8888',
+ ['credentials' => Grpc\ChannelCredentials::createInsecure()]
+ );
+ $interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor());
+ $target = $interceptor_channel->getTarget();
+ $this->assertTrue(is_string($target));
+ $channel->close();
+ }
+}
diff --git a/src/php/tests/unit_tests/PersistentChannelTest.php b/src/php/tests/unit_tests/PersistentChannelTest.php
deleted file mode 100644
index 171780a137..0000000000
--- a/src/php/tests/unit_tests/PersistentChannelTest.php
+++ /dev/null
@@ -1,115 +0,0 @@
-<?php
-/*
- *
- * Copyright 2015 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-class PersistentListTest extends PHPUnit_Framework_TestCase
-{
- public function setUp()
- {
- }
-
- public function tearDown()
- {
- $channel_clean_persistent =
- new Grpc\Channel('localhost:50010', []);
- $channel_clean_persistent->cleanPersistentList();
- }
-
- public function waitUntilNotIdle($channel) {
- for ($i = 0; $i < 10; $i++) {
- $now = Grpc\Timeval::now();
- $deadline = $now->add(new Grpc\Timeval(1000));
- if ($channel->watchConnectivityState(GRPC\CHANNEL_IDLE,
- $deadline)) {
- return true;
- }
- }
- $this->assertTrue(false);
- }
-
- public function assertConnecting($state) {
- $this->assertTrue($state == GRPC\CHANNEL_CONNECTING ||
- $state == GRPC\CHANNEL_TRANSIENT_FAILURE);
- }
-
- public function testPersistentChennelCreateOneChannel()
- {
- $this->channel1 = new Grpc\Channel('localhost:1', []);
- $plist = $this->channel1->getPersistentList();
- $this->assertEquals($plist['localhost:1']['target'], 'localhost:1');
- $this->assertArrayHasKey('localhost:1', $plist);
- $this->assertEquals($plist['localhost:1']['ref_count'], 1);
- $this->assertEquals($plist['localhost:1']['connectivity_status'],
- GRPC\CHANNEL_IDLE);
- $this->assertEquals($plist['localhost:1']['is_valid'], 1);
- $this->channel1->close();
- }
-
- public function testPersistentChennelStatusChange()
- {
- $this->channel1 = new Grpc\Channel('localhost:1', []);
- $plist = $this->channel1->getPersistentList();
- $this->assertEquals($plist['localhost:1']['connectivity_status'],
- GRPC\CHANNEL_IDLE);
- $this->assertEquals($plist['localhost:1']['is_valid'], 1);
- $state = $this->channel1->getConnectivityState(true);
-
- $this->waitUntilNotIdle($this->channel1);
- $plist = $this->channel1->getPersistentList();
- $this->assertConnecting($plist['localhost:1']['connectivity_status']);
- $this->assertEquals($plist['localhost:1']['is_valid'], 1);
-
- $this->channel1->close();
- }
-
- public function testPersistentChennelCloseChannel()
- {
- $this->channel1 = new Grpc\Channel('localhost:1', []);
- $plist = $this->channel1->getPersistentList();
- $this->assertEquals($plist['localhost:1']['ref_count'], 1);
- $this->channel1->close();
- $plist = $this->channel1->getPersistentList();
- $this->assertArrayNotHasKey('localhost:1', $plist);
- }
-
- public function testPersistentChannelSameHost()
- {
- $this->channel1 = new Grpc\Channel('localhost:1', []);
- $this->channel2 = new Grpc\Channel('localhost:1', []);
- //ref_count should be 2
- $plist = $this->channel1->getPersistentList();
- $this->assertArrayHasKey('localhost:1', $plist);
- $this->assertEquals($plist['localhost:1']['ref_count'], 2);
- $this->channel1->close();
- $this->channel2->close();
- }
-
- public function testPersistentChannelDifferentHost()
- {
- $this->channel1 = new Grpc\Channel('localhost:1', []);
- $this->channel2 = new Grpc\Channel('localhost:2', []);
- $plist = $this->channel1->getPersistentList();
- $this->assertArrayHasKey('localhost:1', $plist);
- $this->assertArrayHasKey('localhost:2', $plist);
- $this->assertEquals($plist['localhost:1']['ref_count'], 1);
- $this->assertEquals($plist['localhost:2']['ref_count'], 1);
- $this->channel1->close();
- $this->channel2->close();
- }
-
-}
diff --git a/src/php/tests/unit_tests/PersistentChannelTests/PersistentChannelTest.php b/src/php/tests/unit_tests/PersistentChannelTests/PersistentChannelTest.php
new file mode 100644
index 0000000000..2bb5c4bb85
--- /dev/null
+++ b/src/php/tests/unit_tests/PersistentChannelTests/PersistentChannelTest.php
@@ -0,0 +1,489 @@
+<?php
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * @group persistent_list_bound_tests
+ */
+class PersistentListTest extends PHPUnit_Framework_TestCase
+{
+ public function setUp()
+ {
+ }
+
+ public function tearDown()
+ {
+ $channel_clean_persistent =
+ new Grpc\Channel('localhost:50010', []);
+ $plist = $channel_clean_persistent->getPersistentList();
+ $channel_clean_persistent->cleanPersistentList();
+ }
+
+ public function waitUntilNotIdle($channel) {
+ for ($i = 0; $i < 10; $i++) {
+ $now = Grpc\Timeval::now();
+ $deadline = $now->add(new Grpc\Timeval(1000));
+ if ($channel->watchConnectivityState(GRPC\CHANNEL_IDLE,
+ $deadline)) {
+ return true;
+ }
+ }
+ $this->assertTrue(false);
+ }
+
+ public function assertConnecting($state) {
+ $this->assertTrue($state == GRPC\CHANNEL_CONNECTING ||
+ $state == GRPC\CHANNEL_TRANSIENT_FAILURE);
+ }
+
+ public function testInitHelper()
+ {
+ // PersistentList is not empty at the beginning of the tests
+ // because phpunit will cache the channels created by other test
+ // files.
+ }
+
+
+ public function testChannelNotPersist()
+ {
+ $this->channel1 = new Grpc\Channel('localhost:1', ['force_new' => true]);
+ $channel1_info = $this->channel1->getChannelInfo();
+ $plist_info = $this->channel1->getPersistentList();
+ $this->assertEquals($channel1_info['target'], 'localhost:1');
+ $this->assertEquals($channel1_info['ref_count'], 1);
+ $this->assertEquals($channel1_info['connectivity_status'],
+ GRPC\CHANNEL_IDLE);
+ $this->assertEquals(count($plist_info), 0);
+ $this->channel1->close();
+ }
+
+ public function testPersistentChannelCreateOneChannel()
+ {
+ $this->channel1 = new Grpc\Channel('localhost:1', []);
+ $channel1_info = $this->channel1->getChannelInfo();
+ $plist_info = $this->channel1->getPersistentList();
+ $this->assertEquals($channel1_info['target'], 'localhost:1');
+ $this->assertEquals($channel1_info['ref_count'], 2);
+ $this->assertEquals($channel1_info['connectivity_status'],
+ GRPC\CHANNEL_IDLE);
+ $this->assertArrayHasKey($channel1_info['key'], $plist_info);
+ $this->assertEquals(count($plist_info), 1);
+ $this->channel1->close();
+ }
+
+ public function testPersistentChannelCreateMultipleChannels()
+ {
+ $this->channel1 = new Grpc\Channel('localhost:1', []);
+ $plist_info = $this->channel1->getPersistentList();
+ $this->assertEquals(count($plist_info), 1);
+
+ $this->channel2 = new Grpc\Channel('localhost:2', []);
+ $plist_info = $this->channel1->getPersistentList();
+ $this->assertEquals(count($plist_info), 2);
+
+ $this->channel3 = new Grpc\Channel('localhost:3', []);
+ $plist_info = $this->channel1->getPersistentList();
+ $this->assertEquals(count($plist_info), 3);
+ }
+
+ public function testPersistentChannelStatusChange()
+ {
+ $this->channel1 = new Grpc\Channel('localhost:4', []);
+ $channel1_info = $this->channel1->getChannelInfo();
+ $this->assertEquals($channel1_info['connectivity_status'],
+ GRPC\CHANNEL_IDLE);
+
+ $this->channel1->getConnectivityState(true);
+ $this->waitUntilNotIdle($this->channel1);
+ $channel1_info = $this->channel1->getChannelInfo();
+ $this->assertConnecting($channel1_info['connectivity_status']);
+ $this->channel1->close();
+ }
+
+ public function testPersistentChannelCloseChannel()
+ {
+ $this->channel1 = new Grpc\Channel('localhost:1', []);
+ $this->channel2 = new Grpc\Channel('localhost:1', []);
+
+ $channel1_info = $this->channel1->getChannelInfo();
+ $this->assertEquals($channel1_info['ref_count'], 3);
+ $plist_info = $this->channel1->getPersistentList();
+ $this->assertEquals($plist_info[$channel1_info['key']]['ref_count'], 3);
+
+ $this->channel1->close();
+ $plist_info = $this->channel1->getPersistentList();
+ $this->assertEquals($plist_info[$channel1_info['key']]['ref_count'], 2);
+
+ $this->channel2->close();
+ $plist_info = $this->channel1->getPersistentList();
+ $this->assertEquals($plist_info[$channel1_info['key']]['ref_count'], 1);
+ }
+
+ public function testPersistentChannelSameTarget()
+ {
+ $this->channel1 = new Grpc\Channel('localhost:1', []);
+ $this->channel2 = new Grpc\Channel('localhost:1', []);
+ $plist = $this->channel2->getPersistentList();
+ $channel1_info = $this->channel1->getChannelInfo();
+ $channel2_info = $this->channel2->getChannelInfo();
+ // $channel1 and $channel2 shares the same channel, thus only 1
+ // channel should be in the persistent list.
+ $this->assertEquals($channel1_info['key'], $channel2_info['key']);
+ $this->assertArrayHasKey($channel1_info['key'], $plist);
+ $this->assertEquals(count($plist), 1);
+ $this->channel1->close();
+ $this->channel2->close();
+ }
+
+ public function testPersistentChannelDifferentTarget()
+ {
+ $this->channel1 = new Grpc\Channel('localhost:1', []);
+ $channel1_info = $this->channel1->getChannelInfo();
+ $this->channel2 = new Grpc\Channel('localhost:2', []);
+ $channel2_info = $this->channel1->getChannelInfo();
+ $plist_info = $this->channel1->getPersistentList();
+ $this->assertArrayHasKey($channel1_info['key'], $plist_info);
+ $this->assertArrayHasKey($channel2_info['key'], $plist_info);
+ $this->assertEquals($plist_info[$channel1_info['key']]['ref_count'], 2);
+ $this->assertEquals($plist_info[$channel2_info['key']]['ref_count'], 2);
+ $plist_info = $this->channel1->getPersistentList();
+ $this->assertEquals(count($plist_info), 2);
+ $this->channel1->close();
+ $this->channel2->close();
+ }
+
+ /**
+ * @expectedException RuntimeException
+ * @expectedExceptionMessage startBatch Error. Channel is closed
+ */
+ public function testPersistentChannelSharedChannelClose()
+ {
+ // same underlying channel
+ $this->channel1 = new Grpc\Channel('localhost:10010', [
+ "grpc_target_persist_bound" => 2,
+ ]);
+ $this->channel2 = new Grpc\Channel('localhost:10010', []);
+ $this->server = new Grpc\Server([]);
+ $this->port = $this->server->addHttp2Port('localhost:10010');
+
+ // channel2 can still be use
+ $state = $this->channel2->getConnectivityState();
+ $this->assertEquals(GRPC\CHANNEL_IDLE, $state);
+
+ $call1 = new Grpc\Call($this->channel1,
+ '/foo',
+ Grpc\Timeval::infFuture());
+ $call2 = new Grpc\Call($this->channel2,
+ '/foo',
+ Grpc\Timeval::infFuture());
+ $call3 = new Grpc\Call($this->channel1,
+ '/foo',
+ Grpc\Timeval::infFuture());
+ $call4 = new Grpc\Call($this->channel2,
+ '/foo',
+ Grpc\Timeval::infFuture());
+ $batch = [
+ Grpc\OP_SEND_INITIAL_METADATA => [],
+ ];
+
+ $result = $call1->startBatch($batch);
+ $this->assertTrue($result->send_metadata);
+ $result = $call2->startBatch($batch);
+ $this->assertTrue($result->send_metadata);
+
+ $this->channel1->close();
+ // After closing channel1, channel2 can still be use
+ $result = $call4->startBatch($batch);
+ $this->assertTrue($result->send_metadata);
+ // channel 1 is closed, it will throw an exception.
+ $result = $call3->startBatch($batch);
+ }
+
+ public function testPersistentChannelTargetDefaultUpperBound()
+ {
+ $this->channel1 = new Grpc\Channel('localhost:10011', []);
+ $channel1_info = $this->channel1->getChannelInfo();
+ $this->assertEquals($channel1_info['target_upper_bound'], 1);
+ $this->assertEquals($channel1_info['target_current_size'], 1);
+ }
+
+ public function testPersistentChannelTargetUpperBoundZero()
+ {
+ $this->channel1 = new Grpc\Channel('localhost:10011', [
+ "grpc_target_persist_bound" => 0,
+ ]);
+ // channel1 will not be persisted.
+ $channel1_info = $this->channel1->getChannelInfo();
+ $this->assertEquals($channel1_info['target_upper_bound'], 0);
+ $this->assertEquals($channel1_info['target_current_size'], 0);
+ $plist_info = $this->channel1->getPersistentList();
+ $this->assertEquals(0, count($plist_info));
+ }
+
+ public function testPersistentChannelTargetUpperBoundNotZero()
+ {
+ $this->channel1 = new Grpc\Channel('localhost:10011', [
+ "grpc_target_persist_bound" => 3,
+ ]);
+ $channel1_info = $this->channel1->getChannelInfo();
+ $this->assertEquals($channel1_info['target_upper_bound'], 3);
+ $this->assertEquals($channel1_info['target_current_size'], 1);
+
+ // The upper bound should not be changed
+ $this->channel2 = new Grpc\Channel('localhost:10011', []);
+ $channel2_info = $this->channel2->getChannelInfo();
+ $this->assertEquals($channel2_info['target_upper_bound'], 3);
+ $this->assertEquals($channel2_info['target_current_size'], 1);
+
+ // The upper bound should not be changed
+ $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
+ null);
+ $this->channel3 = new Grpc\Channel('localhost:10011',
+ ['credentials' => $channel_credentials]);
+ $channel3_info = $this->channel3->getChannelInfo();
+ $this->assertEquals($channel3_info['target_upper_bound'], 3);
+ $this->assertEquals($channel3_info['target_current_size'], 2);
+
+ // The upper bound should not be changed
+ $this->channel4 = new Grpc\Channel('localhost:10011', [
+ "grpc_target_persist_bound" => 5,
+ ]);
+ $channel4_info = $this->channel4->getChannelInfo();
+ $this->assertEquals($channel4_info['target_upper_bound'], 5);
+ $this->assertEquals($channel4_info['target_current_size'], 2);
+ }
+
+ public function testPersistentChannelDefaultOutBound1()
+ {
+ $this->channel1 = new Grpc\Channel('localhost:10011', []);
+ // Make channel1 not IDLE.
+ $this->channel1->getConnectivityState(true);
+ $this->waitUntilNotIdle($this->channel1);
+ $channel1_info = $this->channel1->getChannelInfo();
+ $this->assertConnecting($channel1_info['connectivity_status']);
+
+ // Since channel1 is CONNECTING, channel 2 will not be persisted
+ $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
+ null);
+ $this->channel2 = new Grpc\Channel('localhost:10011',
+ ['credentials' => $channel_credentials]);
+ $channel2_info = $this->channel2->getChannelInfo();
+ $this->assertEquals(GRPC\CHANNEL_IDLE, $channel2_info['connectivity_status']);
+
+ // By default, target 'localhost:10011' only persist one channel.
+ // Since channel1 is not Idle channel2 will not be persisted.
+ $plist_info = $this->channel1->getPersistentList();
+ $this->assertEquals(1, count($plist_info));
+ $this->assertArrayHasKey($channel1_info['key'], $plist_info);
+ $this->assertArrayNotHasKey($channel2_info['key'], $plist_info);
+ }
+
+ public function testPersistentChannelDefaultOutBound2()
+ {
+ $this->channel1 = new Grpc\Channel('localhost:10011', []);
+ $channel1_info = $this->channel1->getChannelInfo();
+ $this->assertEquals(GRPC\CHANNEL_IDLE, $channel1_info['connectivity_status']);
+
+ // Although channel1 is IDLE, channel1 still has reference to the underline
+ // gRPC channel. channel2 will not be persisted
+ $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
+ null);
+ $this->channel2 = new Grpc\Channel('localhost:10011',
+ ['credentials' => $channel_credentials]);
+ $channel2_info = $this->channel2->getChannelInfo();
+ $this->assertEquals(GRPC\CHANNEL_IDLE, $channel2_info['connectivity_status']);
+
+ // By default, target 'localhost:10011' only persist one channel.
+ // Since channel1 Idle, channel2 will be persisted.
+ $plist_info = $this->channel1->getPersistentList();
+ $this->assertEquals(1, count($plist_info));
+ $this->assertArrayHasKey($channel1_info['key'], $plist_info);
+ $this->assertArrayNotHasKey($channel2_info['key'], $plist_info);
+ }
+
+ public function testPersistentChannelDefaultOutBound3()
+ {
+ $this->channel1 = new Grpc\Channel('localhost:10011', []);
+ $channel1_info = $this->channel1->getChannelInfo();
+ $this->assertEquals(GRPC\CHANNEL_IDLE, $channel1_info['connectivity_status']);
+
+ $this->channel1->close();
+ // channel1 is closed, no reference holds to the underline channel.
+ // channel2 can be persisted.
+ $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
+ null);
+ $this->channel2 = new Grpc\Channel('localhost:10011',
+ ['credentials' => $channel_credentials]);
+ $channel2_info = $this->channel2->getChannelInfo();
+ $this->assertEquals(GRPC\CHANNEL_IDLE, $channel2_info['connectivity_status']);
+
+ // By default, target 'localhost:10011' only persist one channel.
+ // Since channel1 Idle, channel2 will be persisted.
+ $plist_info = $this->channel2->getPersistentList();
+ $this->assertEquals(1, count($plist_info));
+ $this->assertArrayHasKey($channel2_info['key'], $plist_info);
+ $this->assertArrayNotHasKey($channel1_info['key'], $plist_info);
+ }
+
+ public function testPersistentChannelTwoUpperBound()
+ {
+ $this->channel1 = new Grpc\Channel('localhost:10011', [
+ "grpc_target_persist_bound" => 2,
+ ]);
+ $channel1_info = $this->channel1->getChannelInfo();
+ $this->assertEquals(GRPC\CHANNEL_IDLE, $channel1_info['connectivity_status']);
+
+ // Since channel1 is IDLE, channel 1 will be deleted
+ $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
+ null);
+ $this->channel2 = new Grpc\Channel('localhost:10011',
+ ['credentials' => $channel_credentials]);
+ $channel2_info = $this->channel2->getChannelInfo();
+ $this->assertEquals(GRPC\CHANNEL_IDLE, $channel2_info['connectivity_status']);
+
+ $plist_info = $this->channel1->getPersistentList();
+ $this->assertEquals(2, count($plist_info));
+ $this->assertArrayHasKey($channel1_info['key'], $plist_info);
+ $this->assertArrayHasKey($channel2_info['key'], $plist_info);
+ }
+
+ public function testPersistentChannelTwoUpperBoundOutBound1()
+ {
+ $this->channel1 = new Grpc\Channel('localhost:10011', [
+ "grpc_target_persist_bound" => 2,
+ ]);
+ $channel1_info = $this->channel1->getChannelInfo();
+
+ $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
+ null);
+ $this->channel2 = new Grpc\Channel('localhost:10011',
+ ['credentials' => $channel_credentials]);
+ $channel2_info = $this->channel2->getChannelInfo();
+
+ // Close channel1, so that new channel can be persisted.
+ $this->channel1->close();
+
+ $channel_credentials = Grpc\ChannelCredentials::createSsl("a", null,
+ null);
+ $this->channel3 = new Grpc\Channel('localhost:10011',
+ ['credentials' => $channel_credentials]);
+ $channel3_info = $this->channel3->getChannelInfo();
+
+ $plist_info = $this->channel1->getPersistentList();
+ $this->assertEquals(2, count($plist_info));
+ $this->assertArrayNotHasKey($channel1_info['key'], $plist_info);
+ $this->assertArrayHasKey($channel2_info['key'], $plist_info);
+ $this->assertArrayHasKey($channel3_info['key'], $plist_info);
+ }
+
+ public function testPersistentChannelTwoUpperBoundOutBound2()
+ {
+ $this->channel1 = new Grpc\Channel('localhost:10011', [
+ "grpc_target_persist_bound" => 2,
+ ]);
+ $channel1_info = $this->channel1->getChannelInfo();
+
+ $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
+ null);
+ $this->channel2 = new Grpc\Channel('localhost:10011',
+ ['credentials' => $channel_credentials]);
+ $channel2_info = $this->channel2->getChannelInfo();
+
+ // Close channel2, so that new channel can be persisted.
+ $this->channel2->close();
+
+ $channel_credentials = Grpc\ChannelCredentials::createSsl("a", null,
+ null);
+ $this->channel3 = new Grpc\Channel('localhost:10011',
+ ['credentials' => $channel_credentials]);
+ $channel3_info = $this->channel3->getChannelInfo();
+
+ $plist_info = $this->channel1->getPersistentList();
+ $this->assertEquals(2, count($plist_info));
+ $this->assertArrayHasKey($channel1_info['key'], $plist_info);
+ $this->assertArrayNotHasKey($channel2_info['key'], $plist_info);
+ $this->assertArrayHasKey($channel3_info['key'], $plist_info);
+ }
+
+ public function testPersistentChannelTwoUpperBoundOutBound3()
+ {
+ $this->channel1 = new Grpc\Channel('localhost:10011', [
+ "grpc_target_persist_bound" => 2,
+ ]);
+ $channel1_info = $this->channel1->getChannelInfo();
+
+ $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
+ null);
+ $this->channel2 = new Grpc\Channel('localhost:10011',
+ ['credentials' => $channel_credentials]);
+ $this->channel2->getConnectivityState(true);
+ $this->waitUntilNotIdle($this->channel2);
+ $channel2_info = $this->channel2->getChannelInfo();
+ $this->assertConnecting($channel2_info['connectivity_status']);
+
+ // Only one channel will be deleted
+ $this->channel1->close();
+ $this->channel2->close();
+
+ $channel_credentials = Grpc\ChannelCredentials::createSsl("a", null,
+ null);
+ $this->channel3 = new Grpc\Channel('localhost:10011',
+ ['credentials' => $channel_credentials]);
+ $channel3_info = $this->channel3->getChannelInfo();
+
+ // Only the Idle Channel will be deleted
+ $plist_info = $this->channel1->getPersistentList();
+ $this->assertEquals(2, count($plist_info));
+ $this->assertArrayNotHasKey($channel1_info['key'], $plist_info);
+ $this->assertArrayHasKey($channel2_info['key'], $plist_info);
+ $this->assertArrayHasKey($channel3_info['key'], $plist_info);
+ }
+
+ public function testPersistentChannelTwoUpperBoundOutBound4()
+ {
+ $this->channel1 = new Grpc\Channel('localhost:10011', [
+ "grpc_target_persist_bound" => 2,
+ ]);
+ $this->channel1->getConnectivityState(true);
+ $this->waitUntilNotIdle($this->channel1);
+ $channel1_info = $this->channel1->getChannelInfo();
+ $this->assertConnecting($channel1_info['connectivity_status']);
+
+ $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
+ null);
+ $this->channel2 = new Grpc\Channel('localhost:10011',
+ ['credentials' => $channel_credentials]);
+ $this->channel2->getConnectivityState(true);
+ $this->waitUntilNotIdle($this->channel2);
+ $channel2_info = $this->channel2->getChannelInfo();
+ $this->assertConnecting($channel2_info['connectivity_status']);
+
+ $channel_credentials = Grpc\ChannelCredentials::createSsl("a", null,
+ null);
+ $this->channel3 = new Grpc\Channel('localhost:10011',
+ ['credentials' => $channel_credentials]);
+ $channel3_info = $this->channel3->getChannelInfo();
+
+ // Channel3 will not be persisted
+ $plist_info = $this->channel1->getPersistentList();
+ $this->assertEquals(2, count($plist_info));
+ $this->assertArrayHasKey($channel1_info['key'], $plist_info);
+ $this->assertArrayHasKey($channel2_info['key'], $plist_info);
+ $this->assertArrayNotHasKey($channel3_info['key'], $plist_info);
+ }
+}
diff --git a/src/php/tests/unit_tests/SecureEndToEndTest.php b/src/php/tests/unit_tests/SecureEndToEndTest.php
index e358abe2d2..dff4e878ea 100644
--- a/src/php/tests/unit_tests/SecureEndToEndTest.php
+++ b/src/php/tests/unit_tests/SecureEndToEndTest.php
@@ -44,9 +44,6 @@ class SecureEndToEndTest extends PHPUnit_Framework_TestCase
public function tearDown()
{
$this->channel->close();
- $channel_clean_persistent =
- new Grpc\Channel('localhost:50010', []);
- $channel_clean_persistent->cleanPersistentList();
}
public function testSimpleRequestBody()
diff --git a/src/php/tests/unit_tests/ServerTest.php b/src/php/tests/unit_tests/ServerTest.php
index d18feecefe..ac6f2f0312 100644
--- a/src/php/tests/unit_tests/ServerTest.php
+++ b/src/php/tests/unit_tests/ServerTest.php
@@ -27,9 +27,6 @@ class ServerTest extends PHPUnit_Framework_TestCase
public function tearDown()
{
unset($this->server);
- $channel_clean_persistent =
- new Grpc\Channel('localhost:50010', []);
- $channel_clean_persistent->cleanPersistentList();
}
public function testConstructorWithNull()
@@ -102,6 +99,24 @@ class ServerTest extends PHPUnit_Framework_TestCase
/**
* @expectedException InvalidArgumentException
*/
+ public function testInvalidConstructorWithNumKeyOfArray()
+ {
+ $this->server = new Grpc\Server([10 => '127.0.0.1',
+ 20 => '8080', ]);
+ $this->assertNull($this->server);
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testInvalidConstructorWithList()
+ {
+ $this->server = new Grpc\Server(['127.0.0.1', '8080']);
+ $this->assertNull($this->server);
+ }
+ /**
+ * @expectedException InvalidArgumentException
+ */
public function testInvalidAddHttp2Port()
{
$this->server = new Grpc\Server([]);
diff --git a/src/php/tests/unit_tests/TimevalTest.php b/src/php/tests/unit_tests/TimevalTest.php
index be023adace..bc307ef7f1 100644
--- a/src/php/tests/unit_tests/TimevalTest.php
+++ b/src/php/tests/unit_tests/TimevalTest.php
@@ -25,9 +25,6 @@ class TimevalTest extends PHPUnit_Framework_TestCase
public function tearDown()
{
unset($this->time);
- $channel_clean_persistent =
- new Grpc\Channel('localhost:50010', []);
- $channel_clean_persistent->cleanPersistentList();
}
public function testConstructorWithInt()
diff --git a/src/proto/grpc/health/v1/health.proto b/src/proto/grpc/health/v1/health.proto
index 3fda02c2c3..4b4677b8a4 100644
--- a/src/proto/grpc/health/v1/health.proto
+++ b/src/proto/grpc/health/v1/health.proto
@@ -1,4 +1,4 @@
-// Copyright 2015 gRPC authors.
+// Copyright 2015 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,10 +12,18 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// The canonical version of this proto can be found at
+// https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto
+
syntax = "proto3";
package grpc.health.v1;
+
option csharp_namespace = "Grpc.Health.V1";
+option go_package = "google.golang.org/grpc/health/grpc_health_v1";
+option java_multiple_files = true;
+option java_outer_classname = "HealthProto";
+option java_package = "io.grpc.health.v1";
message HealthCheckRequest {
string service = 1;
diff --git a/src/proto/grpc/lb/v1/load_balancer.proto b/src/proto/grpc/lb/v1/load_balancer.proto
index 75c916defa..3e0a4b2c97 100644
--- a/src/proto/grpc/lb/v1/load_balancer.proto
+++ b/src/proto/grpc/lb/v1/load_balancer.proto
@@ -62,8 +62,10 @@ message LoadBalanceRequest {
}
message InitialLoadBalanceRequest {
- // Name of load balanced service (IE, balancer.service.com)
- // length should be less than 256 bytes.
+ // The name of the load balanced service (e.g., balancer.service.com). The max
+ // length of the name is 256 bytes.
+ // The name might include a port number. How to handle the port number is up
+ // to the balancer.
string name = 1;
}
diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py
index 7fa7303691..b7ed0c8563 100644
--- a/src/python/grpcio/grpc/__init__.py
+++ b/src/python/grpcio/grpc/__init__.py
@@ -813,7 +813,11 @@ class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)):
class Channel(six.with_metaclass(abc.ABCMeta)):
- """Affords RPC invocation via generic methods on client-side."""
+ """Affords RPC invocation via generic methods on client-side.
+
+ Channel objects implement the Context Manager type, although they need not
+ support being entered and exited multiple times.
+ """
@abc.abstractmethod
def subscribe(self, callback, try_to_connect=False):
@@ -926,6 +930,17 @@ class Channel(six.with_metaclass(abc.ABCMeta)):
"""
raise NotImplementedError()
+ @abc.abstractmethod
+ def close(self):
+ """Closes this Channel and releases all resources held by it.
+
+ Closing the Channel will immediately terminate all RPCs active with the
+ Channel and it is not valid to invoke new RPCs with the Channel.
+
+ This method is idempotent.
+ """
+ raise NotImplementedError()
+
########################## Service-Side Context ##############################
diff --git a/src/python/grpcio/grpc/_channel.py b/src/python/grpcio/grpc/_channel.py
index 2eff08aa57..2017d47130 100644
--- a/src/python/grpcio/grpc/_channel.py
+++ b/src/python/grpcio/grpc/_channel.py
@@ -58,6 +58,17 @@ _STREAM_STREAM_INITIAL_DUE = (
_CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE = (
'Exception calling channel subscription callback!')
+_OK_RENDEZVOUS_REPR_FORMAT = ('<_Rendezvous of RPC that terminated with:\n'
+ '\tstatus = {}\n'
+ '\tdetails = "{}"\n'
+ '>')
+
+_NON_OK_RENDEZVOUS_REPR_FORMAT = ('<_Rendezvous of RPC that terminated with:\n'
+ '\tstatus = {}\n'
+ '\tdetails = "{}"\n'
+ '\tdebug_error_string = "{}"\n'
+ '>')
+
def _deadline(timeout):
return None if timeout is None else time.time() + timeout
@@ -79,27 +90,6 @@ def _wait_once_until(condition, until):
condition.wait(timeout=remaining)
-_INTERNAL_CALL_ERROR_MESSAGE_FORMAT = (
- 'Internal gRPC call error %d. ' +
- 'Please report to https://github.com/grpc/grpc/issues')
-
-
-def _check_call_error(call_error, metadata):
- if call_error == cygrpc.CallError.invalid_metadata:
- raise ValueError('metadata was invalid: %s' % metadata)
- elif call_error != cygrpc.CallError.ok:
- raise ValueError(_INTERNAL_CALL_ERROR_MESSAGE_FORMAT % call_error)
-
-
-def _call_error_set_RPCstate(state, call_error, metadata):
- if call_error == cygrpc.CallError.invalid_metadata:
- _abort(state, grpc.StatusCode.INTERNAL,
- 'metadata was invalid: %s' % metadata)
- else:
- _abort(state, grpc.StatusCode.INTERNAL,
- _INTERNAL_CALL_ERROR_MESSAGE_FORMAT % call_error)
-
-
class _RPCState(object):
def __init__(self, due, initial_metadata, trailing_metadata, code, details):
@@ -112,6 +102,7 @@ class _RPCState(object):
self.trailing_metadata = trailing_metadata
self.code = code
self.details = details
+ self.debug_error_string = None
# The semantics of grpc.Future.cancel and grpc.Future.cancelled are
# slightly wonky, so they have to be tracked separately from the rest of the
# result of the RPC. This field tracks whether cancellation was requested
@@ -158,12 +149,13 @@ def _handle_event(event, state, response_deserializer):
else:
state.code = code
state.details = batch_operation.details()
+ state.debug_error_string = batch_operation.error_string()
callbacks.extend(state.callbacks)
state.callbacks = None
return callbacks
-def _event_handler(state, call, response_deserializer):
+def _event_handler(state, response_deserializer):
def handle_event(event):
with state.condition:
@@ -172,40 +164,47 @@ def _event_handler(state, call, response_deserializer):
done = not state.due
for callback in callbacks:
callback()
- return call if done else None
+ return done
return handle_event
-def _consume_request_iterator(request_iterator, state, call,
- request_serializer):
- event_handler = _event_handler(state, call, None)
+def _consume_request_iterator(request_iterator, state, call, request_serializer,
+ event_handler):
- def consume_request_iterator():
+ def consume_request_iterator(): # pylint: disable=too-many-branches
while True:
try:
request = next(request_iterator)
except StopIteration:
break
except Exception: # pylint: disable=broad-except
- logging.exception("Exception iterating requests!")
- call.cancel()
- _abort(state, grpc.StatusCode.UNKNOWN,
- "Exception iterating requests!")
+ code = grpc.StatusCode.UNKNOWN
+ details = 'Exception iterating requests!'
+ logging.exception(details)
+ call.cancel(_common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[code],
+ details)
+ _abort(state, code, details)
return
serialized_request = _common.serialize(request, request_serializer)
with state.condition:
if state.code is None and not state.cancelled:
if serialized_request is None:
- call.cancel()
+ code = grpc.StatusCode.INTERNAL # pylint: disable=redefined-variable-type
details = 'Exception serializing request!'
- _abort(state, grpc.StatusCode.INTERNAL, details)
+ call.cancel(
+ _common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[code],
+ details)
+ _abort(state, code, details)
return
else:
operations = (cygrpc.SendMessageOperation(
serialized_request, _EMPTY_FLAGS),)
- call.start_client_batch(operations, event_handler)
- state.due.add(cygrpc.OperationType.send_message)
+ operating = call.operate(operations, event_handler)
+ if operating:
+ state.due.add(cygrpc.OperationType.send_message)
+ else:
+ return
while True:
state.condition.wait()
if state.code is None:
@@ -219,19 +218,12 @@ def _consume_request_iterator(request_iterator, state, call,
if state.code is None:
operations = (
cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),)
- call.start_client_batch(operations, event_handler)
- state.due.add(cygrpc.OperationType.send_close_from_client)
-
- def stop_consumption_thread(timeout): # pylint: disable=unused-argument
- with state.condition:
- if state.code is None:
- call.cancel()
- state.cancelled = True
- _abort(state, grpc.StatusCode.CANCELLED, 'Cancelled!')
- state.condition.notify_all()
+ operating = call.operate(operations, event_handler)
+ if operating:
+ state.due.add(cygrpc.OperationType.send_close_from_client)
- consumption_thread = _common.CleanupThread(
- stop_consumption_thread, target=consume_request_iterator)
+ consumption_thread = threading.Thread(target=consume_request_iterator)
+ consumption_thread.daemon = True
consumption_thread.start()
@@ -247,9 +239,12 @@ class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call):
def cancel(self):
with self._state.condition:
if self._state.code is None:
- self._call.cancel()
+ code = grpc.StatusCode.CANCELLED
+ details = 'Locally cancelled by application!'
+ self._call.cancel(
+ _common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[code], details)
self._state.cancelled = True
- _abort(self._state, grpc.StatusCode.CANCELLED, 'Cancelled!')
+ _abort(self._state, code, details)
self._state.condition.notify_all()
return False
@@ -318,12 +313,13 @@ class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call):
def _next(self):
with self._state.condition:
if self._state.code is None:
- event_handler = _event_handler(self._state, self._call,
+ event_handler = _event_handler(self._state,
self._response_deserializer)
- self._call.start_client_batch(
+ operating = self._call.operate(
(cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),),
event_handler)
- self._state.due.add(cygrpc.OperationType.receive_message)
+ if operating:
+ self._state.due.add(cygrpc.OperationType.receive_message)
elif self._state.code is grpc.StatusCode.OK:
raise StopIteration()
else:
@@ -391,13 +387,23 @@ class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call):
self._state.condition.wait()
return _common.decode(self._state.details)
+ def debug_error_string(self):
+ with self._state.condition:
+ while self._state.debug_error_string is None:
+ self._state.condition.wait()
+ return _common.decode(self._state.debug_error_string)
+
def _repr(self):
with self._state.condition:
if self._state.code is None:
return '<_Rendezvous object of in-flight RPC>'
+ elif self._state.code is grpc.StatusCode.OK:
+ return _OK_RENDEZVOUS_REPR_FORMAT.format(
+ self._state.code, self._state.details)
else:
- return '<_Rendezvous of RPC that terminated with ({}, {})>'.format(
- self._state.code, _common.decode(self._state.details))
+ return _NON_OK_RENDEZVOUS_REPR_FORMAT.format(
+ self._state.code, self._state.details,
+ self._state.debug_error_string)
def __repr__(self):
return self._repr()
@@ -408,9 +414,12 @@ class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call):
def __del__(self):
with self._state.condition:
if self._state.code is None:
- self._call.cancel()
- self._state.cancelled = True
self._state.code = grpc.StatusCode.CANCELLED
+ self._state.details = 'Cancelled upon garbage collection!'
+ self._state.cancelled = True
+ self._call.cancel(
+ _common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[self._state.code],
+ self._state.details)
self._state.condition.notify_all()
@@ -437,6 +446,24 @@ def _end_unary_response_blocking(state, call, with_call, deadline):
raise _Rendezvous(state, None, None, deadline)
+def _stream_unary_invocation_operationses(metadata):
+ return (
+ (
+ cygrpc.SendInitialMetadataOperation(metadata, _EMPTY_FLAGS),
+ cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
+ cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
+ ),
+ (cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),),
+ )
+
+
+def _stream_unary_invocation_operationses_and_tags(metadata):
+ return tuple((
+ operations,
+ None,
+ ) for operations in _stream_unary_invocation_operationses(metadata))
+
+
class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable):
def __init__(self, channel, managed_call, method, request_serializer,
@@ -448,8 +475,8 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable):
self._response_deserializer = response_deserializer
def _prepare(self, request, timeout, metadata):
- deadline, serialized_request, rendezvous = (_start_unary_request(
- request, timeout, self._request_serializer))
+ deadline, serialized_request, rendezvous = _start_unary_request(
+ request, timeout, self._request_serializer)
if serialized_request is None:
return None, None, None, rendezvous
else:
@@ -467,48 +494,38 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable):
def _blocking(self, request, timeout, metadata, credentials):
state, operations, deadline, rendezvous = self._prepare(
request, timeout, metadata)
- if rendezvous:
+ if state is None:
raise rendezvous
else:
- completion_queue = cygrpc.CompletionQueue()
- call = self._channel.create_call(None, 0, completion_queue,
- self._method, None, deadline)
- if credentials is not None:
- call.set_credentials(credentials._credentials)
- call_error = call.start_client_batch(operations, None)
- _check_call_error(call_error, metadata)
- _handle_event(completion_queue.poll(), state,
- self._response_deserializer)
- return state, call, deadline
+ call = self._channel.segregated_call(
+ 0, self._method, None, deadline, metadata, None
+ if credentials is None else credentials._credentials, ((
+ operations,
+ None,
+ ),))
+ event = call.next_event()
+ _handle_event(event, state, self._response_deserializer)
+ return state, call,
def __call__(self, request, timeout=None, metadata=None, credentials=None):
- state, call, deadline = self._blocking(request, timeout, metadata,
- credentials)
- return _end_unary_response_blocking(state, call, False, deadline)
+ state, call, = self._blocking(request, timeout, metadata, credentials)
+ return _end_unary_response_blocking(state, call, False, None)
def with_call(self, request, timeout=None, metadata=None, credentials=None):
- state, call, deadline = self._blocking(request, timeout, metadata,
- credentials)
- return _end_unary_response_blocking(state, call, True, deadline)
+ state, call, = self._blocking(request, timeout, metadata, credentials)
+ return _end_unary_response_blocking(state, call, True, None)
def future(self, request, timeout=None, metadata=None, credentials=None):
state, operations, deadline, rendezvous = self._prepare(
request, timeout, metadata)
- if rendezvous:
- return rendezvous
+ if state is None:
+ raise rendezvous
else:
- call, drive_call = self._managed_call(None, 0, self._method, None,
- deadline)
- if credentials is not None:
- call.set_credentials(credentials._credentials)
- event_handler = _event_handler(state, call,
- self._response_deserializer)
- with state.condition:
- call_error = call.start_client_batch(operations, event_handler)
- if call_error != cygrpc.CallError.ok:
- _call_error_set_RPCstate(state, call_error, metadata)
- return _Rendezvous(state, None, None, deadline)
- drive_call()
+ event_handler = _event_handler(state, self._response_deserializer)
+ call = self._managed_call(
+ 0, self._method, None, deadline, metadata, None
+ if credentials is None else credentials._credentials,
+ (operations,), event_handler)
return _Rendezvous(state, call, self._response_deserializer,
deadline)
@@ -524,34 +541,27 @@ class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable):
self._response_deserializer = response_deserializer
def __call__(self, request, timeout=None, metadata=None, credentials=None):
- deadline, serialized_request, rendezvous = (_start_unary_request(
- request, timeout, self._request_serializer))
+ deadline, serialized_request, rendezvous = _start_unary_request(
+ request, timeout, self._request_serializer)
if serialized_request is None:
raise rendezvous
else:
state = _RPCState(_UNARY_STREAM_INITIAL_DUE, None, None, None, None)
- call, drive_call = self._managed_call(None, 0, self._method, None,
- deadline)
- if credentials is not None:
- call.set_credentials(credentials._credentials)
- event_handler = _event_handler(state, call,
- self._response_deserializer)
- with state.condition:
- call.start_client_batch(
- (cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),),
- event_handler)
- operations = (
+ operationses = (
+ (
cygrpc.SendInitialMetadataOperation(metadata, _EMPTY_FLAGS),
cygrpc.SendMessageOperation(serialized_request,
_EMPTY_FLAGS),
cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),
cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
- )
- call_error = call.start_client_batch(operations, event_handler)
- if call_error != cygrpc.CallError.ok:
- _call_error_set_RPCstate(state, call_error, metadata)
- return _Rendezvous(state, None, None, deadline)
- drive_call()
+ ),
+ (cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),),
+ )
+ event_handler = _event_handler(state, self._response_deserializer)
+ call = self._managed_call(
+ 0, self._method, None, deadline, metadata, None
+ if credentials is None else credentials._credentials,
+ operationses, event_handler)
return _Rendezvous(state, call, self._response_deserializer,
deadline)
@@ -569,49 +579,38 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable):
def _blocking(self, request_iterator, timeout, metadata, credentials):
deadline = _deadline(timeout)
state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None)
- completion_queue = cygrpc.CompletionQueue()
- call = self._channel.create_call(None, 0, completion_queue,
- self._method, None, deadline)
- if credentials is not None:
- call.set_credentials(credentials._credentials)
- with state.condition:
- call.start_client_batch(
- (cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),), None)
- operations = (
- cygrpc.SendInitialMetadataOperation(metadata, _EMPTY_FLAGS),
- cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
- cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
- )
- call_error = call.start_client_batch(operations, None)
- _check_call_error(call_error, metadata)
- _consume_request_iterator(request_iterator, state, call,
- self._request_serializer)
+ call = self._channel.segregated_call(
+ 0, self._method, None, deadline, metadata, None
+ if credentials is None else credentials._credentials,
+ _stream_unary_invocation_operationses_and_tags(metadata))
+ _consume_request_iterator(request_iterator, state, call,
+ self._request_serializer, None)
while True:
- event = completion_queue.poll()
+ event = call.next_event()
with state.condition:
_handle_event(event, state, self._response_deserializer)
state.condition.notify_all()
if not state.due:
break
- return state, call, deadline
+ return state, call,
def __call__(self,
request_iterator,
timeout=None,
metadata=None,
credentials=None):
- state, call, deadline = self._blocking(request_iterator, timeout,
- metadata, credentials)
- return _end_unary_response_blocking(state, call, False, deadline)
+ state, call, = self._blocking(request_iterator, timeout, metadata,
+ credentials)
+ return _end_unary_response_blocking(state, call, False, None)
def with_call(self,
request_iterator,
timeout=None,
metadata=None,
credentials=None):
- state, call, deadline = self._blocking(request_iterator, timeout,
- metadata, credentials)
- return _end_unary_response_blocking(state, call, True, deadline)
+ state, call, = self._blocking(request_iterator, timeout, metadata,
+ credentials)
+ return _end_unary_response_blocking(state, call, True, None)
def future(self,
request_iterator,
@@ -620,27 +619,13 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable):
credentials=None):
deadline = _deadline(timeout)
state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None)
- call, drive_call = self._managed_call(None, 0, self._method, None,
- deadline)
- if credentials is not None:
- call.set_credentials(credentials._credentials)
- event_handler = _event_handler(state, call, self._response_deserializer)
- with state.condition:
- call.start_client_batch(
- (cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),),
- event_handler)
- operations = (
- cygrpc.SendInitialMetadataOperation(metadata, _EMPTY_FLAGS),
- cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
- cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
- )
- call_error = call.start_client_batch(operations, event_handler)
- if call_error != cygrpc.CallError.ok:
- _call_error_set_RPCstate(state, call_error, metadata)
- return _Rendezvous(state, None, None, deadline)
- drive_call()
- _consume_request_iterator(request_iterator, state, call,
- self._request_serializer)
+ event_handler = _event_handler(state, self._response_deserializer)
+ call = self._managed_call(
+ 0, self._method, None, deadline, metadata, None
+ if credentials is None else credentials._credentials,
+ _stream_unary_invocation_operationses(metadata), event_handler)
+ _consume_request_iterator(request_iterator, state, call,
+ self._request_serializer, event_handler)
return _Rendezvous(state, call, self._response_deserializer, deadline)
@@ -661,26 +646,20 @@ class _StreamStreamMultiCallable(grpc.StreamStreamMultiCallable):
credentials=None):
deadline = _deadline(timeout)
state = _RPCState(_STREAM_STREAM_INITIAL_DUE, None, None, None, None)
- call, drive_call = self._managed_call(None, 0, self._method, None,
- deadline)
- if credentials is not None:
- call.set_credentials(credentials._credentials)
- event_handler = _event_handler(state, call, self._response_deserializer)
- with state.condition:
- call.start_client_batch(
- (cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),),
- event_handler)
- operations = (
+ operationses = (
+ (
cygrpc.SendInitialMetadataOperation(metadata, _EMPTY_FLAGS),
cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
- )
- call_error = call.start_client_batch(operations, event_handler)
- if call_error != cygrpc.CallError.ok:
- _call_error_set_RPCstate(state, call_error, metadata)
- return _Rendezvous(state, None, None, deadline)
- drive_call()
- _consume_request_iterator(request_iterator, state, call,
- self._request_serializer)
+ ),
+ (cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),),
+ )
+ event_handler = _event_handler(state, self._response_deserializer)
+ call = self._managed_call(
+ 0, self._method, None, deadline, metadata, None
+ if credentials is None else credentials._credentials, operationses,
+ event_handler)
+ _consume_request_iterator(request_iterator, state, call,
+ self._request_serializer, event_handler)
return _Rendezvous(state, call, self._response_deserializer, deadline)
@@ -689,67 +668,63 @@ class _ChannelCallState(object):
def __init__(self, channel):
self.lock = threading.Lock()
self.channel = channel
- self.completion_queue = cygrpc.CompletionQueue()
- self.managed_calls = None
+ self.managed_calls = 0
def _run_channel_spin_thread(state):
def channel_spin():
while True:
- event = state.completion_queue.poll()
- completed_call = event.tag(event)
- if completed_call is not None:
+ event = state.channel.next_call_event()
+ call_completed = event.tag(event)
+ if call_completed:
with state.lock:
- state.managed_calls.remove(completed_call)
- if not state.managed_calls:
- state.managed_calls = None
+ state.managed_calls -= 1
+ if state.managed_calls == 0:
return
- def stop_channel_spin(timeout): # pylint: disable=unused-argument
- with state.lock:
- if state.managed_calls is not None:
- for call in state.managed_calls:
- call.cancel()
-
- channel_spin_thread = _common.CleanupThread(
- stop_channel_spin, target=channel_spin)
+ channel_spin_thread = threading.Thread(target=channel_spin)
+ channel_spin_thread.daemon = True
channel_spin_thread.start()
def _channel_managed_call_management(state):
- def create(parent, flags, method, host, deadline):
- """Creates a managed cygrpc.Call and a function to call to drive it.
-
- If operations are successfully added to the returned cygrpc.Call, the
- returned function must be called. If operations are not successfully added
- to the returned cygrpc.Call, the returned function must not be called.
-
- Args:
- parent: A cygrpc.Call to be used as the parent of the created call.
- flags: An integer bitfield of call flags.
- method: The RPC method.
- host: A host string for the created call.
- deadline: A float to be the deadline of the created call or None if the
- call is to have an infinite deadline.
-
- Returns:
- A cygrpc.Call with which to conduct an RPC and a function to call if
- operations are successfully started on the call.
- """
- call = state.channel.create_call(parent, flags, state.completion_queue,
- method, host, deadline)
-
- def drive():
- with state.lock:
- if state.managed_calls is None:
- state.managed_calls = set((call,))
- _run_channel_spin_thread(state)
- else:
- state.managed_calls.add(call)
+ # pylint: disable=too-many-arguments
+ def create(flags, method, host, deadline, metadata, credentials,
+ operationses, event_handler):
+ """Creates a cygrpc.IntegratedCall.
- return call, drive
+ Args:
+ flags: An integer bitfield of call flags.
+ method: The RPC method.
+ host: A host string for the created call.
+ deadline: A float to be the deadline of the created call or None if
+ the call is to have an infinite deadline.
+ metadata: The metadata for the call or None.
+ credentials: A cygrpc.CallCredentials or None.
+ operationses: An iterable of iterables of cygrpc.Operations to be
+ started on the call.
+ event_handler: A behavior to call to handle the events resultant from
+ the operations on the call.
+
+ Returns:
+ A cygrpc.IntegratedCall with which to conduct an RPC.
+ """
+ operationses_and_tags = tuple((
+ operations,
+ event_handler,
+ ) for operations in operationses)
+ with state.lock:
+ call = state.channel.integrated_call(flags, method, host, deadline,
+ metadata, credentials,
+ operationses_and_tags)
+ if state.managed_calls == 0:
+ state.managed_calls = 1
+ _run_channel_spin_thread(state)
+ else:
+ state.managed_calls += 1
+ return call
return create
@@ -819,12 +794,9 @@ def _poll_connectivity(state, channel, initial_try_to_connect):
callback_and_connectivity[1] = state.connectivity
if callbacks:
_spawn_delivery(state, callbacks)
- completion_queue = cygrpc.CompletionQueue()
while True:
- channel.watch_connectivity_state(connectivity,
- time.time() + 0.2, completion_queue,
- None)
- event = completion_queue.poll()
+ event = channel.watch_connectivity_state(connectivity,
+ time.time() + 0.2)
with state.lock:
if not state.callbacks_and_connectivities and not state.try_to_connect:
state.polling = False
@@ -855,10 +827,10 @@ def _moot(state):
def _subscribe(state, callback, try_to_connect):
with state.lock:
if not state.callbacks_and_connectivities and not state.polling:
- polling_thread = _common.CleanupThread(
- lambda timeout: _moot(state),
+ polling_thread = threading.Thread(
target=_poll_connectivity,
args=(state, state.channel, bool(try_to_connect)))
+ polling_thread.daemon = True
polling_thread.start()
state.polling = True
state.callbacks_and_connectivities.append([callback, None])
@@ -944,5 +916,28 @@ class Channel(grpc.Channel):
self._channel, _channel_managed_call_management(self._call_state),
_common.encode(method), request_serializer, response_deserializer)
+ def _close(self):
+ self._channel.close(cygrpc.StatusCode.cancelled, 'Channel closed!')
+ _moot(self._connectivity_state)
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self._close()
+ return False
+
+ def close(self):
+ self._close()
+
def __del__(self):
+ # TODO(https://github.com/grpc/grpc/issues/12531): Several releases
+ # after 1.12 (1.16 or thereabouts?) add a "self._channel.close" call
+ # here (or more likely, call self._close() here). We don't do this today
+ # because many valid use cases today allow the channel to be deleted
+ # immediately after stubs are created. After a sufficient period of time
+ # has passed for all users to be trusted to hang out to their channels
+ # for as long as they are in use and to close them after using them,
+ # then deletion of this grpc._channel.Channel instance can be made to
+ # effect closure of the underlying cygrpc.Channel instance.
_moot(self._connectivity_state)
diff --git a/src/python/grpcio/grpc/_common.py b/src/python/grpcio/grpc/_common.py
index bbb69ad489..862987a0cd 100644
--- a/src/python/grpcio/grpc/_common.py
+++ b/src/python/grpcio/grpc/_common.py
@@ -14,8 +14,6 @@
"""Shared implementation."""
import logging
-import threading
-import time
import six
@@ -101,35 +99,3 @@ def deserialize(serialized_message, deserializer):
def fully_qualified_method(group, method):
return '/{}/{}'.format(group, method)
-
-
-class CleanupThread(threading.Thread):
- """A threading.Thread subclass supporting custom behavior on join().
-
- On Python Interpreter exit, Python will attempt to join outstanding threads
- prior to garbage collection. We may need to do additional cleanup, and
- we accomplish this by overriding the join() method.
- """
-
- def __init__(self, behavior, *args, **kwargs):
- """Constructor.
-
- Args:
- behavior (function): Function called on join() with a single
- argument, timeout, indicating the maximum duration of
- `behavior`, or None indicating `behavior` has no deadline.
- `behavior` must be idempotent.
- args: Positional arguments passed to threading.Thread constructor.
- kwargs: Keyword arguments passed to threading.Thread constructor.
- """
- super(CleanupThread, self).__init__(*args, **kwargs)
- self._behavior = behavior
-
- def join(self, timeout=None):
- start_time = time.time()
- self._behavior(timeout)
- end_time = time.time()
- if timeout is not None:
- timeout -= end_time - start_time
- timeout = max(timeout, 0)
- super(CleanupThread, self).join(timeout)
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pxd.pxi
index 1ba76b7f83..eefc685c0b 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pxd.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pxd.pxi
@@ -13,9 +13,59 @@
# limitations under the License.
+cdef _check_call_error_no_metadata(c_call_error)
+
+
+cdef _check_and_raise_call_error_no_metadata(c_call_error)
+
+
+cdef _check_call_error(c_call_error, metadata)
+
+
+cdef class _CallState:
+
+ cdef grpc_call *c_call
+ cdef set due
+
+
+cdef class _ChannelState:
+
+ cdef object condition
+ cdef grpc_channel *c_channel
+ # A boolean field indicating that the channel is open (if True) or is being
+ # closed (i.e. a call to close is currently executing) or is closed (if
+ # False).
+ # TODO(https://github.com/grpc/grpc/issues/3064): Eliminate "is being closed"
+ # a state in which condition may be acquired by any thread, eliminate this
+ # field and just use the NULLness of c_channel as an indication that the
+ # channel is closed.
+ cdef object open
+
+ # A dict from _BatchOperationTag to _CallState
+ cdef dict integrated_call_states
+ cdef grpc_completion_queue *c_call_completion_queue
+
+ # A set of _CallState
+ cdef set segregated_call_states
+
+ cdef set connectivity_due
+ cdef grpc_completion_queue *c_connectivity_completion_queue
+
+
+cdef class IntegratedCall:
+
+ cdef _ChannelState _channel_state
+ cdef _CallState _call_state
+
+
+cdef class SegregatedCall:
+
+ cdef _ChannelState _channel_state
+ cdef _CallState _call_state
+ cdef grpc_completion_queue *_c_completion_queue
+
+
cdef class Channel:
cdef grpc_arg_pointer_vtable _vtable
- cdef grpc_channel *c_channel
- cdef list references
- cdef readonly _ArgumentsProcessor _arguments_processor
+ cdef _ChannelState _state
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
index a3966497bc..72e74e84ae 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
@@ -14,82 +14,439 @@
cimport cpython
+import threading
+
+_INTERNAL_CALL_ERROR_MESSAGE_FORMAT = (
+ 'Internal gRPC call error %d. ' +
+ 'Please report to https://github.com/grpc/grpc/issues')
+
+
+cdef str _call_error_metadata(metadata):
+ return 'metadata was invalid: %s' % metadata
+
+
+cdef str _call_error_no_metadata(c_call_error):
+ return _INTERNAL_CALL_ERROR_MESSAGE_FORMAT % c_call_error
+
+
+cdef str _call_error(c_call_error, metadata):
+ if c_call_error == GRPC_CALL_ERROR_INVALID_METADATA:
+ return _call_error_metadata(metadata)
+ else:
+ return _call_error_no_metadata(c_call_error)
+
+
+cdef _check_call_error_no_metadata(c_call_error):
+ if c_call_error != GRPC_CALL_OK:
+ return _INTERNAL_CALL_ERROR_MESSAGE_FORMAT % c_call_error
+ else:
+ return None
+
+
+cdef _check_and_raise_call_error_no_metadata(c_call_error):
+ error = _check_call_error_no_metadata(c_call_error)
+ if error is not None:
+ raise ValueError(error)
+
+
+cdef _check_call_error(c_call_error, metadata):
+ if c_call_error == GRPC_CALL_ERROR_INVALID_METADATA:
+ return _call_error_metadata(metadata)
+ else:
+ return _check_call_error_no_metadata(c_call_error)
+
+
+cdef void _raise_call_error_no_metadata(c_call_error) except *:
+ raise ValueError(_call_error_no_metadata(c_call_error))
+
+
+cdef void _raise_call_error(c_call_error, metadata) except *:
+ raise ValueError(_call_error(c_call_error, metadata))
+
+
+cdef _destroy_c_completion_queue(grpc_completion_queue *c_completion_queue):
+ grpc_completion_queue_shutdown(c_completion_queue)
+ grpc_completion_queue_destroy(c_completion_queue)
+
+
+cdef class _CallState:
+
+ def __cinit__(self):
+ self.due = set()
+
+
+cdef class _ChannelState:
+
+ def __cinit__(self):
+ self.condition = threading.Condition()
+ self.open = True
+ self.integrated_call_states = {}
+ self.segregated_call_states = set()
+ self.connectivity_due = set()
+
+
+cdef tuple _operate(grpc_call *c_call, object operations, object user_tag):
+ cdef grpc_call_error c_call_error
+ cdef _BatchOperationTag tag = _BatchOperationTag(user_tag, operations, None)
+ tag.prepare()
+ cpython.Py_INCREF(tag)
+ with nogil:
+ c_call_error = grpc_call_start_batch(
+ c_call, tag.c_ops, tag.c_nops, <cpython.PyObject *>tag, NULL)
+ return c_call_error, tag
+
+
+cdef object _operate_from_integrated_call(
+ _ChannelState channel_state, _CallState call_state, object operations,
+ object user_tag):
+ cdef grpc_call_error c_call_error
+ cdef _BatchOperationTag tag
+ with channel_state.condition:
+ if call_state.due:
+ c_call_error, tag = _operate(call_state.c_call, operations, user_tag)
+ if c_call_error == GRPC_CALL_OK:
+ call_state.due.add(tag)
+ channel_state.integrated_call_states[tag] = call_state
+ return True
+ else:
+ _raise_call_error_no_metadata(c_call_error)
+ else:
+ return False
+
+
+cdef object _operate_from_segregated_call(
+ _ChannelState channel_state, _CallState call_state, object operations,
+ object user_tag):
+ cdef grpc_call_error c_call_error
+ cdef _BatchOperationTag tag
+ with channel_state.condition:
+ if call_state.due:
+ c_call_error, tag = _operate(call_state.c_call, operations, user_tag)
+ if c_call_error == GRPC_CALL_OK:
+ call_state.due.add(tag)
+ return True
+ else:
+ _raise_call_error_no_metadata(c_call_error)
+ else:
+ return False
+
+
+cdef _cancel(
+ _ChannelState channel_state, _CallState call_state, grpc_status_code code,
+ str details):
+ cdef grpc_call_error c_call_error
+ with channel_state.condition:
+ if call_state.due:
+ c_call_error = grpc_call_cancel_with_status(
+ call_state.c_call, code, _encode(details), NULL)
+ _check_and_raise_call_error_no_metadata(c_call_error)
+
+
+cdef BatchOperationEvent _next_call_event(
+ _ChannelState channel_state, grpc_completion_queue *c_completion_queue,
+ on_success):
+ tag, event = _latent_event(c_completion_queue, None)
+ with channel_state.condition:
+ on_success(tag)
+ channel_state.condition.notify_all()
+ return event
+
+
+# TODO(https://github.com/grpc/grpc/issues/14569): This could be a lot simpler.
+cdef void _call(
+ _ChannelState channel_state, _CallState call_state,
+ grpc_completion_queue *c_completion_queue, on_success, int flags, method,
+ host, object deadline, CallCredentials credentials,
+ object operationses_and_user_tags, object metadata) except *:
+ """Invokes an RPC.
+
+ Args:
+ channel_state: A _ChannelState with its "open" attribute set to True. RPCs
+ may not be invoked on a closed channel.
+ call_state: An empty _CallState to be altered (specifically assigned a
+ c_call and having its due set populated) if the RPC invocation is
+ successful.
+ c_completion_queue: A grpc_completion_queue to be used for the call's
+ operations.
+ on_success: A behavior to be called if attempting to start operations for
+ the call succeeds. If called the behavior will be called while holding the
+ channel_state condition and passed the tags associated with operations
+ that were successfully started for the call.
+ flags: Flags to be passed to gRPC Core as part of call creation.
+ method: The fully-qualified name of the RPC method being invoked.
+ host: A "host" string to be passed to gRPC Core as part of call creation.
+ deadline: A float for the deadline of the RPC, or None if the RPC is to have
+ no deadline.
+ credentials: A _CallCredentials for the RPC or None.
+ operationses_and_user_tags: A sequence of length-two sequences the first
+ element of which is a sequence of Operations and the second element of
+ which is an object to be used as a tag. A SendInitialMetadataOperation
+ must be present in the first element of this value.
+ metadata: The metadata for this call.
+ """
+ cdef grpc_slice method_slice
+ cdef grpc_slice host_slice
+ cdef grpc_slice *host_slice_ptr
+ cdef grpc_call_credentials *c_call_credentials
+ cdef grpc_call_error c_call_error
+ cdef tuple error_and_wrapper_tag
+ cdef _BatchOperationTag wrapper_tag
+ with channel_state.condition:
+ if channel_state.open:
+ method_slice = _slice_from_bytes(method)
+ if host is None:
+ host_slice_ptr = NULL
+ else:
+ host_slice = _slice_from_bytes(host)
+ host_slice_ptr = &host_slice
+ call_state.c_call = grpc_channel_create_call(
+ channel_state.c_channel, NULL, flags,
+ c_completion_queue, method_slice, host_slice_ptr,
+ _timespec_from_time(deadline), NULL)
+ grpc_slice_unref(method_slice)
+ if host_slice_ptr:
+ grpc_slice_unref(host_slice)
+ if credentials is not None:
+ c_call_credentials = credentials.c()
+ c_call_error = grpc_call_set_credentials(
+ call_state.c_call, c_call_credentials)
+ grpc_call_credentials_release(c_call_credentials)
+ if c_call_error != GRPC_CALL_OK:
+ grpc_call_unref(call_state.c_call)
+ call_state.c_call = NULL
+ _raise_call_error_no_metadata(c_call_error)
+ started_tags = set()
+ for operations, user_tag in operationses_and_user_tags:
+ c_call_error, tag = _operate(call_state.c_call, operations, user_tag)
+ if c_call_error == GRPC_CALL_OK:
+ started_tags.add(tag)
+ else:
+ grpc_call_cancel(call_state.c_call, NULL)
+ grpc_call_unref(call_state.c_call)
+ call_state.c_call = NULL
+ _raise_call_error(c_call_error, metadata)
+ else:
+ call_state.due.update(started_tags)
+ on_success(started_tags)
+ else:
+ raise ValueError('Cannot invoke RPC on closed channel!')
+
+cdef void _process_integrated_call_tag(
+ _ChannelState state, _BatchOperationTag tag) except *:
+ cdef _CallState call_state = state.integrated_call_states.pop(tag)
+ call_state.due.remove(tag)
+ if not call_state.due:
+ grpc_call_unref(call_state.c_call)
+ call_state.c_call = NULL
+
+
+cdef class IntegratedCall:
+
+ def __cinit__(self, _ChannelState channel_state, _CallState call_state):
+ self._channel_state = channel_state
+ self._call_state = call_state
+
+ def operate(self, operations, tag):
+ return _operate_from_integrated_call(
+ self._channel_state, self._call_state, operations, tag)
+
+ def cancel(self, code, details):
+ _cancel(self._channel_state, self._call_state, code, details)
+
+
+cdef IntegratedCall _integrated_call(
+ _ChannelState state, int flags, method, host, object deadline,
+ object metadata, CallCredentials credentials, operationses_and_user_tags):
+ call_state = _CallState()
+
+ def on_success(started_tags):
+ for started_tag in started_tags:
+ state.integrated_call_states[started_tag] = call_state
+
+ _call(
+ state, call_state, state.c_call_completion_queue, on_success, flags,
+ method, host, deadline, credentials, operationses_and_user_tags, metadata)
+
+ return IntegratedCall(state, call_state)
+
+
+cdef object _process_segregated_call_tag(
+ _ChannelState state, _CallState call_state,
+ grpc_completion_queue *c_completion_queue, _BatchOperationTag tag):
+ call_state.due.remove(tag)
+ if not call_state.due:
+ grpc_call_unref(call_state.c_call)
+ call_state.c_call = NULL
+ state.segregated_call_states.remove(call_state)
+ _destroy_c_completion_queue(c_completion_queue)
+ return True
+ else:
+ return False
+
+
+cdef class SegregatedCall:
+
+ def __cinit__(self, _ChannelState channel_state, _CallState call_state):
+ self._channel_state = channel_state
+ self._call_state = call_state
+
+ def operate(self, operations, tag):
+ return _operate_from_segregated_call(
+ self._channel_state, self._call_state, operations, tag)
+
+ def cancel(self, code, details):
+ _cancel(self._channel_state, self._call_state, code, details)
+
+ def next_event(self):
+ def on_success(tag):
+ _process_segregated_call_tag(
+ self._channel_state, self._call_state, self._c_completion_queue, tag)
+ return _next_call_event(
+ self._channel_state, self._c_completion_queue, on_success)
+
+
+cdef SegregatedCall _segregated_call(
+ _ChannelState state, int flags, method, host, object deadline,
+ object metadata, CallCredentials credentials, operationses_and_user_tags):
+ cdef _CallState call_state = _CallState()
+ cdef grpc_completion_queue *c_completion_queue = (
+ grpc_completion_queue_create_for_next(NULL))
+ cdef SegregatedCall segregated_call
+
+ def on_success(started_tags):
+ state.segregated_call_states.add(call_state)
+
+ try:
+ _call(
+ state, call_state, c_completion_queue, on_success, flags, method, host,
+ deadline, credentials, operationses_and_user_tags, metadata)
+ except:
+ _destroy_c_completion_queue(c_completion_queue)
+ raise
+
+ segregated_call = SegregatedCall(state, call_state)
+ segregated_call._c_completion_queue = c_completion_queue
+ return segregated_call
+
+
+cdef object _watch_connectivity_state(
+ _ChannelState state, grpc_connectivity_state last_observed_state,
+ object deadline):
+ cdef _ConnectivityTag tag = _ConnectivityTag(object())
+ with state.condition:
+ if state.open:
+ cpython.Py_INCREF(tag)
+ grpc_channel_watch_connectivity_state(
+ state.c_channel, last_observed_state, _timespec_from_time(deadline),
+ state.c_connectivity_completion_queue, <cpython.PyObject *>tag)
+ state.connectivity_due.add(tag)
+ else:
+ raise ValueError('Cannot invoke RPC on closed channel!')
+ completed_tag, event = _latent_event(
+ state.c_connectivity_completion_queue, None)
+ with state.condition:
+ state.connectivity_due.remove(completed_tag)
+ state.condition.notify_all()
+ return event
+
+
+cdef _close(_ChannelState state, grpc_status_code code, object details):
+ cdef _CallState call_state
+ encoded_details = _encode(details)
+ with state.condition:
+ if state.open:
+ state.open = False
+ for call_state in set(state.integrated_call_states.values()):
+ grpc_call_cancel_with_status(
+ call_state.c_call, code, encoded_details, NULL)
+ for call_state in state.segregated_call_states:
+ grpc_call_cancel_with_status(
+ call_state.c_call, code, encoded_details, NULL)
+ # TODO(https://github.com/grpc/grpc/issues/3064): Cancel connectivity
+ # watching.
+
+ while state.integrated_call_states:
+ state.condition.wait()
+ while state.segregated_call_states:
+ state.condition.wait()
+ while state.connectivity_due:
+ state.condition.wait()
+
+ _destroy_c_completion_queue(state.c_call_completion_queue)
+ _destroy_c_completion_queue(state.c_connectivity_completion_queue)
+ grpc_channel_destroy(state.c_channel)
+ state.c_channel = NULL
+ grpc_shutdown()
+ state.condition.notify_all()
+ else:
+ # Another call to close already completed in the past or is currently
+ # being executed in another thread.
+ while state.c_channel != NULL:
+ state.condition.wait()
+
cdef class Channel:
- def __cinit__(self, bytes target, object arguments,
- ChannelCredentials channel_credentials=None):
+ def __cinit__(
+ self, bytes target, object arguments,
+ ChannelCredentials channel_credentials):
grpc_init()
+ self._state = _ChannelState()
self._vtable.copy = &_copy_pointer
self._vtable.destroy = &_destroy_pointer
self._vtable.cmp = &_compare_pointer
cdef _ArgumentsProcessor arguments_processor = _ArgumentsProcessor(
arguments)
cdef grpc_channel_args *c_arguments = arguments_processor.c(&self._vtable)
- self.references = []
- c_target = target
if channel_credentials is None:
- self.c_channel = grpc_insecure_channel_create(c_target, c_arguments, NULL)
+ self._state.c_channel = grpc_insecure_channel_create(
+ <char *>target, c_arguments, NULL)
else:
c_channel_credentials = channel_credentials.c()
- self.c_channel = grpc_secure_channel_create(
- c_channel_credentials, c_target, c_arguments, NULL)
+ self._state.c_channel = grpc_secure_channel_create(
+ c_channel_credentials, <char *>target, c_arguments, NULL)
grpc_channel_credentials_release(c_channel_credentials)
- arguments_processor.un_c()
- self.references.append(target)
- self.references.append(arguments)
-
- def create_call(self, Call parent, int flags,
- CompletionQueue queue not None,
- method, host, object deadline):
- if queue.is_shutting_down:
- raise ValueError("queue must not be shutting down or shutdown")
- cdef grpc_slice method_slice = _slice_from_bytes(method)
- cdef grpc_slice host_slice
- cdef grpc_slice *host_slice_ptr = NULL
- if host is not None:
- host_slice = _slice_from_bytes(host)
- host_slice_ptr = &host_slice
- cdef Call operation_call = Call()
- operation_call.references = [self, queue]
- cdef grpc_call *parent_call = NULL
- if parent is not None:
- parent_call = parent.c_call
- operation_call.c_call = grpc_channel_create_call(
- self.c_channel, parent_call, flags,
- queue.c_completion_queue, method_slice, host_slice_ptr,
- _timespec_from_time(deadline), NULL)
- grpc_slice_unref(method_slice)
- if host_slice_ptr:
- grpc_slice_unref(host_slice)
- return operation_call
+ self._state.c_call_completion_queue = (
+ grpc_completion_queue_create_for_next(NULL))
+ self._state.c_connectivity_completion_queue = (
+ grpc_completion_queue_create_for_next(NULL))
+
+ def target(self):
+ cdef char *c_target
+ with self._state.condition:
+ c_target = grpc_channel_get_target(self._state.c_channel)
+ target = <bytes>c_target
+ gpr_free(c_target)
+ return target
+
+ def integrated_call(
+ self, int flags, method, host, object deadline, object metadata,
+ CallCredentials credentials, operationses_and_tags):
+ return _integrated_call(
+ self._state, flags, method, host, deadline, metadata, credentials,
+ operationses_and_tags)
+
+ def next_call_event(self):
+ def on_success(tag):
+ _process_integrated_call_tag(self._state, tag)
+ return _next_call_event(
+ self._state, self._state.c_call_completion_queue, on_success)
+
+ def segregated_call(
+ self, int flags, method, host, object deadline, object metadata,
+ CallCredentials credentials, operationses_and_tags):
+ return _segregated_call(
+ self._state, flags, method, host, deadline, metadata, credentials,
+ operationses_and_tags)
def check_connectivity_state(self, bint try_to_connect):
- cdef grpc_connectivity_state result
- with nogil:
- result = grpc_channel_check_connectivity_state(self.c_channel,
- try_to_connect)
- return result
+ with self._state.condition:
+ return grpc_channel_check_connectivity_state(
+ self._state.c_channel, try_to_connect)
def watch_connectivity_state(
- self, grpc_connectivity_state last_observed_state,
- object deadline, CompletionQueue queue not None, tag):
- cdef _ConnectivityTag connectivity_tag = _ConnectivityTag(tag)
- cpython.Py_INCREF(connectivity_tag)
- grpc_channel_watch_connectivity_state(
- self.c_channel, last_observed_state, _timespec_from_time(deadline),
- queue.c_completion_queue, <cpython.PyObject *>connectivity_tag)
+ self, grpc_connectivity_state last_observed_state, object deadline):
+ return _watch_connectivity_state(self._state, last_observed_state, deadline)
- def target(self):
- cdef char *target = NULL
- with nogil:
- target = grpc_channel_get_target(self.c_channel)
- result = <bytes>target
- with nogil:
- gpr_free(target)
- return result
-
- def __dealloc__(self):
- if self.c_channel != NULL:
- grpc_channel_destroy(self.c_channel)
- grpc_shutdown()
+ def close(self, code, details):
+ _close(self._state, code, details)
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd.pxi
index 5ea0287b81..9f06ce086e 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd.pxi
@@ -13,10 +13,16 @@
# limitations under the License.
+cdef grpc_event _next(grpc_completion_queue *c_completion_queue, deadline)
+
+
+cdef _interpret_event(grpc_event c_event)
+
+
cdef class CompletionQueue:
cdef grpc_completion_queue *c_completion_queue
cdef bint is_shutting_down
cdef bint is_shutdown
- cdef _interpret_event(self, grpc_event event)
+ cdef _interpret_event(self, grpc_event c_event)
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
index 40496d1124..a2d765546a 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
@@ -20,6 +20,53 @@ import time
cdef int _INTERRUPT_CHECK_PERIOD_MS = 200
+cdef grpc_event _next(grpc_completion_queue *c_completion_queue, deadline):
+ cdef gpr_timespec c_increment
+ cdef gpr_timespec c_timeout
+ cdef gpr_timespec c_deadline
+ c_increment = gpr_time_from_millis(_INTERRUPT_CHECK_PERIOD_MS, GPR_TIMESPAN)
+ if deadline is None:
+ c_deadline = gpr_inf_future(GPR_CLOCK_REALTIME)
+ else:
+ c_deadline = _timespec_from_time(deadline)
+
+ with nogil:
+ while True:
+ c_timeout = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c_increment)
+ if gpr_time_cmp(c_timeout, c_deadline) > 0:
+ c_timeout = c_deadline
+ c_event = grpc_completion_queue_next(c_completion_queue, c_timeout, NULL)
+ if (c_event.type != GRPC_QUEUE_TIMEOUT or
+ gpr_time_cmp(c_timeout, c_deadline) == 0):
+ break
+
+ # Handle any signals
+ with gil:
+ cpython.PyErr_CheckSignals()
+ return c_event
+
+
+cdef _interpret_event(grpc_event c_event):
+ cdef _Tag tag
+ if c_event.type == GRPC_QUEUE_TIMEOUT:
+ # NOTE(nathaniel): For now we coopt ConnectivityEvent here.
+ return None, ConnectivityEvent(GRPC_QUEUE_TIMEOUT, False, None)
+ elif c_event.type == GRPC_QUEUE_SHUTDOWN:
+ # NOTE(nathaniel): For now we coopt ConnectivityEvent here.
+ return None, ConnectivityEvent(GRPC_QUEUE_SHUTDOWN, False, None)
+ else:
+ tag = <_Tag>c_event.tag
+ # We receive event tags only after they've been inc-ref'd elsewhere in
+ # the code.
+ cpython.Py_DECREF(tag)
+ return tag, tag.event(c_event)
+
+
+cdef _latent_event(grpc_completion_queue *c_completion_queue, object deadline):
+ cdef grpc_event c_event = _next(c_completion_queue, deadline)
+ return _interpret_event(c_event)
+
+
cdef class CompletionQueue:
def __cinit__(self, shutdown_cq=False):
@@ -36,48 +83,16 @@ cdef class CompletionQueue:
self.is_shutting_down = False
self.is_shutdown = False
- cdef _interpret_event(self, grpc_event event):
- cdef _Tag tag = None
- if event.type == GRPC_QUEUE_TIMEOUT:
- # NOTE(nathaniel): For now we coopt ConnectivityEvent here.
- return ConnectivityEvent(GRPC_QUEUE_TIMEOUT, False, None)
- elif event.type == GRPC_QUEUE_SHUTDOWN:
+ cdef _interpret_event(self, grpc_event c_event):
+ unused_tag, event = _interpret_event(c_event)
+ if event.completion_type == GRPC_QUEUE_SHUTDOWN:
self.is_shutdown = True
- # NOTE(nathaniel): For now we coopt ConnectivityEvent here.
- return ConnectivityEvent(GRPC_QUEUE_TIMEOUT, True, None)
- else:
- tag = <_Tag>event.tag
- # We receive event tags only after they've been inc-ref'd elsewhere in
- # the code.
- cpython.Py_DECREF(tag)
- return tag.event(event)
+ return event
+ # We name this 'poll' to avoid problems with CPython's expectations for
+ # 'special' methods (like next and __next__).
def poll(self, deadline=None):
- # We name this 'poll' to avoid problems with CPython's expectations for
- # 'special' methods (like next and __next__).
- cdef gpr_timespec c_increment
- cdef gpr_timespec c_timeout
- cdef gpr_timespec c_deadline
- if deadline is None:
- c_deadline = gpr_inf_future(GPR_CLOCK_REALTIME)
- else:
- c_deadline = _timespec_from_time(deadline)
- with nogil:
- c_increment = gpr_time_from_millis(_INTERRUPT_CHECK_PERIOD_MS, GPR_TIMESPAN)
-
- while True:
- c_timeout = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c_increment)
- if gpr_time_cmp(c_timeout, c_deadline) > 0:
- c_timeout = c_deadline
- event = grpc_completion_queue_next(
- self.c_completion_queue, c_timeout, NULL)
- if event.type != GRPC_QUEUE_TIMEOUT or gpr_time_cmp(c_timeout, c_deadline) == 0:
- break;
-
- # Handle any signals
- with gil:
- cpython.PyErr_CheckSignals()
- return self._interpret_event(event)
+ return self._interpret_event(_next(self.c_completion_queue, deadline))
def shutdown(self):
with nogil:
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
index a4c0319553..2d6c900c54 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
@@ -291,6 +291,7 @@ cdef extern from "grpc/grpc.h":
grpc_metadata_array *trailing_metadata
grpc_status_code *status
grpc_slice *status_details
+ char** error_string
ctypedef struct grpc_op_data_recv_close_on_server:
int *cancelled
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/operation.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/operation.pxd.pxi
index bfbe27785b..69a2a4989e 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/operation.pxd.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/operation.pxd.pxi
@@ -91,9 +91,11 @@ cdef class ReceiveStatusOnClientOperation(Operation):
cdef grpc_metadata_array _c_trailing_metadata
cdef grpc_status_code _c_code
cdef grpc_slice _c_details
+ cdef const char* _c_error_string
cdef tuple _trailing_metadata
cdef object _code
cdef str _details
+ cdef str _error_string
cdef void c(self)
cdef void un_c(self)
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/operation.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/operation.pyx.pxi
index 239d0f3f95..454627f570 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/operation.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/operation.pyx.pxi
@@ -199,6 +199,8 @@ cdef class ReceiveStatusOnClientOperation(Operation):
&self._c_code)
self.c_op.data.receive_status_on_client.status_details = (
&self._c_details)
+ self.c_op.data.receive_status_on_client.error_string = (
+ &self._c_error_string)
cdef void un_c(self):
self._trailing_metadata = _metadata(&self._c_trailing_metadata)
@@ -206,6 +208,11 @@ cdef class ReceiveStatusOnClientOperation(Operation):
self._code = self._c_code
self._details = _decode(_slice_bytes(self._c_details))
grpc_slice_unref(self._c_details)
+ if self._c_error_string != NULL:
+ self._error_string = _decode(self._c_error_string)
+ gpr_free(<void*>self._c_error_string)
+ else:
+ self._error_string = ""
def trailing_metadata(self):
return self._trailing_metadata
@@ -216,6 +223,9 @@ cdef class ReceiveStatusOnClientOperation(Operation):
def details(self):
return self._details
+ def error_string(self):
+ return self._error_string
+
cdef class ReceiveCloseOnServerOperation(Operation):
diff --git a/src/python/grpcio/grpc/_grpcio_metadata.py b/src/python/grpcio/grpc/_grpcio_metadata.py
index cb5da72f1f..ad53f60ad3 100644
--- a/src/python/grpcio/grpc/_grpcio_metadata.py
+++ b/src/python/grpcio/grpc/_grpcio_metadata.py
@@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc/_grpcio_metadata.py.template`!!!
-__version__ = """1.12.0.dev0"""
+__version__ = """1.13.0.dev0"""
diff --git a/src/python/grpcio/grpc/_interceptor.py b/src/python/grpcio/grpc/_interceptor.py
index d029472c68..f465e35a9c 100644
--- a/src/python/grpcio/grpc/_interceptor.py
+++ b/src/python/grpcio/grpc/_interceptor.py
@@ -334,6 +334,19 @@ class _Channel(grpc.Channel):
else:
return thunk(method)
+ def _close(self):
+ self._channel.close()
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self._close()
+ return False
+
+ def close(self):
+ self._channel.close()
+
def intercept_channel(channel, *interceptors):
for interceptor in reversed(list(interceptors)):
diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py
index c988e0c87c..d849cadbee 100644
--- a/src/python/grpcio/grpc/_server.py
+++ b/src/python/grpcio/grpc/_server.py
@@ -780,14 +780,8 @@ def _start(state):
state.stage = _ServerStage.STARTED
_request_call(state)
- def cleanup_server(timeout):
- if timeout is None:
- _stop(state, _UNEXPECTED_EXIT_SERVER_GRACE).wait()
- else:
- _stop(state, timeout).wait()
-
- thread = _common.CleanupThread(
- cleanup_server, target=_serve, args=(state,))
+ thread = threading.Thread(target=_serve, args=(state,))
+ thread.daemon = True
thread.start()
diff --git a/src/python/grpcio/grpc/beta/_server_adaptations.py b/src/python/grpcio/grpc/beta/_server_adaptations.py
index 3c04fd7639..ccafec8951 100644
--- a/src/python/grpcio/grpc/beta/_server_adaptations.py
+++ b/src/python/grpcio/grpc/beta/_server_adaptations.py
@@ -168,11 +168,8 @@ def _run_request_pipe_thread(request_iterator, request_consumer,
return
request_consumer.terminate()
- def stop_request_pipe(timeout): # pylint: disable=unused-argument
- thread_joined.set()
-
- request_pipe_thread = _common.CleanupThread(
- stop_request_pipe, target=pipe_requests)
+ request_pipe_thread = threading.Thread(target=pipe_requests)
+ request_pipe_thread.daemon = True
request_pipe_thread.start()
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index a053609e39..6dee3b81f1 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -28,7 +28,6 @@ CORE_SOURCE_FILES = [
'src/core/lib/gpr/env_linux.cc',
'src/core/lib/gpr/env_posix.cc',
'src/core/lib/gpr/env_windows.cc',
- 'src/core/lib/gpr/fork.cc',
'src/core/lib/gpr/host_port.cc',
'src/core/lib/gpr/log.cc',
'src/core/lib/gpr/log_android.cc',
@@ -53,6 +52,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/gpr/tmpfile_posix.cc',
'src/core/lib/gpr/tmpfile_windows.cc',
'src/core/lib/gpr/wrap_memcpy.cc',
+ 'src/core/lib/gprpp/fork.cc',
'src/core/lib/gprpp/thd_posix.cc',
'src/core/lib/gprpp/thd_windows.cc',
'src/core/lib/profiling/basic_timers.cc',
@@ -64,7 +64,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/channel/channel_stack.cc',
'src/core/lib/channel/channel_stack_builder.cc',
'src/core/lib/channel/channel_trace.cc',
- 'src/core/lib/channel/channel_trace_registry.cc',
+ 'src/core/lib/channel/channelz_registry.cc',
'src/core/lib/channel/connected_channel.cc',
'src/core/lib/channel/handshaker.cc',
'src/core/lib/channel/handshaker_factory.cc',
@@ -300,7 +300,6 @@ CORE_SOURCE_FILES = [
'third_party/nanopb/pb_decode.c',
'third_party/nanopb/pb_encode.c',
'src/core/tsi/transport_security.cc',
- 'src/core/tsi/transport_security_adapter.cc',
'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
'src/core/ext/transport/chttp2/client/authority.cc',
@@ -348,7 +347,6 @@ CORE_SOURCE_FILES = [
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc',
'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
- 'src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc',
'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc',
diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py
index de5a780abd..57dc26dbeb 100644
--- a/src/python/grpcio/grpc_version.py
+++ b/src/python/grpcio/grpc_version.py
@@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!!
-VERSION = '1.12.0.dev0'
+VERSION = '1.13.0.dev0'
diff --git a/src/python/grpcio_health_checking/grpc_version.py b/src/python/grpcio_health_checking/grpc_version.py
index afcd316e5c..ba0d4a3b6d 100644
--- a/src/python/grpcio_health_checking/grpc_version.py
+++ b/src/python/grpcio_health_checking/grpc_version.py
@@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!!
-VERSION = '1.12.0.dev0'
+VERSION = '1.13.0.dev0'
diff --git a/src/python/grpcio_reflection/grpc_version.py b/src/python/grpcio_reflection/grpc_version.py
index 824b73201d..ea2878d9ee 100644
--- a/src/python/grpcio_reflection/grpc_version.py
+++ b/src/python/grpcio_reflection/grpc_version.py
@@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!!
-VERSION = '1.12.0.dev0'
+VERSION = '1.13.0.dev0'
diff --git a/src/python/grpcio_testing/grpc_testing/_channel/_channel.py b/src/python/grpcio_testing/grpc_testing/_channel/_channel.py
index b015b8d738..0c1941e6be 100644
--- a/src/python/grpcio_testing/grpc_testing/_channel/_channel.py
+++ b/src/python/grpcio_testing/grpc_testing/_channel/_channel.py
@@ -56,6 +56,21 @@ class TestingChannel(grpc_testing.Channel):
response_deserializer=None):
return _multi_callable.StreamStream(method, self._state)
+ def _close(self):
+ # TODO(https://github.com/grpc/grpc/issues/12531): Decide what
+ # action to take here, if any?
+ pass
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self._close()
+ return False
+
+ def close(self):
+ self._close()
+
def take_unary_unary(self, method_descriptor):
return _channel_rpc.unary_unary(self._state, method_descriptor)
diff --git a/src/python/grpcio_testing/grpc_version.py b/src/python/grpcio_testing/grpc_version.py
index 5b1f4c4cc0..02f19f2283 100644
--- a/src/python/grpcio_testing/grpc_version.py
+++ b/src/python/grpcio_testing/grpc_version.py
@@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_testing/grpc_version.py.template`!!!
-VERSION = '1.12.0.dev0'
+VERSION = '1.13.0.dev0'
diff --git a/src/python/grpcio_tests/grpc_version.py b/src/python/grpcio_tests/grpc_version.py
index 382f95018e..9d2e41644e 100644
--- a/src/python/grpcio_tests/grpc_version.py
+++ b/src/python/grpcio_tests/grpc_version.py
@@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!!
-VERSION = '1.12.0.dev0'
+VERSION = '1.13.0.dev0'
diff --git a/src/python/grpcio_tests/setup.py b/src/python/grpcio_tests/setup.py
index 98ac19d188..1262e48571 100644
--- a/src/python/grpcio_tests/setup.py
+++ b/src/python/grpcio_tests/setup.py
@@ -37,13 +37,16 @@ PACKAGE_DIRECTORIES = {
}
INSTALL_REQUIRES = (
- 'coverage>=4.0', 'enum34>=1.0.4', 'futures>=2.2.0',
+ 'coverage>=4.0', 'enum34>=1.0.4',
'grpcio>={version}'.format(version=grpc_version.VERSION),
'grpcio-tools>={version}'.format(version=grpc_version.VERSION),
'grpcio-health-checking>={version}'.format(version=grpc_version.VERSION),
'oauth2client>=1.4.7', 'protobuf>=3.5.2.post1', 'six>=1.10',
'google-auth>=1.0.0', 'requests>=2.14.2')
+if not PY3:
+ INSTALL_REQUIRES += ('futures>=2.2.0',)
+
COMMAND_CLASS = {
# Run `preprocess` *before* doing any packaging!
'preprocess': commands.GatherProto,
diff --git a/src/python/grpcio_tests/tests/tests.json b/src/python/grpcio_tests/tests/tests.json
index d38ee517f0..0d94426413 100644
--- a/src/python/grpcio_tests/tests/tests.json
+++ b/src/python/grpcio_tests/tests/tests.json
@@ -25,6 +25,7 @@
"unit._auth_test.AccessTokenAuthMetadataPluginTest",
"unit._auth_test.GoogleCallCredentialsTest",
"unit._channel_args_test.ChannelArgsTest",
+ "unit._channel_close_test.ChannelCloseTest",
"unit._channel_connectivity_test.ChannelConnectivityTest",
"unit._channel_ready_future_test.ChannelReadyFutureTest",
"unit._compression_test.CompressionTest",
@@ -52,7 +53,6 @@
"unit._server_ssl_cert_config_test.ServerSSLCertReloadTestCertConfigReuse",
"unit._server_ssl_cert_config_test.ServerSSLCertReloadTestWithClientAuth",
"unit._server_ssl_cert_config_test.ServerSSLCertReloadTestWithoutClientAuth",
- "unit._thread_cleanup_test.CleanupThreadTest",
"unit.beta._beta_features_test.BetaFeaturesTest",
"unit.beta._beta_features_test.ContextManagementAndLifecycleTest",
"unit.beta._connectivity_channel_test.ConnectivityStatesTest",
diff --git a/src/python/grpcio_tests/tests/unit/_channel_close_test.py b/src/python/grpcio_tests/tests/unit/_channel_close_test.py
new file mode 100644
index 0000000000..af3a9ee1ee
--- /dev/null
+++ b/src/python/grpcio_tests/tests/unit/_channel_close_test.py
@@ -0,0 +1,185 @@
+# Copyright 2018 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests server and client side compression."""
+
+import threading
+import time
+import unittest
+
+import grpc
+
+from tests.unit import test_common
+from tests.unit.framework.common import test_constants
+
+_BEAT = 0.5
+_SOME_TIME = 5
+_MORE_TIME = 10
+
+
+class _MethodHandler(grpc.RpcMethodHandler):
+
+ request_streaming = True
+ response_streaming = True
+ request_deserializer = None
+ response_serializer = None
+
+ def stream_stream(self, request_iterator, servicer_context):
+ for request in request_iterator:
+ yield request * 2
+
+
+_METHOD_HANDLER = _MethodHandler()
+
+
+class _GenericHandler(grpc.GenericRpcHandler):
+
+ def service(self, handler_call_details):
+ return _METHOD_HANDLER
+
+
+_GENERIC_HANDLER = _GenericHandler()
+
+
+class _Pipe(object):
+
+ def __init__(self, values):
+ self._condition = threading.Condition()
+ self._values = list(values)
+ self._open = True
+
+ def __iter__(self):
+ return self
+
+ def _next(self):
+ with self._condition:
+ while not self._values and self._open:
+ self._condition.wait()
+ if self._values:
+ return self._values.pop(0)
+ else:
+ raise StopIteration()
+
+ def next(self):
+ return self._next()
+
+ def __next__(self):
+ return self._next()
+
+ def add(self, value):
+ with self._condition:
+ self._values.append(value)
+ self._condition.notify()
+
+ def close(self):
+ with self._condition:
+ self._open = False
+ self._condition.notify()
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, type, value, traceback):
+ self.close()
+
+
+class ChannelCloseTest(unittest.TestCase):
+
+ def setUp(self):
+ self._server = test_common.test_server(
+ max_workers=test_constants.THREAD_CONCURRENCY)
+ self._server.add_generic_rpc_handlers((_GENERIC_HANDLER,))
+ self._port = self._server.add_insecure_port('[::]:0')
+ self._server.start()
+
+ def tearDown(self):
+ self._server.stop(None)
+
+ def test_close_immediately_after_call_invocation(self):
+ channel = grpc.insecure_channel('localhost:{}'.format(self._port))
+ multi_callable = channel.stream_stream('Meffod')
+ request_iterator = _Pipe(())
+ response_iterator = multi_callable(request_iterator)
+ channel.close()
+ request_iterator.close()
+
+ self.assertIs(response_iterator.code(), grpc.StatusCode.CANCELLED)
+
+ def test_close_while_call_active(self):
+ channel = grpc.insecure_channel('localhost:{}'.format(self._port))
+ multi_callable = channel.stream_stream('Meffod')
+ request_iterator = _Pipe((b'abc',))
+ response_iterator = multi_callable(request_iterator)
+ next(response_iterator)
+ channel.close()
+ request_iterator.close()
+
+ self.assertIs(response_iterator.code(), grpc.StatusCode.CANCELLED)
+
+ def test_context_manager_close_while_call_active(self):
+ with grpc.insecure_channel('localhost:{}'.format(
+ self._port)) as channel: # pylint: disable=bad-continuation
+ multi_callable = channel.stream_stream('Meffod')
+ request_iterator = _Pipe((b'abc',))
+ response_iterator = multi_callable(request_iterator)
+ next(response_iterator)
+ request_iterator.close()
+
+ self.assertIs(response_iterator.code(), grpc.StatusCode.CANCELLED)
+
+ def test_context_manager_close_while_many_calls_active(self):
+ with grpc.insecure_channel('localhost:{}'.format(
+ self._port)) as channel: # pylint: disable=bad-continuation
+ multi_callable = channel.stream_stream('Meffod')
+ request_iterators = tuple(
+ _Pipe((b'abc',))
+ for _ in range(test_constants.THREAD_CONCURRENCY))
+ response_iterators = []
+ for request_iterator in request_iterators:
+ response_iterator = multi_callable(request_iterator)
+ next(response_iterator)
+ response_iterators.append(response_iterator)
+ for request_iterator in request_iterators:
+ request_iterator.close()
+
+ for response_iterator in response_iterators:
+ self.assertIs(response_iterator.code(), grpc.StatusCode.CANCELLED)
+
+ def test_many_concurrent_closes(self):
+ channel = grpc.insecure_channel('localhost:{}'.format(self._port))
+ multi_callable = channel.stream_stream('Meffod')
+ request_iterator = _Pipe((b'abc',))
+ response_iterator = multi_callable(request_iterator)
+ next(response_iterator)
+ start = time.time()
+ end = start + _MORE_TIME
+
+ def sleep_some_time_then_close():
+ time.sleep(_SOME_TIME)
+ channel.close()
+
+ for _ in range(test_constants.THREAD_CONCURRENCY):
+ close_thread = threading.Thread(target=sleep_some_time_then_close)
+ close_thread.start()
+ while True:
+ request_iterator.add(b'def')
+ time.sleep(_BEAT)
+ if end < time.time():
+ break
+ request_iterator.close()
+
+ self.assertIs(response_iterator.code(), grpc.StatusCode.CANCELLED)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py b/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py
index 4f8868d346..578a3d79ad 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py
@@ -19,6 +19,7 @@ import unittest
from grpc._cython import cygrpc
from grpc.framework.foundation import logging_pool
from tests.unit.framework.common import test_constants
+from tests.unit._cython import test_utilities
_EMPTY_FLAGS = 0
_EMPTY_METADATA = ()
@@ -30,6 +31,8 @@ _RECEIVE_MESSAGE_TAG = 'receive_message'
_SERVER_COMPLETE_CALL_TAG = 'server_complete_call'
_SUCCESS_CALL_FRACTION = 1.0 / 8.0
+_SUCCESSFUL_CALLS = int(test_constants.RPC_CONCURRENCY * _SUCCESS_CALL_FRACTION)
+_UNSUCCESSFUL_CALLS = test_constants.RPC_CONCURRENCY - _SUCCESSFUL_CALLS
class _State(object):
@@ -150,7 +153,8 @@ class CancelManyCallsTest(unittest.TestCase):
server.register_completion_queue(server_completion_queue)
port = server.add_http2_port(b'[::]:0')
server.start()
- channel = cygrpc.Channel('localhost:{}'.format(port).encode(), None)
+ channel = cygrpc.Channel('localhost:{}'.format(port).encode(), None,
+ None)
state = _State()
@@ -165,31 +169,33 @@ class CancelManyCallsTest(unittest.TestCase):
client_condition = threading.Condition()
client_due = set()
- client_completion_queue = cygrpc.CompletionQueue()
- client_driver = _QueueDriver(client_condition, client_completion_queue,
- client_due)
- client_driver.start()
with client_condition:
client_calls = []
for index in range(test_constants.RPC_CONCURRENCY):
- client_call = channel.create_call(None, _EMPTY_FLAGS,
- client_completion_queue,
- b'/twinkies', None, None)
- operations = (
- cygrpc.SendInitialMetadataOperation(_EMPTY_METADATA,
- _EMPTY_FLAGS),
- cygrpc.SendMessageOperation(b'\x45\x56', _EMPTY_FLAGS),
- cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),
- cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),
- cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
- cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
- )
tag = 'client_complete_call_{0:04d}_tag'.format(index)
- client_call.start_client_batch(operations, tag)
+ client_call = channel.integrated_call(
+ _EMPTY_FLAGS, b'/twinkies', None, None, _EMPTY_METADATA,
+ None, ((
+ (
+ cygrpc.SendInitialMetadataOperation(
+ _EMPTY_METADATA, _EMPTY_FLAGS),
+ cygrpc.SendMessageOperation(b'\x45\x56',
+ _EMPTY_FLAGS),
+ cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),
+ cygrpc.ReceiveInitialMetadataOperation(
+ _EMPTY_FLAGS),
+ cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
+ cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
+ ),
+ tag,
+ ),))
client_due.add(tag)
client_calls.append(client_call)
+ client_events_future = test_utilities.SimpleFuture(
+ lambda: tuple(channel.next_call_event() for _ in range(_SUCCESSFUL_CALLS)))
+
with state.condition:
while True:
if state.parked_handlers < test_constants.THREAD_CONCURRENCY:
@@ -201,12 +207,14 @@ class CancelManyCallsTest(unittest.TestCase):
state.condition.notify_all()
break
- client_driver.events(
- test_constants.RPC_CONCURRENCY * _SUCCESS_CALL_FRACTION)
+ client_events_future.result()
with client_condition:
for client_call in client_calls:
- client_call.cancel()
+ client_call.cancel(cygrpc.StatusCode.cancelled, 'Cancelled!')
+ for _ in range(_UNSUCCESSFUL_CALLS):
+ channel.next_call_event()
+ channel.close(cygrpc.StatusCode.unknown, 'Cancelled on channel close!')
with state.condition:
server.shutdown(server_completion_queue, _SERVER_SHUTDOWN_TAG)
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_channel_test.py b/src/python/grpcio_tests/tests/unit/_cython/_channel_test.py
index 7305d0fa3f..d95286071d 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_channel_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_channel_test.py
@@ -21,25 +21,20 @@ from grpc._cython import cygrpc
from tests.unit.framework.common import test_constants
-def _channel_and_completion_queue():
- channel = cygrpc.Channel(b'localhost:54321', ())
- completion_queue = cygrpc.CompletionQueue()
- return channel, completion_queue
+def _channel():
+ return cygrpc.Channel(b'localhost:54321', (), None)
-def _connectivity_loop(channel, completion_queue):
+def _connectivity_loop(channel):
for _ in range(100):
connectivity = channel.check_connectivity_state(True)
- channel.watch_connectivity_state(connectivity,
- time.time() + 0.2, completion_queue,
- None)
- completion_queue.poll()
+ channel.watch_connectivity_state(connectivity, time.time() + 0.2)
def _create_loop_destroy():
- channel, completion_queue = _channel_and_completion_queue()
- _connectivity_loop(channel, completion_queue)
- completion_queue.shutdown()
+ channel = _channel()
+ _connectivity_loop(channel)
+ channel.close(cygrpc.StatusCode.ok, 'Channel close!')
def _in_parallel(behavior, arguments):
@@ -55,12 +50,9 @@ def _in_parallel(behavior, arguments):
class ChannelTest(unittest.TestCase):
def test_single_channel_lonely_connectivity(self):
- channel, completion_queue = _channel_and_completion_queue()
- _in_parallel(_connectivity_loop, (
- channel,
- completion_queue,
- ))
- completion_queue.shutdown()
+ channel = _channel()
+ _connectivity_loop(channel)
+ channel.close(cygrpc.StatusCode.ok, 'Channel close!')
def test_multiple_channels_lonely_connectivity(self):
_in_parallel(_create_loop_destroy, ())
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_common.py b/src/python/grpcio_tests/tests/unit/_cython/_common.py
index 7fd3d19b4e..d8210f36f8 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_common.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_common.py
@@ -100,7 +100,8 @@ class RpcTest(object):
self.server.register_completion_queue(self.server_completion_queue)
port = self.server.add_http2_port(b'[::]:0')
self.server.start()
- self.channel = cygrpc.Channel('localhost:{}'.format(port).encode(), [])
+ self.channel = cygrpc.Channel('localhost:{}'.format(port).encode(), [],
+ None)
self._server_shutdown_tag = 'server_shutdown_tag'
self.server_condition = threading.Condition()
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_no_messages_server_completion_queue_per_call_test.py b/src/python/grpcio_tests/tests/unit/_cython/_no_messages_server_completion_queue_per_call_test.py
index 7caa98f72d..8a721788f4 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_no_messages_server_completion_queue_per_call_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_no_messages_server_completion_queue_per_call_test.py
@@ -19,6 +19,7 @@ import unittest
from grpc._cython import cygrpc
from tests.unit._cython import _common
+from tests.unit._cython import test_utilities
class Test(_common.RpcTest, unittest.TestCase):
@@ -41,31 +42,27 @@ class Test(_common.RpcTest, unittest.TestCase):
server_request_call_tag,
})
- client_call = self.channel.create_call(None, _common.EMPTY_FLAGS,
- self.client_completion_queue,
- b'/twinkies', None, None)
client_receive_initial_metadata_tag = 'client_receive_initial_metadata_tag'
client_complete_rpc_tag = 'client_complete_rpc_tag'
- with self.client_condition:
- client_receive_initial_metadata_start_batch_result = (
- client_call.start_client_batch([
- cygrpc.ReceiveInitialMetadataOperation(_common.EMPTY_FLAGS),
- ], client_receive_initial_metadata_tag))
- self.assertEqual(cygrpc.CallError.ok,
- client_receive_initial_metadata_start_batch_result)
- client_complete_rpc_start_batch_result = client_call.start_client_batch(
+ client_call = self.channel.integrated_call(
+ _common.EMPTY_FLAGS, b'/twinkies', None, None,
+ _common.INVOCATION_METADATA, None, [(
[
- cygrpc.SendInitialMetadataOperation(
- _common.INVOCATION_METADATA, _common.EMPTY_FLAGS),
- cygrpc.SendCloseFromClientOperation(_common.EMPTY_FLAGS),
- cygrpc.ReceiveStatusOnClientOperation(_common.EMPTY_FLAGS),
- ], client_complete_rpc_tag)
- self.assertEqual(cygrpc.CallError.ok,
- client_complete_rpc_start_batch_result)
- self.client_driver.add_due({
+ cygrpc.ReceiveInitialMetadataOperation(_common.EMPTY_FLAGS),
+ ],
client_receive_initial_metadata_tag,
- client_complete_rpc_tag,
- })
+ )])
+ client_call.operate([
+ cygrpc.SendInitialMetadataOperation(_common.INVOCATION_METADATA,
+ _common.EMPTY_FLAGS),
+ cygrpc.SendCloseFromClientOperation(_common.EMPTY_FLAGS),
+ cygrpc.ReceiveStatusOnClientOperation(_common.EMPTY_FLAGS),
+ ], client_complete_rpc_tag)
+
+ client_events_future = test_utilities.SimpleFuture(
+ lambda: [
+ self.channel.next_call_event(),
+ self.channel.next_call_event(),])
server_request_call_event = self.server_driver.event_with_tag(
server_request_call_tag)
@@ -96,20 +93,23 @@ class Test(_common.RpcTest, unittest.TestCase):
server_complete_rpc_event = server_call_driver.event_with_tag(
server_complete_rpc_tag)
- client_receive_initial_metadata_event = self.client_driver.event_with_tag(
- client_receive_initial_metadata_tag)
- client_complete_rpc_event = self.client_driver.event_with_tag(
- client_complete_rpc_tag)
+ client_events = client_events_future.result()
+ if client_events[0].tag is client_receive_initial_metadata_tag:
+ client_receive_initial_metadata_event = client_events[0]
+ client_complete_rpc_event = client_events[1]
+ else:
+ client_complete_rpc_event = client_events[0]
+ client_receive_initial_metadata_event = client_events[1]
return (
_common.OperationResult(server_request_call_start_batch_result,
server_request_call_event.completion_type,
server_request_call_event.success),
_common.OperationResult(
- client_receive_initial_metadata_start_batch_result,
+ cygrpc.CallError.ok,
client_receive_initial_metadata_event.completion_type,
client_receive_initial_metadata_event.success),
- _common.OperationResult(client_complete_rpc_start_batch_result,
+ _common.OperationResult(cygrpc.CallError.ok,
client_complete_rpc_event.completion_type,
client_complete_rpc_event.success),
_common.OperationResult(
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_no_messages_single_server_completion_queue_test.py b/src/python/grpcio_tests/tests/unit/_cython/_no_messages_single_server_completion_queue_test.py
index 8582a39c01..47f39ebce2 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_no_messages_single_server_completion_queue_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_no_messages_single_server_completion_queue_test.py
@@ -19,6 +19,7 @@ import unittest
from grpc._cython import cygrpc
from tests.unit._cython import _common
+from tests.unit._cython import test_utilities
class Test(_common.RpcTest, unittest.TestCase):
@@ -36,28 +37,31 @@ class Test(_common.RpcTest, unittest.TestCase):
server_request_call_tag,
})
- client_call = self.channel.create_call(None, _common.EMPTY_FLAGS,
- self.client_completion_queue,
- b'/twinkies', None, None)
client_receive_initial_metadata_tag = 'client_receive_initial_metadata_tag'
client_complete_rpc_tag = 'client_complete_rpc_tag'
- with self.client_condition:
- client_receive_initial_metadata_start_batch_result = (
- client_call.start_client_batch([
- cygrpc.ReceiveInitialMetadataOperation(_common.EMPTY_FLAGS),
- ], client_receive_initial_metadata_tag))
- client_complete_rpc_start_batch_result = client_call.start_client_batch(
- [
- cygrpc.SendInitialMetadataOperation(
- _common.INVOCATION_METADATA, _common.EMPTY_FLAGS),
- cygrpc.SendCloseFromClientOperation(_common.EMPTY_FLAGS),
- cygrpc.ReceiveStatusOnClientOperation(_common.EMPTY_FLAGS),
- ], client_complete_rpc_tag)
- self.client_driver.add_due({
- client_receive_initial_metadata_tag,
- client_complete_rpc_tag,
- })
-
+ client_call = self.channel.integrated_call(
+ _common.EMPTY_FLAGS, b'/twinkies', None, None,
+ _common.INVOCATION_METADATA, None, [
+ (
+ [
+ cygrpc.SendInitialMetadataOperation(
+ _common.INVOCATION_METADATA, _common.EMPTY_FLAGS),
+ cygrpc.SendCloseFromClientOperation(
+ _common.EMPTY_FLAGS),
+ cygrpc.ReceiveStatusOnClientOperation(
+ _common.EMPTY_FLAGS),
+ ],
+ client_complete_rpc_tag,
+ ),
+ ])
+ client_call.operate([
+ cygrpc.ReceiveInitialMetadataOperation(_common.EMPTY_FLAGS),
+ ], client_receive_initial_metadata_tag)
+
+ client_events_future = test_utilities.SimpleFuture(
+ lambda: [
+ self.channel.next_call_event(),
+ self.channel.next_call_event(),])
server_request_call_event = self.server_driver.event_with_tag(
server_request_call_tag)
@@ -87,20 +91,19 @@ class Test(_common.RpcTest, unittest.TestCase):
server_complete_rpc_event = self.server_driver.event_with_tag(
server_complete_rpc_tag)
- client_receive_initial_metadata_event = self.client_driver.event_with_tag(
- client_receive_initial_metadata_tag)
- client_complete_rpc_event = self.client_driver.event_with_tag(
- client_complete_rpc_tag)
+ client_events = client_events_future.result()
+ client_receive_initial_metadata_event = client_events[0]
+ client_complete_rpc_event = client_events[1]
return (
_common.OperationResult(server_request_call_start_batch_result,
server_request_call_event.completion_type,
server_request_call_event.success),
_common.OperationResult(
- client_receive_initial_metadata_start_batch_result,
+ cygrpc.CallError.ok,
client_receive_initial_metadata_event.completion_type,
client_receive_initial_metadata_event.success),
- _common.OperationResult(client_complete_rpc_start_batch_result,
+ _common.OperationResult(cygrpc.CallError.ok,
client_complete_rpc_event.completion_type,
client_complete_rpc_event.success),
_common.OperationResult(
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py b/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py
index bc63b54879..8a903bfaf9 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py
@@ -17,6 +17,7 @@ import threading
import unittest
from grpc._cython import cygrpc
+from tests.unit._cython import test_utilities
_EMPTY_FLAGS = 0
_EMPTY_METADATA = ()
@@ -118,7 +119,8 @@ class ReadSomeButNotAllResponsesTest(unittest.TestCase):
server.register_completion_queue(server_completion_queue)
port = server.add_http2_port(b'[::]:0')
server.start()
- channel = cygrpc.Channel('localhost:{}'.format(port).encode(), set())
+ channel = cygrpc.Channel('localhost:{}'.format(port).encode(), set(),
+ None)
server_shutdown_tag = 'server_shutdown_tag'
server_driver = _ServerDriver(server_completion_queue,
@@ -127,10 +129,6 @@ class ReadSomeButNotAllResponsesTest(unittest.TestCase):
client_condition = threading.Condition()
client_due = set()
- client_completion_queue = cygrpc.CompletionQueue()
- client_driver = _QueueDriver(client_condition, client_completion_queue,
- client_due)
- client_driver.start()
server_call_condition = threading.Condition()
server_send_initial_metadata_tag = 'server_send_initial_metadata_tag'
@@ -154,25 +152,28 @@ class ReadSomeButNotAllResponsesTest(unittest.TestCase):
server_completion_queue,
server_rpc_tag)
- client_call = channel.create_call(None, _EMPTY_FLAGS,
- client_completion_queue, b'/twinkies',
- None, None)
client_receive_initial_metadata_tag = 'client_receive_initial_metadata_tag'
client_complete_rpc_tag = 'client_complete_rpc_tag'
- with client_condition:
- client_receive_initial_metadata_start_batch_result = (
- client_call.start_client_batch([
- cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),
- ], client_receive_initial_metadata_tag))
- client_due.add(client_receive_initial_metadata_tag)
- client_complete_rpc_start_batch_result = (
- client_call.start_client_batch([
- cygrpc.SendInitialMetadataOperation(_EMPTY_METADATA,
- _EMPTY_FLAGS),
- cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),
- cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
- ], client_complete_rpc_tag))
- client_due.add(client_complete_rpc_tag)
+ client_call = channel.segregated_call(
+ _EMPTY_FLAGS, b'/twinkies', None, None, _EMPTY_METADATA, None, (
+ (
+ [
+ cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),
+ ],
+ client_receive_initial_metadata_tag,
+ ),
+ (
+ [
+ cygrpc.SendInitialMetadataOperation(
+ _EMPTY_METADATA, _EMPTY_FLAGS),
+ cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),
+ cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
+ ],
+ client_complete_rpc_tag,
+ ),
+ ))
+ client_receive_initial_metadata_event_future = test_utilities.SimpleFuture(
+ client_call.next_event)
server_rpc_event = server_driver.first_event()
@@ -208,19 +209,20 @@ class ReadSomeButNotAllResponsesTest(unittest.TestCase):
server_complete_rpc_tag)
server_call_driver.events()
- with client_condition:
- client_receive_first_message_tag = 'client_receive_first_message_tag'
- client_receive_first_message_start_batch_result = (
- client_call.start_client_batch([
- cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
- ], client_receive_first_message_tag))
- client_due.add(client_receive_first_message_tag)
- client_receive_first_message_event = client_driver.event_with_tag(
- client_receive_first_message_tag)
+ client_recieve_initial_metadata_event = client_receive_initial_metadata_event_future.result(
+ )
+
+ client_receive_first_message_tag = 'client_receive_first_message_tag'
+ client_call.operate([
+ cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
+ ], client_receive_first_message_tag)
+ client_receive_first_message_event = client_call.next_event()
- client_call_cancel_result = client_call.cancel()
- client_driver.events()
+ client_call_cancel_result = client_call.cancel(
+ cygrpc.StatusCode.cancelled, 'Cancelled during test!')
+ client_complete_rpc_event = client_call.next_event()
+ channel.close(cygrpc.StatusCode.unknown, 'Channel closed!')
server.shutdown(server_completion_queue, server_shutdown_tag)
server.cancel_all_calls()
server_driver.events()
@@ -228,11 +230,6 @@ class ReadSomeButNotAllResponsesTest(unittest.TestCase):
self.assertEqual(cygrpc.CallError.ok, request_call_result)
self.assertEqual(cygrpc.CallError.ok,
server_send_initial_metadata_start_batch_result)
- self.assertEqual(cygrpc.CallError.ok,
- client_receive_initial_metadata_start_batch_result)
- self.assertEqual(cygrpc.CallError.ok,
- client_complete_rpc_start_batch_result)
- self.assertEqual(cygrpc.CallError.ok, client_call_cancel_result)
self.assertIs(server_rpc_tag, server_rpc_event.tag)
self.assertEqual(cygrpc.CompletionType.operation_complete,
server_rpc_event.completion_type)
diff --git a/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py b/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
index 23f5ef605d..724a690746 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
@@ -51,8 +51,8 @@ class TypeSmokeTest(unittest.TestCase):
del server
def testChannelUpDown(self):
- channel = cygrpc.Channel(b'[::]:0', None)
- del channel
+ channel = cygrpc.Channel(b'[::]:0', None, None)
+ channel.close(cygrpc.StatusCode.cancelled, 'Test method anyway!')
def test_metadata_plugin_call_credentials_up_down(self):
cygrpc.MetadataPluginCallCredentials(_metadata_plugin,
@@ -121,7 +121,7 @@ class ServerClientMixin(object):
client_credentials)
else:
self.client_channel = cygrpc.Channel('localhost:{}'.format(
- self.port).encode(), set())
+ self.port).encode(), set(), None)
if host_override:
self.host_argument = None # default host
self.expected_host = host_override
@@ -131,17 +131,20 @@ class ServerClientMixin(object):
self.expected_host = self.host_argument
def tearDownMixin(self):
+ self.client_channel.close(cygrpc.StatusCode.ok, 'test being torn down!')
+ del self.client_channel
del self.server
del self.client_completion_queue
del self.server_completion_queue
- def _perform_operations(self, operations, call, queue, deadline,
- description):
- """Perform the list of operations with given call, queue, and deadline.
+ def _perform_queue_operations(self, operations, call, queue, deadline,
+ description):
+ """Perform the operations with given call, queue, and deadline.
- Invocation errors are reported with as an exception with `description` in
- the message. Performs the operations asynchronously, returning a future.
- """
+ Invocation errors are reported with as an exception with `description`
+ in the message. Performs the operations asynchronously, returning a
+ future.
+ """
def performer():
tag = object()
@@ -185,9 +188,6 @@ class ServerClientMixin(object):
self.assertEqual(cygrpc.CallError.ok, request_call_result)
client_call_tag = object()
- client_call = self.client_channel.create_call(
- None, 0, self.client_completion_queue, METHOD, self.host_argument,
- DEADLINE)
client_initial_metadata = (
(
CLIENT_METADATA_ASCII_KEY,
@@ -198,18 +198,24 @@ class ServerClientMixin(object):
CLIENT_METADATA_BIN_VALUE,
),
)
- client_start_batch_result = client_call.start_client_batch([
- cygrpc.SendInitialMetadataOperation(client_initial_metadata,
- _EMPTY_FLAGS),
- cygrpc.SendMessageOperation(REQUEST, _EMPTY_FLAGS),
- cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),
- cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),
- cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
- cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
- ], client_call_tag)
- self.assertEqual(cygrpc.CallError.ok, client_start_batch_result)
- client_event_future = test_utilities.CompletionQueuePollFuture(
- self.client_completion_queue, DEADLINE)
+ client_call = self.client_channel.integrated_call(
+ 0, METHOD, self.host_argument, DEADLINE, client_initial_metadata,
+ None, [
+ (
+ [
+ cygrpc.SendInitialMetadataOperation(
+ client_initial_metadata, _EMPTY_FLAGS),
+ cygrpc.SendMessageOperation(REQUEST, _EMPTY_FLAGS),
+ cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),
+ cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),
+ cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
+ cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
+ ],
+ client_call_tag,
+ ),
+ ])
+ client_event_future = test_utilities.SimpleFuture(
+ self.client_channel.next_call_event)
request_event = self.server_completion_queue.poll(deadline=DEADLINE)
self.assertEqual(cygrpc.CompletionType.operation_complete,
@@ -304,66 +310,76 @@ class ServerClientMixin(object):
del client_call
del server_call
- def test6522(self):
+ def test_6522(self):
DEADLINE = time.time() + 5
DEADLINE_TOLERANCE = 0.25
METHOD = b'twinkies'
empty_metadata = ()
+ # Prologue
server_request_tag = object()
self.server.request_call(self.server_completion_queue,
self.server_completion_queue,
server_request_tag)
- client_call = self.client_channel.create_call(
- None, 0, self.client_completion_queue, METHOD, self.host_argument,
- DEADLINE)
-
- # Prologue
- def perform_client_operations(operations, description):
- return self._perform_operations(operations, client_call,
- self.client_completion_queue,
- DEADLINE, description)
-
- client_event_future = perform_client_operations([
- cygrpc.SendInitialMetadataOperation(empty_metadata, _EMPTY_FLAGS),
- cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),
- ], "Client prologue")
+ client_call = self.client_channel.segregated_call(
+ 0, METHOD, self.host_argument, DEADLINE, None, None, ([(
+ [
+ cygrpc.SendInitialMetadataOperation(empty_metadata,
+ _EMPTY_FLAGS),
+ cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),
+ ],
+ object(),
+ ), (
+ [
+ cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
+ ],
+ object(),
+ )]))
+
+ client_initial_metadata_event_future = test_utilities.SimpleFuture(
+ client_call.next_event)
request_event = self.server_completion_queue.poll(deadline=DEADLINE)
server_call = request_event.call
def perform_server_operations(operations, description):
- return self._perform_operations(operations, server_call,
- self.server_completion_queue,
- DEADLINE, description)
+ return self._perform_queue_operations(operations, server_call,
+ self.server_completion_queue,
+ DEADLINE, description)
server_event_future = perform_server_operations([
cygrpc.SendInitialMetadataOperation(empty_metadata, _EMPTY_FLAGS),
], "Server prologue")
- client_event_future.result() # force completion
+ client_initial_metadata_event_future.result() # force completion
server_event_future.result()
# Messaging
for _ in range(10):
- client_event_future = perform_client_operations([
+ client_call.operate([
cygrpc.SendMessageOperation(b'', _EMPTY_FLAGS),
cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
], "Client message")
+ client_message_event_future = test_utilities.SimpleFuture(
+ client_call.next_event)
server_event_future = perform_server_operations([
cygrpc.SendMessageOperation(b'', _EMPTY_FLAGS),
cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
], "Server receive")
- client_event_future.result() # force completion
+ client_message_event_future.result() # force completion
server_event_future.result()
# Epilogue
- client_event_future = perform_client_operations([
+ client_call.operate([
cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),
- cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS)
], "Client epilogue")
+ # One for ReceiveStatusOnClient, one for SendCloseFromClient.
+ client_events_future = test_utilities.SimpleFuture(
+ lambda: {
+ client_call.next_event(),
+ client_call.next_event(),})
server_event_future = perform_server_operations([
cygrpc.ReceiveCloseOnServerOperation(_EMPTY_FLAGS),
@@ -371,7 +387,7 @@ class ServerClientMixin(object):
empty_metadata, cygrpc.StatusCode.ok, b'', _EMPTY_FLAGS)
], "Server epilogue")
- client_event_future.result() # force completion
+ client_events_future.result() # force completion
server_event_future.result()
diff --git a/src/python/grpcio_tests/tests/unit/_invalid_metadata_test.py b/src/python/grpcio_tests/tests/unit/_invalid_metadata_test.py
index 4edf0fc4ad..f153089a24 100644
--- a/src/python/grpcio_tests/tests/unit/_invalid_metadata_test.py
+++ b/src/python/grpcio_tests/tests/unit/_invalid_metadata_test.py
@@ -81,29 +81,16 @@ class InvalidMetadataTest(unittest.TestCase):
request = b'\x07\x08'
metadata = (('InVaLiD', 'UnaryRequestFutureUnaryResponse'),)
expected_error_details = "metadata was invalid: %s" % metadata
- response_future = self._unary_unary.future(request, metadata=metadata)
- with self.assertRaises(grpc.RpcError) as exception_context:
- response_future.result()
- self.assertEqual(exception_context.exception.details(),
- expected_error_details)
- self.assertEqual(exception_context.exception.code(),
- grpc.StatusCode.INTERNAL)
- self.assertEqual(response_future.details(), expected_error_details)
- self.assertEqual(response_future.code(), grpc.StatusCode.INTERNAL)
+ with self.assertRaises(ValueError) as exception_context:
+ self._unary_unary.future(request, metadata=metadata)
def testUnaryRequestStreamResponse(self):
request = b'\x37\x58'
metadata = (('InVaLiD', 'UnaryRequestStreamResponse'),)
expected_error_details = "metadata was invalid: %s" % metadata
- response_iterator = self._unary_stream(request, metadata=metadata)
- with self.assertRaises(grpc.RpcError) as exception_context:
- next(response_iterator)
- self.assertEqual(exception_context.exception.details(),
- expected_error_details)
- self.assertEqual(exception_context.exception.code(),
- grpc.StatusCode.INTERNAL)
- self.assertEqual(response_iterator.details(), expected_error_details)
- self.assertEqual(response_iterator.code(), grpc.StatusCode.INTERNAL)
+ with self.assertRaises(ValueError) as exception_context:
+ self._unary_stream(request, metadata=metadata)
+ self.assertIn(expected_error_details, str(exception_context.exception))
def testStreamRequestBlockingUnaryResponse(self):
request_iterator = (
@@ -129,32 +116,18 @@ class InvalidMetadataTest(unittest.TestCase):
b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH))
metadata = (('InVaLiD', 'StreamRequestFutureUnaryResponse'),)
expected_error_details = "metadata was invalid: %s" % metadata
- response_future = self._stream_unary.future(
- request_iterator, metadata=metadata)
- with self.assertRaises(grpc.RpcError) as exception_context:
- response_future.result()
- self.assertEqual(exception_context.exception.details(),
- expected_error_details)
- self.assertEqual(exception_context.exception.code(),
- grpc.StatusCode.INTERNAL)
- self.assertEqual(response_future.details(), expected_error_details)
- self.assertEqual(response_future.code(), grpc.StatusCode.INTERNAL)
+ with self.assertRaises(ValueError) as exception_context:
+ self._stream_unary.future(request_iterator, metadata=metadata)
+ self.assertIn(expected_error_details, str(exception_context.exception))
def testStreamRequestStreamResponse(self):
request_iterator = (
b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH))
metadata = (('InVaLiD', 'StreamRequestStreamResponse'),)
expected_error_details = "metadata was invalid: %s" % metadata
- response_iterator = self._stream_stream(
- request_iterator, metadata=metadata)
- with self.assertRaises(grpc.RpcError) as exception_context:
- next(response_iterator)
- self.assertEqual(exception_context.exception.details(),
- expected_error_details)
- self.assertEqual(exception_context.exception.code(),
- grpc.StatusCode.INTERNAL)
- self.assertEqual(response_iterator.details(), expected_error_details)
- self.assertEqual(response_iterator.code(), grpc.StatusCode.INTERNAL)
+ with self.assertRaises(ValueError) as exception_context:
+ self._stream_stream(request_iterator, metadata=metadata)
+ self.assertIn(expected_error_details, str(exception_context.exception))
if __name__ == '__main__':
diff --git a/src/python/grpcio_tests/tests/unit/_rpc_test.py b/src/python/grpcio_tests/tests/unit/_rpc_test.py
index 54f01d9f8d..34e7831a98 100644
--- a/src/python/grpcio_tests/tests/unit/_rpc_test.py
+++ b/src/python/grpcio_tests/tests/unit/_rpc_test.py
@@ -225,6 +225,7 @@ class RPCTest(unittest.TestCase):
self.assertEqual(expected_response, response)
self.assertIs(grpc.StatusCode.OK, call.code())
+ self.assertEqual("", call.debug_error_string())
def testSuccessfulUnaryRequestFutureUnaryResponse(self):
request = b'\x07\x08'
@@ -706,6 +707,13 @@ class RPCTest(unittest.TestCase):
self.assertIs(grpc.StatusCode.UNKNOWN,
exception_context.exception.code())
+ # sanity checks on to make sure returned string contains default members
+ # of the error
+ debug_error_string = exception_context.exception.debug_error_string()
+ self.assertIn("created", debug_error_string)
+ self.assertIn("description", debug_error_string)
+ self.assertIn("file", debug_error_string)
+ self.assertIn("file_line", debug_error_string)
def testFailedUnaryRequestFutureUnaryResponse(self):
request = b'\x37\x17'
diff --git a/src/python/grpcio_tests/tests/unit/_thread_cleanup_test.py b/src/python/grpcio_tests/tests/unit/_thread_cleanup_test.py
deleted file mode 100644
index 18f5af058a..0000000000
--- a/src/python/grpcio_tests/tests/unit/_thread_cleanup_test.py
+++ /dev/null
@@ -1,115 +0,0 @@
-# Copyright 2016 gRPC authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Tests for CleanupThread."""
-
-import threading
-import time
-import unittest
-
-from grpc import _common
-
-_SHORT_TIME = 0.5
-_LONG_TIME = 5.0
-_EPSILON = 0.5
-
-
-def cleanup(timeout):
- if timeout is not None:
- time.sleep(timeout)
- else:
- time.sleep(_LONG_TIME)
-
-
-def slow_cleanup(timeout):
- # Don't respect timeout
- time.sleep(_LONG_TIME)
-
-
-class CleanupThreadTest(unittest.TestCase):
-
- def testTargetInvocation(self):
- event = threading.Event()
-
- def target(arg1, arg2, arg3=None):
- self.assertEqual('arg1', arg1)
- self.assertEqual('arg2', arg2)
- self.assertEqual('arg3', arg3)
- event.set()
-
- cleanup_thread = _common.CleanupThread(
- behavior=lambda x: None,
- target=target,
- name='test-name',
- args=('arg1', 'arg2'),
- kwargs={
- 'arg3': 'arg3'
- })
- cleanup_thread.start()
- cleanup_thread.join()
- self.assertEqual(cleanup_thread.name, 'test-name')
- self.assertTrue(event.is_set())
-
- def testJoinNoTimeout(self):
- cleanup_thread = _common.CleanupThread(behavior=cleanup)
- cleanup_thread.start()
- start_time = time.time()
- cleanup_thread.join()
- end_time = time.time()
- self.assertAlmostEqual(
- _LONG_TIME, end_time - start_time, delta=_EPSILON)
-
- def testJoinTimeout(self):
- cleanup_thread = _common.CleanupThread(behavior=cleanup)
- cleanup_thread.start()
- start_time = time.time()
- cleanup_thread.join(_SHORT_TIME)
- end_time = time.time()
- self.assertAlmostEqual(
- _SHORT_TIME, end_time - start_time, delta=_EPSILON)
-
- def testJoinTimeoutSlowBehavior(self):
- cleanup_thread = _common.CleanupThread(behavior=slow_cleanup)
- cleanup_thread.start()
- start_time = time.time()
- cleanup_thread.join(_SHORT_TIME)
- end_time = time.time()
- self.assertAlmostEqual(
- _LONG_TIME, end_time - start_time, delta=_EPSILON)
-
- def testJoinTimeoutSlowTarget(self):
- event = threading.Event()
-
- def target():
- event.wait(_LONG_TIME)
-
- cleanup_thread = _common.CleanupThread(behavior=cleanup, target=target)
- cleanup_thread.start()
- start_time = time.time()
- cleanup_thread.join(_SHORT_TIME)
- end_time = time.time()
- self.assertAlmostEqual(
- _SHORT_TIME, end_time - start_time, delta=_EPSILON)
- event.set()
-
- def testJoinZeroTimeout(self):
- cleanup_thread = _common.CleanupThread(behavior=cleanup)
- cleanup_thread.start()
- start_time = time.time()
- cleanup_thread.join(0)
- end_time = time.time()
- self.assertAlmostEqual(0, end_time - start_time, delta=_EPSILON)
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/src/ruby/bin/math_client.rb b/src/ruby/bin/math_client.rb
index 15120c0c0d..66717d8bf3 100755
--- a/src/ruby/bin/math_client.rb
+++ b/src/ruby/bin/math_client.rb
@@ -27,15 +27,26 @@ $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
require 'grpc'
require 'math_services_pb'
require 'optparse'
+require 'logger'
include GRPC::Core::TimeConsts
+module StdoutLogger
+ def logger
+ LOGGER
+ end
+
+ LOGGER = Logger.new(STDOUT)
+end
+
+GRPC.extend(StdoutLogger)
+
def do_div(stub)
GRPC.logger.info('request_response')
GRPC.logger.info('----------------')
req = Math::DivArgs.new(dividend: 7, divisor: 3)
GRPC.logger.info("div(7/3): req=#{req.inspect}")
- resp = stub.div(req, timeout: INFINITE_FUTURE)
+ resp = stub.div(req)
GRPC.logger.info("Answer: #{resp.inspect}")
GRPC.logger.info('----------------')
end
@@ -56,7 +67,7 @@ def do_fib(stub)
GRPC.logger.info('----------------')
req = Math::FibArgs.new(limit: 11)
GRPC.logger.info("fib(11): req=#{req.inspect}")
- resp = stub.fib(req, timeout: INFINITE_FUTURE)
+ resp = stub.fib(req)
resp.each do |r|
GRPC.logger.info("Answer: #{r.inspect}")
end
@@ -71,7 +82,7 @@ def do_div_many(stub)
reqs << Math::DivArgs.new(dividend: 5, divisor: 2)
reqs << Math::DivArgs.new(dividend: 7, divisor: 2)
GRPC.logger.info("div(7/3), div(5/2), div(7/2): reqs=#{reqs.inspect}")
- resp = stub.div_many(reqs, timeout: INFINITE_FUTURE)
+ resp = stub.div_many(reqs)
resp.each do |r|
GRPC.logger.info("Answer: #{r.inspect}")
end
@@ -107,19 +118,16 @@ def main
# The Math::Math:: module occurs because the service has the same name as its
# package. That practice should be avoided by defining real services.
-
- p options
if options['secure']
stub_opts = {
:creds => test_creds,
- GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.fr'
+ GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.fr',
+ timeout: INFINITE_FUTURE,
}
- p stub_opts
- p options['host']
stub = Math::Math::Stub.new(options['host'], **stub_opts)
GRPC.logger.info("... connecting securely on #{options['host']}")
else
- stub = Math::Math::Stub.new(options['host'])
+ stub = Math::Math::Stub.new(options['host'], :this_channel_is_insecure, timeout: INFINITE_FUTURE)
GRPC.logger.info("... connecting insecurely on #{options['host']}")
end
diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb
index 31ab6a302b..838ac45927 100644
--- a/src/ruby/lib/grpc/generic/rpc_server.rb
+++ b/src/ruby/lib/grpc/generic/rpc_server.rb
@@ -364,7 +364,8 @@ module GRPC
# sent yet
c = ActiveCall.new(an_rpc.call, noop, noop, an_rpc.deadline,
metadata_received: true, started: false)
- c.send_status(GRPC::Core::StatusCodes::RESOURCE_EXHAUSTED, '')
+ c.send_status(GRPC::Core::StatusCodes::RESOURCE_EXHAUSTED,
+ 'No free threads in thread pool')
nil
end
diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb
index 2cb7c4be53..15f375100a 100644
--- a/src/ruby/lib/grpc/version.rb
+++ b/src/ruby/lib/grpc/version.rb
@@ -14,5 +14,5 @@
# GRPC contains the General RPC module.
module GRPC
- VERSION = '1.12.0.dev'
+ VERSION = '1.13.0.dev'
end
diff --git a/src/ruby/pb/grpc/health/v1/health_services_pb.rb b/src/ruby/pb/grpc/health/v1/health_services_pb.rb
index 520f8e7ec5..169e160f90 100644
--- a/src/ruby/pb/grpc/health/v1/health_services_pb.rb
+++ b/src/ruby/pb/grpc/health/v1/health_services_pb.rb
@@ -1,7 +1,7 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# Source: grpc/health/v1/health.proto for package 'grpc.health.v1'
# Original file comments:
-# Copyright 2015 gRPC authors.
+# Copyright 2015 The gRPC Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,6 +15,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+# The canonical version of this proto can be found at
+# https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto
+#
require 'grpc'
require 'grpc/health/v1/health_pb'
diff --git a/src/ruby/pb/test/client.rb b/src/ruby/pb/test/client.rb
index 63959d9b14..1b9d7cbbe6 100755
--- a/src/ruby/pb/test/client.rb
+++ b/src/ruby/pb/test/client.rb
@@ -734,7 +734,7 @@ def parse_args
opts.on('--use_tls USE_TLS', ['false', 'true'],
'require a secure connection?') do |v|
args['secure'] = v == 'true'
-p end
+ end
opts.on('--use_test_ca USE_TEST_CA', ['false', 'true'],
'if secure, use the test certificate?') do |v|
args['use_test_ca'] = v == 'true'
diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb
index 822f70eb0a..09d5c82674 100644
--- a/src/ruby/tools/version.rb
+++ b/src/ruby/tools/version.rb
@@ -14,6 +14,6 @@
module GRPC
module Tools
- VERSION = '1.12.0.dev'
+ VERSION = '1.13.0.dev'
end
end