From af7cf54e512953a9a3e71f6ad4993a7069c093fb Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 22 May 2015 10:07:34 -0700 Subject: [PATCH 01/52] Build shared libraries for wrapped languages too --- tools/run_tests/run_tests.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index 3a344693c1f..a1ecb11ef43 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -57,7 +57,7 @@ class SimpleConfig(object): if environ is None: environ = {} self.build_config = config - self.maxjobs = 2 * multiprocessing.cpu_count() + self.maxjobs = 100 * multiprocessing.cpu_count() self.allow_hashing = (config != 'gcov') self.environ = environ self.environ['CONFIG'] = config @@ -151,7 +151,7 @@ class NodeLanguage(object): environ={'GRPC_TRACE': 'surface,batch'})] def make_targets(self): - return ['static_c'] + return ['static_c', 'shared_c'] def build_steps(self): return [['tools/run_tests/build_node.sh']] @@ -170,7 +170,7 @@ class PhpLanguage(object): environ={'GRPC_TRACE': 'surface,batch'})] def make_targets(self): - return ['static_c'] + return ['static_c', 'shared_c'] def build_steps(self): return [['tools/run_tests/build_php.sh']] @@ -204,7 +204,7 @@ class PythonLanguage(object): return files + modules def make_targets(self): - return ['static_c', 'grpc_python_plugin'] + return ['static_c', 'grpc_python_plugin', 'shared_c'] def build_steps(self): return [['tools/run_tests/build_python.sh']] @@ -282,7 +282,7 @@ class Build(object): return [] def make_targets(self): - return ['static'] + return ['static', 'shared'] def build_steps(self): return [] From c82a866c99f165fb46ea2cda60f60e64db44aad0 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 22 May 2015 10:15:55 -0700 Subject: [PATCH 02/52] Fix typo --- tools/run_tests/run_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index a1ecb11ef43..ac49885921a 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -57,7 +57,7 @@ class SimpleConfig(object): if environ is None: environ = {} self.build_config = config - self.maxjobs = 100 * multiprocessing.cpu_count() + self.maxjobs = 2 * multiprocessing.cpu_count() self.allow_hashing = (config != 'gcov') self.environ = environ self.environ['CONFIG'] = config From ce192ed4f31bb01964d150c7889c916167ef0755 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 22 May 2015 12:46:14 -0700 Subject: [PATCH 03/52] Fix 4.4 build --- tools/run_tests/run_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index ac49885921a..755d460c94c 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -282,7 +282,7 @@ class Build(object): return [] def make_targets(self): - return ['static', 'shared'] + return ['static'] def build_steps(self): return [] From 9686dabd044666f32cbc30f7551caf81a05124e2 Mon Sep 17 00:00:00 2001 From: Alistair Veitch Date: Tue, 26 May 2015 14:26:47 -0700 Subject: [PATCH 04/52] Initial refactoring and context API changes --- BUILD | 40 +- Makefile | 342 +----------------- build.json | 181 +-------- include/grpc/census.h | 91 +++++ src/core/census/README.md | 76 ++++ src/core/census/context.c | 59 +++ src/core/census/context.h | 49 +++ src/core/census/grpc_context.c | 41 +++ src/core/census/grpc_context.h | 42 +++ src/core/census/initialize.c | 38 ++ src/core/surface/call.c | 35 +- src/core/surface/channel_create.c | 3 +- src/core/surface/init.c | 4 +- src/core/surface/secure_channel_create.c | 3 +- src/core/surface/server.c | 15 +- tools/run_tests/tests.json | 72 ---- vsprojects/Grpc.mak | 58 +-- vsprojects/grpc/grpc.vcxproj | 28 +- vsprojects/grpc/grpc.vcxproj.filters | 62 +--- .../grpc_test_util/grpc_test_util.vcxproj | 2 - .../grpc_unsecure/grpc_unsecure.vcxproj | 28 +- .../grpc_unsecure.vcxproj.filters | 62 +--- 22 files changed, 527 insertions(+), 804 deletions(-) create mode 100644 include/grpc/census.h create mode 100644 src/core/census/README.md create mode 100644 src/core/census/context.c create mode 100644 src/core/census/context.h create mode 100644 src/core/census/grpc_context.c create mode 100644 src/core/census/grpc_context.h create mode 100644 src/core/census/initialize.c diff --git a/BUILD b/BUILD index bcee870bd3c..a68771ec279 100644 --- a/BUILD +++ b/BUILD @@ -143,7 +143,7 @@ cc_library( "src/core/tsi/ssl_transport_security.h", "src/core/tsi/transport_security.h", "src/core/tsi/transport_security_interface.h", - "src/core/channel/census_filter.h", + "src/core/census/grpc_context.h", "src/core/channel/channel_args.h", "src/core/channel/channel_stack.h", "src/core/channel/child_channel.h", @@ -192,12 +192,6 @@ cc_library( "src/core/json/json_writer.h", "src/core/profiling/timers.h", "src/core/profiling/timers_preciseclock.h", - "src/core/statistics/census_interface.h", - "src/core/statistics/census_log.h", - "src/core/statistics/census_rpc_stats.h", - "src/core/statistics/census_tracing.h", - "src/core/statistics/hash_table.h", - "src/core/statistics/window_stats.h", "src/core/surface/byte_buffer_queue.h", "src/core/surface/call.h", "src/core/surface/channel.h", @@ -230,6 +224,7 @@ cc_library( "src/core/transport/stream_op.h", "src/core/transport/transport.h", "src/core/transport/transport_impl.h", + "src/core/census/context.h", "src/core/httpcli/format_request.c", "src/core/httpcli/httpcli.c", "src/core/httpcli/httpcli_security_connector.c", @@ -251,7 +246,7 @@ cc_library( "src/core/tsi/fake_transport_security.c", "src/core/tsi/ssl_transport_security.c", "src/core/tsi/transport_security.c", - "src/core/channel/census_filter.c", + "src/core/census/grpc_context.c", "src/core/channel/channel_args.c", "src/core/channel/channel_stack.c", "src/core/channel/child_channel.c", @@ -303,12 +298,6 @@ cc_library( "src/core/json/json_writer.c", "src/core/profiling/basic_timers.c", "src/core/profiling/stap_timers.c", - "src/core/statistics/census_init.c", - "src/core/statistics/census_log.c", - "src/core/statistics/census_rpc_stats.c", - "src/core/statistics/census_tracing.c", - "src/core/statistics/hash_table.c", - "src/core/statistics/window_stats.c", "src/core/surface/byte_buffer.c", "src/core/surface/byte_buffer_queue.c", "src/core/surface/byte_buffer_reader.c", @@ -348,6 +337,8 @@ cc_library( "src/core/transport/stream_op.c", "src/core/transport/transport.c", "src/core/transport/transport_op_string.c", + "src/core/census/context.c", + "src/core/census/initialize.c", ], hdrs = [ "include/grpc/grpc_security.h", @@ -355,6 +346,7 @@ cc_library( "include/grpc/byte_buffer_reader.h", "include/grpc/grpc.h", "include/grpc/status.h", + "include/grpc/census.h", ], includes = [ "include", @@ -370,7 +362,7 @@ cc_library( cc_library( name = "grpc_unsecure", srcs = [ - "src/core/channel/census_filter.h", + "src/core/census/grpc_context.h", "src/core/channel/channel_args.h", "src/core/channel/channel_stack.h", "src/core/channel/child_channel.h", @@ -419,12 +411,6 @@ cc_library( "src/core/json/json_writer.h", "src/core/profiling/timers.h", "src/core/profiling/timers_preciseclock.h", - "src/core/statistics/census_interface.h", - "src/core/statistics/census_log.h", - "src/core/statistics/census_rpc_stats.h", - "src/core/statistics/census_tracing.h", - "src/core/statistics/hash_table.h", - "src/core/statistics/window_stats.h", "src/core/surface/byte_buffer_queue.h", "src/core/surface/call.h", "src/core/surface/channel.h", @@ -457,8 +443,9 @@ cc_library( "src/core/transport/stream_op.h", "src/core/transport/transport.h", "src/core/transport/transport_impl.h", + "src/core/census/context.h", "src/core/surface/init_unsecure.c", - "src/core/channel/census_filter.c", + "src/core/census/grpc_context.c", "src/core/channel/channel_args.c", "src/core/channel/channel_stack.c", "src/core/channel/child_channel.c", @@ -510,12 +497,6 @@ cc_library( "src/core/json/json_writer.c", "src/core/profiling/basic_timers.c", "src/core/profiling/stap_timers.c", - "src/core/statistics/census_init.c", - "src/core/statistics/census_log.c", - "src/core/statistics/census_rpc_stats.c", - "src/core/statistics/census_tracing.c", - "src/core/statistics/hash_table.c", - "src/core/statistics/window_stats.c", "src/core/surface/byte_buffer.c", "src/core/surface/byte_buffer_queue.c", "src/core/surface/byte_buffer_reader.c", @@ -555,12 +536,15 @@ cc_library( "src/core/transport/stream_op.c", "src/core/transport/transport.c", "src/core/transport/transport_op_string.c", + "src/core/census/context.c", + "src/core/census/initialize.c", ], hdrs = [ "include/grpc/byte_buffer.h", "include/grpc/byte_buffer_reader.h", "include/grpc/grpc.h", "include/grpc/status.h", + "include/grpc/census.h", ], includes = [ "include", diff --git a/Makefile b/Makefile index 45910714137..ac6df5ea026 100644 --- a/Makefile +++ b/Makefile @@ -595,16 +595,6 @@ alarm_list_test: $(BINDIR)/$(CONFIG)/alarm_list_test alarm_test: $(BINDIR)/$(CONFIG)/alarm_test alpn_test: $(BINDIR)/$(CONFIG)/alpn_test bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test -census_hash_table_test: $(BINDIR)/$(CONFIG)/census_hash_table_test -census_statistics_multiple_writers_circular_buffer_test: $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_circular_buffer_test -census_statistics_multiple_writers_test: $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_test -census_statistics_performance_test: $(BINDIR)/$(CONFIG)/census_statistics_performance_test -census_statistics_quick_test: $(BINDIR)/$(CONFIG)/census_statistics_quick_test -census_statistics_small_log_test: $(BINDIR)/$(CONFIG)/census_statistics_small_log_test -census_stats_store_test: $(BINDIR)/$(CONFIG)/census_stats_store_test -census_stub_test: $(BINDIR)/$(CONFIG)/census_stub_test -census_trace_store_test: $(BINDIR)/$(CONFIG)/census_trace_store_test -census_window_stats_test: $(BINDIR)/$(CONFIG)/census_window_stats_test chttp2_status_conversion_test: $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test chttp2_stream_encoder_test: $(BINDIR)/$(CONFIG)/chttp2_stream_encoder_test chttp2_stream_map_test: $(BINDIR)/$(CONFIG)/chttp2_stream_map_test @@ -1093,7 +1083,7 @@ privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG buildtests: buildtests_c buildtests_cxx -buildtests_c: privatelibs_c $(BINDIR)/$(CONFIG)/alarm_heap_test $(BINDIR)/$(CONFIG)/alarm_list_test $(BINDIR)/$(CONFIG)/alarm_test $(BINDIR)/$(CONFIG)/alpn_test $(BINDIR)/$(CONFIG)/bin_encoder_test $(BINDIR)/$(CONFIG)/census_hash_table_test $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_circular_buffer_test $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_test $(BINDIR)/$(CONFIG)/census_statistics_performance_test $(BINDIR)/$(CONFIG)/census_statistics_quick_test $(BINDIR)/$(CONFIG)/census_statistics_small_log_test $(BINDIR)/$(CONFIG)/census_stub_test $(BINDIR)/$(CONFIG)/census_window_stats_test $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test $(BINDIR)/$(CONFIG)/chttp2_stream_encoder_test $(BINDIR)/$(CONFIG)/chttp2_stream_map_test $(BINDIR)/$(CONFIG)/dualstack_socket_test $(BINDIR)/$(CONFIG)/fd_posix_test $(BINDIR)/$(CONFIG)/fling_client $(BINDIR)/$(CONFIG)/fling_server $(BINDIR)/$(CONFIG)/fling_stream_test $(BINDIR)/$(CONFIG)/fling_test $(BINDIR)/$(CONFIG)/gpr_cancellable_test $(BINDIR)/$(CONFIG)/gpr_cmdline_test $(BINDIR)/$(CONFIG)/gpr_env_test $(BINDIR)/$(CONFIG)/gpr_file_test $(BINDIR)/$(CONFIG)/gpr_histogram_test $(BINDIR)/$(CONFIG)/gpr_host_port_test $(BINDIR)/$(CONFIG)/gpr_log_test $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test $(BINDIR)/$(CONFIG)/gpr_slice_test $(BINDIR)/$(CONFIG)/gpr_string_test $(BINDIR)/$(CONFIG)/gpr_sync_test $(BINDIR)/$(CONFIG)/gpr_thd_test $(BINDIR)/$(CONFIG)/gpr_time_test $(BINDIR)/$(CONFIG)/gpr_tls_test $(BINDIR)/$(CONFIG)/gpr_useful_test $(BINDIR)/$(CONFIG)/grpc_base64_test $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test $(BINDIR)/$(CONFIG)/grpc_channel_stack_test $(BINDIR)/$(CONFIG)/grpc_completion_queue_test $(BINDIR)/$(CONFIG)/grpc_credentials_test $(BINDIR)/$(CONFIG)/grpc_json_token_test $(BINDIR)/$(CONFIG)/grpc_stream_op_test $(BINDIR)/$(CONFIG)/hpack_parser_test $(BINDIR)/$(CONFIG)/hpack_table_test $(BINDIR)/$(CONFIG)/httpcli_format_request_test $(BINDIR)/$(CONFIG)/httpcli_parser_test $(BINDIR)/$(CONFIG)/httpcli_test $(BINDIR)/$(CONFIG)/json_rewrite $(BINDIR)/$(CONFIG)/json_rewrite_test $(BINDIR)/$(CONFIG)/json_test $(BINDIR)/$(CONFIG)/lame_client_test $(BINDIR)/$(CONFIG)/message_compress_test $(BINDIR)/$(CONFIG)/multi_init_test $(BINDIR)/$(CONFIG)/murmur_hash_test $(BINDIR)/$(CONFIG)/no_server_test $(BINDIR)/$(CONFIG)/poll_kick_posix_test $(BINDIR)/$(CONFIG)/resolve_address_test $(BINDIR)/$(CONFIG)/secure_endpoint_test $(BINDIR)/$(CONFIG)/sockaddr_utils_test $(BINDIR)/$(CONFIG)/tcp_client_posix_test $(BINDIR)/$(CONFIG)/tcp_posix_test $(BINDIR)/$(CONFIG)/tcp_server_posix_test $(BINDIR)/$(CONFIG)/time_averaged_stats_test $(BINDIR)/$(CONFIG)/time_test $(BINDIR)/$(CONFIG)/timeout_encoding_test $(BINDIR)/$(CONFIG)/timers_test $(BINDIR)/$(CONFIG)/transport_metadata_test $(BINDIR)/$(CONFIG)/transport_security_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_unsecure_test +buildtests_c: privatelibs_c $(BINDIR)/$(CONFIG)/alarm_heap_test $(BINDIR)/$(CONFIG)/alarm_list_test $(BINDIR)/$(CONFIG)/alarm_test $(BINDIR)/$(CONFIG)/alpn_test $(BINDIR)/$(CONFIG)/bin_encoder_test $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test $(BINDIR)/$(CONFIG)/chttp2_stream_encoder_test $(BINDIR)/$(CONFIG)/chttp2_stream_map_test $(BINDIR)/$(CONFIG)/dualstack_socket_test $(BINDIR)/$(CONFIG)/fd_posix_test $(BINDIR)/$(CONFIG)/fling_client $(BINDIR)/$(CONFIG)/fling_server $(BINDIR)/$(CONFIG)/fling_stream_test $(BINDIR)/$(CONFIG)/fling_test $(BINDIR)/$(CONFIG)/gpr_cancellable_test $(BINDIR)/$(CONFIG)/gpr_cmdline_test $(BINDIR)/$(CONFIG)/gpr_env_test $(BINDIR)/$(CONFIG)/gpr_file_test $(BINDIR)/$(CONFIG)/gpr_histogram_test $(BINDIR)/$(CONFIG)/gpr_host_port_test $(BINDIR)/$(CONFIG)/gpr_log_test $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test $(BINDIR)/$(CONFIG)/gpr_slice_test $(BINDIR)/$(CONFIG)/gpr_string_test $(BINDIR)/$(CONFIG)/gpr_sync_test $(BINDIR)/$(CONFIG)/gpr_thd_test $(BINDIR)/$(CONFIG)/gpr_time_test $(BINDIR)/$(CONFIG)/gpr_tls_test $(BINDIR)/$(CONFIG)/gpr_useful_test $(BINDIR)/$(CONFIG)/grpc_base64_test $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test $(BINDIR)/$(CONFIG)/grpc_channel_stack_test $(BINDIR)/$(CONFIG)/grpc_completion_queue_test $(BINDIR)/$(CONFIG)/grpc_credentials_test $(BINDIR)/$(CONFIG)/grpc_json_token_test $(BINDIR)/$(CONFIG)/grpc_stream_op_test $(BINDIR)/$(CONFIG)/hpack_parser_test $(BINDIR)/$(CONFIG)/hpack_table_test $(BINDIR)/$(CONFIG)/httpcli_format_request_test $(BINDIR)/$(CONFIG)/httpcli_parser_test $(BINDIR)/$(CONFIG)/httpcli_test $(BINDIR)/$(CONFIG)/json_rewrite $(BINDIR)/$(CONFIG)/json_rewrite_test $(BINDIR)/$(CONFIG)/json_test $(BINDIR)/$(CONFIG)/lame_client_test $(BINDIR)/$(CONFIG)/message_compress_test $(BINDIR)/$(CONFIG)/multi_init_test $(BINDIR)/$(CONFIG)/murmur_hash_test $(BINDIR)/$(CONFIG)/no_server_test $(BINDIR)/$(CONFIG)/poll_kick_posix_test $(BINDIR)/$(CONFIG)/resolve_address_test $(BINDIR)/$(CONFIG)/secure_endpoint_test $(BINDIR)/$(CONFIG)/sockaddr_utils_test $(BINDIR)/$(CONFIG)/tcp_client_posix_test $(BINDIR)/$(CONFIG)/tcp_posix_test $(BINDIR)/$(CONFIG)/tcp_server_posix_test $(BINDIR)/$(CONFIG)/time_averaged_stats_test $(BINDIR)/$(CONFIG)/time_test $(BINDIR)/$(CONFIG)/timeout_encoding_test $(BINDIR)/$(CONFIG)/timers_test $(BINDIR)/$(CONFIG)/transport_metadata_test $(BINDIR)/$(CONFIG)/transport_security_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_message_length_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_registered_call_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_and_call_creds_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_posix_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_with_high_initial_sequence_number_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_bad_hostname_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_empty_batch_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_message_length_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_registered_call_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_unsecure_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_unsecure_test buildtests_cxx: privatelibs_cxx $(BINDIR)/$(CONFIG)/async_end2end_test $(BINDIR)/$(CONFIG)/async_streaming_ping_pong_test $(BINDIR)/$(CONFIG)/async_unary_ping_pong_test $(BINDIR)/$(CONFIG)/channel_arguments_test $(BINDIR)/$(CONFIG)/cli_call_test $(BINDIR)/$(CONFIG)/credentials_test $(BINDIR)/$(CONFIG)/cxx_time_test $(BINDIR)/$(CONFIG)/end2end_test $(BINDIR)/$(CONFIG)/generic_end2end_test $(BINDIR)/$(CONFIG)/grpc_cli $(BINDIR)/$(CONFIG)/interop_client $(BINDIR)/$(CONFIG)/interop_server $(BINDIR)/$(CONFIG)/interop_test $(BINDIR)/$(CONFIG)/mock_test $(BINDIR)/$(CONFIG)/status_test $(BINDIR)/$(CONFIG)/sync_streaming_ping_pong_test $(BINDIR)/$(CONFIG)/sync_unary_ping_pong_test $(BINDIR)/$(CONFIG)/thread_pool_test $(BINDIR)/$(CONFIG)/thread_stress_test @@ -1110,22 +1100,6 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/alpn_test || ( echo test alpn_test failed ; exit 1 ) $(E) "[RUN] Testing bin_encoder_test" $(Q) $(BINDIR)/$(CONFIG)/bin_encoder_test || ( echo test bin_encoder_test failed ; exit 1 ) - $(E) "[RUN] Testing census_hash_table_test" - $(Q) $(BINDIR)/$(CONFIG)/census_hash_table_test || ( echo test census_hash_table_test failed ; exit 1 ) - $(E) "[RUN] Testing census_statistics_multiple_writers_circular_buffer_test" - $(Q) $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_circular_buffer_test || ( echo test census_statistics_multiple_writers_circular_buffer_test failed ; exit 1 ) - $(E) "[RUN] Testing census_statistics_multiple_writers_test" - $(Q) $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_test || ( echo test census_statistics_multiple_writers_test failed ; exit 1 ) - $(E) "[RUN] Testing census_statistics_performance_test" - $(Q) $(BINDIR)/$(CONFIG)/census_statistics_performance_test || ( echo test census_statistics_performance_test failed ; exit 1 ) - $(E) "[RUN] Testing census_statistics_quick_test" - $(Q) $(BINDIR)/$(CONFIG)/census_statistics_quick_test || ( echo test census_statistics_quick_test failed ; exit 1 ) - $(E) "[RUN] Testing census_statistics_small_log_test" - $(Q) $(BINDIR)/$(CONFIG)/census_statistics_small_log_test || ( echo test census_statistics_small_log_test failed ; exit 1 ) - $(E) "[RUN] Testing census_stub_test" - $(Q) $(BINDIR)/$(CONFIG)/census_stub_test || ( echo test census_stub_test failed ; exit 1 ) - $(E) "[RUN] Testing census_window_stats_test" - $(Q) $(BINDIR)/$(CONFIG)/census_window_stats_test || ( echo test census_window_stats_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_status_conversion_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test || ( echo test chttp2_status_conversion_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_stream_encoder_test" @@ -2468,7 +2442,7 @@ LIBGRPC_SRC = \ src/core/tsi/fake_transport_security.c \ src/core/tsi/ssl_transport_security.c \ src/core/tsi/transport_security.c \ - src/core/channel/census_filter.c \ + src/core/census/grpc_context.c \ src/core/channel/channel_args.c \ src/core/channel/channel_stack.c \ src/core/channel/child_channel.c \ @@ -2520,12 +2494,6 @@ LIBGRPC_SRC = \ src/core/json/json_writer.c \ src/core/profiling/basic_timers.c \ src/core/profiling/stap_timers.c \ - src/core/statistics/census_init.c \ - src/core/statistics/census_log.c \ - src/core/statistics/census_rpc_stats.c \ - src/core/statistics/census_tracing.c \ - src/core/statistics/hash_table.c \ - src/core/statistics/window_stats.c \ src/core/surface/byte_buffer.c \ src/core/surface/byte_buffer_queue.c \ src/core/surface/byte_buffer_reader.c \ @@ -2565,6 +2533,8 @@ LIBGRPC_SRC = \ src/core/transport/stream_op.c \ src/core/transport/transport.c \ src/core/transport/transport_op_string.c \ + src/core/census/context.c \ + src/core/census/initialize.c \ PUBLIC_HEADERS_C += \ include/grpc/grpc_security.h \ @@ -2572,6 +2542,7 @@ PUBLIC_HEADERS_C += \ include/grpc/byte_buffer_reader.h \ include/grpc/grpc.h \ include/grpc/status.h \ + include/grpc/census.h \ LIBGRPC_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_SRC)))) @@ -2641,7 +2612,6 @@ LIBGRPC_TEST_UTIL_SRC = \ test/core/end2end/data/test_root_cert.c \ test/core/end2end/cq_verifier.c \ test/core/iomgr/endpoint_tests.c \ - test/core/statistics/census_log_tests.c \ test/core/util/grpc_profiler.c \ test/core/util/parse_hexstring.c \ test/core/util/port_posix.c \ @@ -2686,7 +2656,6 @@ endif LIBGRPC_TEST_UTIL_UNSECURE_SRC = \ test/core/end2end/cq_verifier.c \ test/core/iomgr/endpoint_tests.c \ - test/core/statistics/census_log_tests.c \ test/core/util/grpc_profiler.c \ test/core/util/parse_hexstring.c \ test/core/util/port_posix.c \ @@ -2716,7 +2685,7 @@ endif LIBGRPC_UNSECURE_SRC = \ src/core/surface/init_unsecure.c \ - src/core/channel/census_filter.c \ + src/core/census/grpc_context.c \ src/core/channel/channel_args.c \ src/core/channel/channel_stack.c \ src/core/channel/child_channel.c \ @@ -2768,12 +2737,6 @@ LIBGRPC_UNSECURE_SRC = \ src/core/json/json_writer.c \ src/core/profiling/basic_timers.c \ src/core/profiling/stap_timers.c \ - src/core/statistics/census_init.c \ - src/core/statistics/census_log.c \ - src/core/statistics/census_rpc_stats.c \ - src/core/statistics/census_tracing.c \ - src/core/statistics/hash_table.c \ - src/core/statistics/window_stats.c \ src/core/surface/byte_buffer.c \ src/core/surface/byte_buffer_queue.c \ src/core/surface/byte_buffer_reader.c \ @@ -2813,12 +2776,15 @@ LIBGRPC_UNSECURE_SRC = \ src/core/transport/stream_op.c \ src/core/transport/transport.c \ src/core/transport/transport_op_string.c \ + src/core/census/context.c \ + src/core/census/initialize.c \ PUBLIC_HEADERS_C += \ include/grpc/byte_buffer.h \ include/grpc/byte_buffer_reader.h \ include/grpc/grpc.h \ include/grpc/status.h \ + include/grpc/census.h \ LIBGRPC_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_UNSECURE_SRC)))) @@ -4666,296 +4632,6 @@ endif endif -CENSUS_HASH_TABLE_TEST_SRC = \ - test/core/statistics/hash_table_test.c \ - -CENSUS_HASH_TABLE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_HASH_TABLE_TEST_SRC)))) -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -$(BINDIR)/$(CONFIG)/census_hash_table_test: openssl_dep_error - -else - -$(BINDIR)/$(CONFIG)/census_hash_table_test: $(CENSUS_HASH_TABLE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(CENSUS_HASH_TABLE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/census_hash_table_test - -endif - -$(OBJDIR)/$(CONFIG)/test/core/statistics/hash_table_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -deps_census_hash_table_test: $(CENSUS_HASH_TABLE_TEST_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(CENSUS_HASH_TABLE_TEST_OBJS:.o=.dep) -endif -endif - - -CENSUS_STATISTICS_MULTIPLE_WRITERS_CIRCULAR_BUFFER_TEST_SRC = \ - test/core/statistics/multiple_writers_circular_buffer_test.c \ - -CENSUS_STATISTICS_MULTIPLE_WRITERS_CIRCULAR_BUFFER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_STATISTICS_MULTIPLE_WRITERS_CIRCULAR_BUFFER_TEST_SRC)))) -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -$(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_circular_buffer_test: openssl_dep_error - -else - -$(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_circular_buffer_test: $(CENSUS_STATISTICS_MULTIPLE_WRITERS_CIRCULAR_BUFFER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(CENSUS_STATISTICS_MULTIPLE_WRITERS_CIRCULAR_BUFFER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_circular_buffer_test - -endif - -$(OBJDIR)/$(CONFIG)/test/core/statistics/multiple_writers_circular_buffer_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -deps_census_statistics_multiple_writers_circular_buffer_test: $(CENSUS_STATISTICS_MULTIPLE_WRITERS_CIRCULAR_BUFFER_TEST_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(CENSUS_STATISTICS_MULTIPLE_WRITERS_CIRCULAR_BUFFER_TEST_OBJS:.o=.dep) -endif -endif - - -CENSUS_STATISTICS_MULTIPLE_WRITERS_TEST_SRC = \ - test/core/statistics/multiple_writers_test.c \ - -CENSUS_STATISTICS_MULTIPLE_WRITERS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_STATISTICS_MULTIPLE_WRITERS_TEST_SRC)))) -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -$(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_test: openssl_dep_error - -else - -$(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_test: $(CENSUS_STATISTICS_MULTIPLE_WRITERS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(CENSUS_STATISTICS_MULTIPLE_WRITERS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_test - -endif - -$(OBJDIR)/$(CONFIG)/test/core/statistics/multiple_writers_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -deps_census_statistics_multiple_writers_test: $(CENSUS_STATISTICS_MULTIPLE_WRITERS_TEST_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(CENSUS_STATISTICS_MULTIPLE_WRITERS_TEST_OBJS:.o=.dep) -endif -endif - - -CENSUS_STATISTICS_PERFORMANCE_TEST_SRC = \ - test/core/statistics/performance_test.c \ - -CENSUS_STATISTICS_PERFORMANCE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_STATISTICS_PERFORMANCE_TEST_SRC)))) -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -$(BINDIR)/$(CONFIG)/census_statistics_performance_test: openssl_dep_error - -else - -$(BINDIR)/$(CONFIG)/census_statistics_performance_test: $(CENSUS_STATISTICS_PERFORMANCE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(CENSUS_STATISTICS_PERFORMANCE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/census_statistics_performance_test - -endif - -$(OBJDIR)/$(CONFIG)/test/core/statistics/performance_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -deps_census_statistics_performance_test: $(CENSUS_STATISTICS_PERFORMANCE_TEST_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(CENSUS_STATISTICS_PERFORMANCE_TEST_OBJS:.o=.dep) -endif -endif - - -CENSUS_STATISTICS_QUICK_TEST_SRC = \ - test/core/statistics/quick_test.c \ - -CENSUS_STATISTICS_QUICK_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_STATISTICS_QUICK_TEST_SRC)))) -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -$(BINDIR)/$(CONFIG)/census_statistics_quick_test: openssl_dep_error - -else - -$(BINDIR)/$(CONFIG)/census_statistics_quick_test: $(CENSUS_STATISTICS_QUICK_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(CENSUS_STATISTICS_QUICK_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/census_statistics_quick_test - -endif - -$(OBJDIR)/$(CONFIG)/test/core/statistics/quick_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -deps_census_statistics_quick_test: $(CENSUS_STATISTICS_QUICK_TEST_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(CENSUS_STATISTICS_QUICK_TEST_OBJS:.o=.dep) -endif -endif - - -CENSUS_STATISTICS_SMALL_LOG_TEST_SRC = \ - test/core/statistics/small_log_test.c \ - -CENSUS_STATISTICS_SMALL_LOG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_STATISTICS_SMALL_LOG_TEST_SRC)))) -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -$(BINDIR)/$(CONFIG)/census_statistics_small_log_test: openssl_dep_error - -else - -$(BINDIR)/$(CONFIG)/census_statistics_small_log_test: $(CENSUS_STATISTICS_SMALL_LOG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(CENSUS_STATISTICS_SMALL_LOG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/census_statistics_small_log_test - -endif - -$(OBJDIR)/$(CONFIG)/test/core/statistics/small_log_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -deps_census_statistics_small_log_test: $(CENSUS_STATISTICS_SMALL_LOG_TEST_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(CENSUS_STATISTICS_SMALL_LOG_TEST_OBJS:.o=.dep) -endif -endif - - -CENSUS_STATS_STORE_TEST_SRC = \ - test/core/statistics/rpc_stats_test.c \ - -CENSUS_STATS_STORE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_STATS_STORE_TEST_SRC)))) -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -$(BINDIR)/$(CONFIG)/census_stats_store_test: openssl_dep_error - -else - -$(BINDIR)/$(CONFIG)/census_stats_store_test: $(CENSUS_STATS_STORE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(CENSUS_STATS_STORE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/census_stats_store_test - -endif - -$(OBJDIR)/$(CONFIG)/test/core/statistics/rpc_stats_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -deps_census_stats_store_test: $(CENSUS_STATS_STORE_TEST_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(CENSUS_STATS_STORE_TEST_OBJS:.o=.dep) -endif -endif - - -CENSUS_STUB_TEST_SRC = \ - test/core/statistics/census_stub_test.c \ - -CENSUS_STUB_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_STUB_TEST_SRC)))) -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -$(BINDIR)/$(CONFIG)/census_stub_test: openssl_dep_error - -else - -$(BINDIR)/$(CONFIG)/census_stub_test: $(CENSUS_STUB_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(CENSUS_STUB_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/census_stub_test - -endif - -$(OBJDIR)/$(CONFIG)/test/core/statistics/census_stub_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -deps_census_stub_test: $(CENSUS_STUB_TEST_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(CENSUS_STUB_TEST_OBJS:.o=.dep) -endif -endif - - -CENSUS_TRACE_STORE_TEST_SRC = \ - test/core/statistics/trace_test.c \ - -CENSUS_TRACE_STORE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_TRACE_STORE_TEST_SRC)))) -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -$(BINDIR)/$(CONFIG)/census_trace_store_test: openssl_dep_error - -else - -$(BINDIR)/$(CONFIG)/census_trace_store_test: $(CENSUS_TRACE_STORE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(CENSUS_TRACE_STORE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/census_trace_store_test - -endif - -$(OBJDIR)/$(CONFIG)/test/core/statistics/trace_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -deps_census_trace_store_test: $(CENSUS_TRACE_STORE_TEST_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(CENSUS_TRACE_STORE_TEST_OBJS:.o=.dep) -endif -endif - - -CENSUS_WINDOW_STATS_TEST_SRC = \ - test/core/statistics/window_stats_test.c \ - -CENSUS_WINDOW_STATS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_WINDOW_STATS_TEST_SRC)))) -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -$(BINDIR)/$(CONFIG)/census_window_stats_test: openssl_dep_error - -else - -$(BINDIR)/$(CONFIG)/census_window_stats_test: $(CENSUS_WINDOW_STATS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(CENSUS_WINDOW_STATS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/census_window_stats_test - -endif - -$(OBJDIR)/$(CONFIG)/test/core/statistics/window_stats_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -deps_census_window_stats_test: $(CENSUS_WINDOW_STATS_TEST_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(CENSUS_WINDOW_STATS_TEST_OBJS:.o=.dep) -endif -endif - - CHTTP2_STATUS_CONVERSION_TEST_SRC = \ test/core/transport/chttp2/status_conversion_test.c \ diff --git a/build.json b/build.json index 18c0eb1211d..aadd22f9bbb 100644 --- a/build.json +++ b/build.json @@ -12,6 +12,19 @@ } }, "filegroups": [ + { + "name": "census", + "public_headers": [ + "include/grpc/census.h" + ], + "headers": [ + "src/core/census/context.h" + ], + "src": [ + "src/core/census/context.c", + "src/core/census/initialize.c" + ] + }, { "name": "grpc++_base", "public_headers": [ @@ -91,7 +104,7 @@ "include/grpc/status.h" ], "headers": [ - "src/core/channel/census_filter.h", + "src/core/census/grpc_context.h", "src/core/channel/channel_args.h", "src/core/channel/channel_stack.h", "src/core/channel/child_channel.h", @@ -140,12 +153,6 @@ "src/core/json/json_writer.h", "src/core/profiling/timers.h", "src/core/profiling/timers_preciseclock.h", - "src/core/statistics/census_interface.h", - "src/core/statistics/census_log.h", - "src/core/statistics/census_rpc_stats.h", - "src/core/statistics/census_tracing.h", - "src/core/statistics/hash_table.h", - "src/core/statistics/window_stats.h", "src/core/surface/byte_buffer_queue.h", "src/core/surface/call.h", "src/core/surface/channel.h", @@ -180,7 +187,7 @@ "src/core/transport/transport_impl.h" ], "src": [ - "src/core/channel/census_filter.c", + "src/core/census/grpc_context.c", "src/core/channel/channel_args.c", "src/core/channel/channel_stack.c", "src/core/channel/child_channel.c", @@ -232,12 +239,6 @@ "src/core/json/json_writer.c", "src/core/profiling/basic_timers.c", "src/core/profiling/stap_timers.c", - "src/core/statistics/census_init.c", - "src/core/statistics/census_log.c", - "src/core/statistics/census_rpc_stats.c", - "src/core/statistics/census_tracing.c", - "src/core/statistics/hash_table.c", - "src/core/statistics/window_stats.c", "src/core/surface/byte_buffer.c", "src/core/surface/byte_buffer_queue.c", "src/core/surface/byte_buffer_reader.c", @@ -284,7 +285,6 @@ "src": [ "test/core/end2end/cq_verifier.c", "test/core/iomgr/endpoint_tests.c", - "test/core/statistics/census_log_tests.c", "test/core/util/grpc_profiler.c", "test/core/util/parse_hexstring.c", "test/core/util/port_posix.c", @@ -446,7 +446,8 @@ ], "baselib": true, "filegroups": [ - "grpc_base" + "grpc_base", + "census" ], "secure": "yes", "vs_project_guid": "{29D16885-7228-4C31-81ED-5F9187C7F2A9}" @@ -497,7 +498,8 @@ ], "baselib": true, "filegroups": [ - "grpc_base" + "grpc_base", + "census" ], "secure": "no", "vs_project_guid": "{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}" @@ -788,151 +790,6 @@ "gpr" ] }, - { - "name": "census_hash_table_test", - "build": "test", - "language": "c", - "src": [ - "test/core/statistics/hash_table_test.c" - ], - "deps": [ - "grpc_test_util", - "grpc", - "gpr_test_util", - "gpr" - ] - }, - { - "name": "census_statistics_multiple_writers_circular_buffer_test", - "flaky": true, - "build": "test", - "language": "c", - "src": [ - "test/core/statistics/multiple_writers_circular_buffer_test.c" - ], - "deps": [ - "grpc_test_util", - "grpc", - "gpr_test_util", - "gpr" - ] - }, - { - "name": "census_statistics_multiple_writers_test", - "flaky": true, - "build": "test", - "language": "c", - "src": [ - "test/core/statistics/multiple_writers_test.c" - ], - "deps": [ - "grpc_test_util", - "grpc", - "gpr_test_util", - "gpr" - ] - }, - { - "name": "census_statistics_performance_test", - "flaky": true, - "build": "test", - "language": "c", - "src": [ - "test/core/statistics/performance_test.c" - ], - "deps": [ - "grpc_test_util", - "grpc", - "gpr_test_util", - "gpr" - ] - }, - { - "name": "census_statistics_quick_test", - "flaky": true, - "build": "test", - "language": "c", - "src": [ - "test/core/statistics/quick_test.c" - ], - "deps": [ - "grpc_test_util", - "grpc", - "gpr_test_util", - "gpr" - ] - }, - { - "name": "census_statistics_small_log_test", - "flaky": true, - "build": "test", - "language": "c", - "src": [ - "test/core/statistics/small_log_test.c" - ], - "deps": [ - "grpc_test_util", - "grpc", - "gpr_test_util", - "gpr" - ] - }, - { - "name": "census_stats_store_test", - "build": "executable", - "language": "c", - "src": [ - "test/core/statistics/rpc_stats_test.c" - ], - "deps": [ - "grpc_test_util", - "grpc", - "gpr_test_util", - "gpr" - ] - }, - { - "name": "census_stub_test", - "build": "test", - "language": "c", - "src": [ - "test/core/statistics/census_stub_test.c" - ], - "deps": [ - "grpc_test_util", - "grpc", - "gpr_test_util", - "gpr" - ] - }, - { - "name": "census_trace_store_test", - "build": "executable", - "language": "c", - "src": [ - "test/core/statistics/trace_test.c" - ], - "deps": [ - "grpc_test_util", - "grpc", - "gpr_test_util", - "gpr" - ] - }, - { - "name": "census_window_stats_test", - "build": "test", - "language": "c", - "src": [ - "test/core/statistics/window_stats_test.c" - ], - "deps": [ - "grpc_test_util", - "grpc", - "gpr_test_util", - "gpr" - ] - }, { "name": "chttp2_status_conversion_test", "build": "test", diff --git a/include/grpc/census.h b/include/grpc/census.h new file mode 100644 index 00000000000..338d02ba1cf --- /dev/null +++ b/include/grpc/census.h @@ -0,0 +1,91 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* RPC-internal Census API's. These are designed to be generic enough that + * they can (ultimately) be used in many different RPC systems (with differing + * implementations). */ + +#ifndef CENSUS_CENSUS_H +#define CENSUS_CENSUS_H + +#include +#include + +/* Identify census functionality that can be enabled via census_initialize(). */ +enum census_functions { + CENSUS_NONE = 0, /* Do not enable census. */ + CENSUS_TRACING = 1, /* Enable census tracing. */ + CENSUS_STATS = 2, /* Enable Census stats collection. */ + CENSUS_CPU = 4, /* Enable Census CPU usage collection. */ + CENSUS_ALL = CENSUS_TRACING | CENSUS_STATS | CENSUS_CPU +}; + +/* Shutdown and startup census subsystem. The 'functions' argument should be + * the OR (|) of census_functions values. If census fails to initialize, then + * census_initialize() will return a non-zero value. */ +int census_initialize(int functions); +void census_shutdown(); + +/* Internally, Census relies on a context, which should be propagated across + * RPC's. From the RPC subsystems viewpoint, this is an opaque data structure. + * A context must be used as the first argument to all other census + * functions. The context can be serialized for passing across the wire. */ +typedef struct census_context census_context; + +/* This function is called by the RPC subsystem whenever it needs to get a + * serialized form of the current census context (presumably to pass across + * the wire). Arguments: + * 'buffer': pointer to memory into which serialized context will be placed + * 'buf_size': size of 'buffer' + * + * Returns: the number of bytes used in buffer if successful, or 0 if the + * buffer is of insufficient size. + * + * TODO(aveitch): determine how best to communicate required/max buffer size + * so caller doesn't have to guess. */ +size_t census_context_serialize(const census_context *context, char *buffer, + size_t buf_size); + +/* Create a new census context, possibly from a serialized buffer. If 'buffer' + * is non-NULL, it is assumed that it is a buffer encoded by + * census_context_serialize(). If `buffer` is NULL, a new, empty context is + * created. + * + * Returns NULL on error (buffer is incorrectly formatted) */ +census_context *census_context_deserialize(char *buffer); + +/* The given context is destroyed. Once destroyed, using the context in + * future census calls will result in undefined behavior. */ +void census_context_destroy(census_context *context); + +#endif /* CENSUS_CENSUS_H */ diff --git a/src/core/census/README.md b/src/core/census/README.md new file mode 100644 index 00000000000..fb615a2194d --- /dev/null +++ b/src/core/census/README.md @@ -0,0 +1,76 @@ + + +# Census - a resource measurement and tracing system + +This directory contains code for Census, which will ultimately provide the +following features for any gRPC-using system: +* A [dapper](http://research.google.com/pubs/pub36356.html)-like tracing + system, enabling tracing across a distributed infrastructure. +* RPC statistics and measurements for key metrics, such as latency, bytes + transferred, number of errors etc. +* Resource measurement framework which can be used for measuring custom + metrics. Through the use of [tags](#Tags), these can be broken down across + the entire distributed stack. +* Easy integration of the above with + [Google Cloud Trace](https://cloud.google.com/tools/cloud-trace) and + [Google Cloud Monitoring](https://cloud.google.com/monitoring/). + +## Concepts + +### Context + +### Operations + +### Tags + +### Metrics + +## API + +### Internal/RPC API + +### External/Client API + +### RPC API + +## Files in this directory + +Note that files and functions in this directory can be split into two +categories: +* Files that define core census library functions. Functions etc. in these + files are named census\_\*, and constitute the core census library + functionality. At some time in the future, these will become a standalone + library. +* Files that define functions etc. that provide a convenient interface between + grpc and the core census functionality. These files are all named + grpc\_\*.{c,h}, and define function names beginning with grpc\_census\_\*. + diff --git a/src/core/census/context.c b/src/core/census/context.c new file mode 100644 index 00000000000..a940e96ec0c --- /dev/null +++ b/src/core/census/context.c @@ -0,0 +1,59 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "context.h" + +#include +#include +#include + +/* Placeholder implementation only. */ + +size_t census_context_serialize(const census_context *context, char *buffer, + size_t buf_size) { + /* TODO(aveitch): implement serialization */ + return 0; +} + +census_context *census_context_deserialize(char *buffer) { + census_context *ret; + if (buffer != NULL) { + /* TODO(aveitch): implement deserialization */ + return NULL; + } + ret = gpr_malloc(sizeof(census_context)); + memset(ret, 0, sizeof(census_context)); + return ret; +} + +void census_context_destroy(census_context *context) { gpr_free(context); } diff --git a/src/core/census/context.h b/src/core/census/context.h new file mode 100644 index 00000000000..d43a69f7e54 --- /dev/null +++ b/src/core/census/context.h @@ -0,0 +1,49 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_INTERNAL_CORE_CENSUS_CONTEXT_H +#define GRPC_INTERNAL_CORE_CENSUS_CONTEXT_H + +#include + +/* census_context is the in-memory representation of information needed to + * maintain tracing, RPC statistics and resource usage information. */ +struct census_context { + gpr_uint64 op_id; /* Operation identifier - unique per-context */ + gpr_uint64 trace_id; /* Globally unique trace identifier */ + /* TODO(aveitch) Add census tags: + const census_tag_set *tags; + */ +}; + +#endif /* GRPC_INTERNAL_CORE_CENSUS_CONTEXT_H */ diff --git a/src/core/census/grpc_context.c b/src/core/census/grpc_context.c new file mode 100644 index 00000000000..4b1ba49e707 --- /dev/null +++ b/src/core/census/grpc_context.c @@ -0,0 +1,41 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include "src/core/census/grpc_context.h" + +void *grpc_census_context_create() { return census_context_deserialize(NULL); } + +void grpc_census_context_destroy(void *context) { + census_context_destroy((census_context *)context); +} diff --git a/src/core/census/grpc_context.h b/src/core/census/grpc_context.h new file mode 100644 index 00000000000..f610f6ce21d --- /dev/null +++ b/src/core/census/grpc_context.h @@ -0,0 +1,42 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* GRPC <--> CENSUS context interface */ + +#ifndef CENSUS_GRPC_CONTEXT_H +#define CENSUS_GRPC_CONTEXT_H + +void *grpc_census_context_create(); +void grpc_census_context_destroy(void *context); + +#endif /* CENSUS_GRPC_CONTEXT_H */ diff --git a/src/core/census/initialize.c b/src/core/census/initialize.c new file mode 100644 index 00000000000..d72c08b91ca --- /dev/null +++ b/src/core/census/initialize.c @@ -0,0 +1,38 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +int census_initialize(int functions) { return 0; } + +void census_shutdown() {} diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 50df36cae9f..b0b922b6421 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -31,6 +31,7 @@ * */ +#include "src/core/census/grpc_context.h" #include "src/core/surface/call.h" #include "src/core/channel/channel_stack.h" #include "src/core/iomgr/alarm.h" @@ -242,9 +243,9 @@ static int fill_send_ops(grpc_call *call, grpc_transport_op *op); static void execute_op(grpc_call *call, grpc_transport_op *op); static void recv_metadata(grpc_call *call, grpc_metadata_batch *metadata); static void finish_read_ops(grpc_call *call); -static grpc_call_error cancel_with_status( - grpc_call *c, grpc_status_code status, const char *description, - gpr_uint8 locked); +static grpc_call_error cancel_with_status(grpc_call *c, grpc_status_code status, + const char *description, + gpr_uint8 locked); grpc_call *grpc_call_create(grpc_channel *channel, grpc_completion_queue *cq, const void *server_transport_data, @@ -268,6 +269,8 @@ grpc_call *grpc_call_create(grpc_channel *channel, grpc_completion_queue *cq, if (call->is_client) { call->request_set[GRPC_IOREQ_SEND_TRAILING_METADATA] = REQSET_DONE; call->request_set[GRPC_IOREQ_SEND_STATUS] = REQSET_DONE; + call->context[GRPC_CONTEXT_TRACING] = grpc_census_context_create(); + call->destroy_context[GRPC_CONTEXT_TRACING] = grpc_census_context_destroy; } GPR_ASSERT(add_initial_metadata_count < MAX_SEND_INITIAL_METADATA_COUNT); for (i = 0; i < add_initial_metadata_count; i++) { @@ -402,7 +405,8 @@ static void lock(grpc_call *call) { gpr_mu_lock(&call->mu); } static int need_more_data(grpc_call *call) { return is_op_live(call, GRPC_IOREQ_RECV_INITIAL_METADATA) || - (is_op_live(call, GRPC_IOREQ_RECV_MESSAGE) && grpc_bbq_empty(&call->incoming_queue)) || + (is_op_live(call, GRPC_IOREQ_RECV_MESSAGE) && + grpc_bbq_empty(&call->incoming_queue)) || is_op_live(call, GRPC_IOREQ_RECV_TRAILING_METADATA) || is_op_live(call, GRPC_IOREQ_RECV_STATUS) || is_op_live(call, GRPC_IOREQ_RECV_STATUS_DETAILS) || @@ -557,13 +561,13 @@ static void finish_live_ioreq_op(grpc_call *call, grpc_ioreq_op op, break; case GRPC_IOREQ_RECV_INITIAL_METADATA: GPR_SWAP(grpc_metadata_array, call->buffered_metadata[0], - *call->request_data[GRPC_IOREQ_RECV_INITIAL_METADATA] - .recv_metadata); + *call->request_data[GRPC_IOREQ_RECV_INITIAL_METADATA] + .recv_metadata); break; case GRPC_IOREQ_RECV_TRAILING_METADATA: GPR_SWAP(grpc_metadata_array, call->buffered_metadata[1], - *call->request_data[GRPC_IOREQ_RECV_TRAILING_METADATA] - .recv_metadata); + *call->request_data[GRPC_IOREQ_RECV_TRAILING_METADATA] + .recv_metadata); break; case GRPC_IOREQ_OP_COUNT: abort(); @@ -653,9 +657,8 @@ static int add_slice_to_message(grpc_call *call, gpr_slice slice) { } /* we have to be reading a message to know what to do here */ if (!call->reading_message) { - cancel_with_status( - call, GRPC_STATUS_INVALID_ARGUMENT, - "Received payload data while not reading a message", 1); + cancel_with_status(call, GRPC_STATUS_INVALID_ARGUMENT, + "Received payload data while not reading a message", 1); return 0; } /* append the slice to the incoming buffer */ @@ -1021,9 +1024,9 @@ grpc_call_error grpc_call_cancel_with_status(grpc_call *c, return cancel_with_status(c, status, description, 0); } -static grpc_call_error cancel_with_status( - grpc_call *c, grpc_status_code status, const char *description, - gpr_uint8 locked) { +static grpc_call_error cancel_with_status(grpc_call *c, grpc_status_code status, + const char *description, + gpr_uint8 locked) { grpc_transport_op op; grpc_mdstr *details = description ? grpc_mdstr_from_string(c->metadata_context, description) @@ -1287,8 +1290,8 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops, tag); } -void grpc_call_context_set(grpc_call *call, grpc_context_index elem, void *value, - void (*destroy)(void *value)) { +void grpc_call_context_set(grpc_call *call, grpc_context_index elem, + void *value, void (*destroy)(void *value)) { if (call->destroy_context[elem]) { call->destroy_context[elem](value); } diff --git a/src/core/surface/channel_create.c b/src/core/surface/channel_create.c index daa8d3a7c6a..9fa6696bf6b 100644 --- a/src/core/surface/channel_create.c +++ b/src/core/surface/channel_create.c @@ -195,9 +195,10 @@ grpc_channel *grpc_channel_create(const char *target, const grpc_channel_filter *filters[MAX_FILTERS]; int n = 0; filters[n++] = &grpc_client_surface_filter; + /* TODO(census) if (grpc_channel_args_is_census_enabled(args)) { filters[n++] = &grpc_client_census_filter; - } + } */ filters[n++] = &grpc_client_channel_filter; GPR_ASSERT(n <= MAX_FILTERS); channel = grpc_channel_create_from_filters(filters, n, args, mdctx, 1); diff --git a/src/core/surface/init.c b/src/core/surface/init.c index d6eb9b2c24b..5cd5d9197f3 100644 --- a/src/core/surface/init.c +++ b/src/core/surface/init.c @@ -31,11 +31,11 @@ * */ +#include #include #include "src/core/channel/channel_stack.h" #include "src/core/debug/trace.h" #include "src/core/iomgr/iomgr.h" -#include "src/core/statistics/census_interface.h" #include "src/core/profiling/timers.h" #include "src/core/surface/call.h" #include "src/core/surface/init.h" @@ -64,7 +64,7 @@ void grpc_init(void) { grpc_security_pre_init(); grpc_iomgr_init(); grpc_tracer_init("GRPC_TRACE"); - census_init(); + census_initialize(CENSUS_NONE); grpc_timers_global_init(); } gpr_mu_unlock(&g_init_mu); diff --git a/src/core/surface/secure_channel_create.c b/src/core/surface/secure_channel_create.c index 3e331293b5d..23156c981ed 100644 --- a/src/core/surface/secure_channel_create.c +++ b/src/core/surface/secure_channel_create.c @@ -234,9 +234,10 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds, new_args_from_connector != NULL ? new_args_from_connector : args, &connector_arg); filters[n++] = &grpc_client_surface_filter; + /* TODO(census) if (grpc_channel_args_is_census_enabled(args)) { filters[n++] = &grpc_client_census_filter; - } + } */ filters[n++] = &grpc_client_channel_filter; GPR_ASSERT(n <= MAX_FILTERS); channel = grpc_channel_create_from_filters(filters, n, args_copy, mdctx, 1); diff --git a/src/core/surface/server.c b/src/core/surface/server.c index 351ed5b7586..b8ac4106872 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -592,9 +592,15 @@ static void destroy_channel_elem(grpc_channel_element *elem) { } static const grpc_channel_filter server_surface_filter = { - server_start_transport_op, channel_op, sizeof(call_data), init_call_elem, - destroy_call_elem, sizeof(channel_data), init_channel_elem, - destroy_channel_elem, "server", + server_start_transport_op, + channel_op, + sizeof(call_data), + init_call_elem, + destroy_call_elem, + sizeof(channel_data), + init_channel_elem, + destroy_channel_elem, + "server", }; void grpc_server_register_completion_queue(grpc_server *server, @@ -640,9 +646,10 @@ grpc_server *grpc_server_create_from_filters(grpc_channel_filter **filters, server->channel_filters = gpr_malloc(server->channel_filter_count * sizeof(grpc_channel_filter *)); server->channel_filters[0] = &server_surface_filter; + /* TODO(census) if (census_enabled) { server->channel_filters[1] = &grpc_server_census_filter; - } + } */ for (i = 0; i < filter_count; i++) { server->channel_filters[i + 1 + census_enabled] = filters[i]; } diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json index d161041c1f6..93ae0961367 100644 --- a/tools/run_tests/tests.json +++ b/tools/run_tests/tests.json @@ -46,78 +46,6 @@ "posix" ] }, - { - "flaky": false, - "language": "c", - "name": "census_hash_table_test", - "platforms": [ - "windows", - "posix" - ] - }, - { - "flaky": true, - "language": "c", - "name": "census_statistics_multiple_writers_circular_buffer_test", - "platforms": [ - "windows", - "posix" - ] - }, - { - "flaky": true, - "language": "c", - "name": "census_statistics_multiple_writers_test", - "platforms": [ - "windows", - "posix" - ] - }, - { - "flaky": true, - "language": "c", - "name": "census_statistics_performance_test", - "platforms": [ - "windows", - "posix" - ] - }, - { - "flaky": true, - "language": "c", - "name": "census_statistics_quick_test", - "platforms": [ - "windows", - "posix" - ] - }, - { - "flaky": true, - "language": "c", - "name": "census_statistics_small_log_test", - "platforms": [ - "windows", - "posix" - ] - }, - { - "flaky": false, - "language": "c", - "name": "census_stub_test", - "platforms": [ - "windows", - "posix" - ] - }, - { - "flaky": false, - "language": "c", - "name": "census_window_stats_test", - "platforms": [ - "windows", - "posix" - ] - }, { "flaky": false, "language": "c", diff --git a/vsprojects/Grpc.mak b/vsprojects/Grpc.mak index 275ad42d843..964e501744b 100644 --- a/vsprojects/Grpc.mak +++ b/vsprojects/Grpc.mak @@ -57,7 +57,7 @@ $(OUT_DIR): build_libs: build_gpr build_gpr_test_util build_grpc build_grpc_test_util build_grpc_test_util_unsecure build_grpc_unsecure Debug\end2end_fixture_chttp2_fake_security.lib Debug\end2end_fixture_chttp2_fullstack.lib Debug\end2end_fixture_chttp2_simple_ssl_fullstack.lib Debug\end2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack.lib Debug\end2end_fixture_chttp2_socket_pair.lib Debug\end2end_fixture_chttp2_socket_pair_one_byte_at_a_time.lib Debug\end2end_test_bad_hostname.lib Debug\end2end_test_cancel_after_accept.lib Debug\end2end_test_cancel_after_accept_and_writes_closed.lib Debug\end2end_test_cancel_after_invoke.lib Debug\end2end_test_cancel_before_invoke.lib Debug\end2end_test_cancel_in_a_vacuum.lib Debug\end2end_test_census_simple_request.lib Debug\end2end_test_disappearing_server.lib Debug\end2end_test_early_server_shutdown_finishes_inflight_calls.lib Debug\end2end_test_early_server_shutdown_finishes_tags.lib Debug\end2end_test_empty_batch.lib Debug\end2end_test_graceful_server_shutdown.lib Debug\end2end_test_invoke_large_request.lib Debug\end2end_test_max_concurrent_streams.lib Debug\end2end_test_max_message_length.lib Debug\end2end_test_no_op.lib Debug\end2end_test_ping_pong_streaming.lib Debug\end2end_test_registered_call.lib Debug\end2end_test_request_response_with_binary_metadata_and_payload.lib Debug\end2end_test_request_response_with_metadata_and_payload.lib Debug\end2end_test_request_response_with_payload.lib Debug\end2end_test_request_response_with_payload_and_call_creds.lib Debug\end2end_test_request_response_with_trailing_metadata_and_payload.lib Debug\end2end_test_request_with_large_metadata.lib Debug\end2end_test_request_with_payload.lib Debug\end2end_test_simple_delayed_request.lib Debug\end2end_test_simple_request.lib Debug\end2end_test_simple_request_with_high_initial_sequence_number.lib Debug\end2end_certs.lib buildtests: buildtests_c buildtests_cxx -buildtests_c: alarm_heap_test.exe alarm_list_test.exe alarm_test.exe alpn_test.exe bin_encoder_test.exe census_hash_table_test.exe census_statistics_multiple_writers_circular_buffer_test.exe census_statistics_multiple_writers_test.exe census_statistics_performance_test.exe census_statistics_quick_test.exe census_statistics_small_log_test.exe census_stub_test.exe census_window_stats_test.exe chttp2_status_conversion_test.exe chttp2_stream_encoder_test.exe chttp2_stream_map_test.exe fling_client.exe fling_server.exe gpr_cancellable_test.exe gpr_cmdline_test.exe gpr_env_test.exe gpr_file_test.exe gpr_histogram_test.exe gpr_host_port_test.exe gpr_log_test.exe gpr_slice_buffer_test.exe gpr_slice_test.exe gpr_string_test.exe gpr_sync_test.exe gpr_thd_test.exe gpr_time_test.exe gpr_tls_test.exe gpr_useful_test.exe grpc_base64_test.exe grpc_byte_buffer_reader_test.exe grpc_channel_stack_test.exe grpc_completion_queue_test.exe grpc_credentials_test.exe grpc_json_token_test.exe grpc_stream_op_test.exe hpack_parser_test.exe hpack_table_test.exe httpcli_format_request_test.exe httpcli_parser_test.exe httpcli_test.exe json_rewrite.exe json_rewrite_test.exe json_test.exe lame_client_test.exe message_compress_test.exe multi_init_test.exe murmur_hash_test.exe no_server_test.exe resolve_address_test.exe secure_endpoint_test.exe sockaddr_utils_test.exe time_averaged_stats_test.exe time_test.exe timeout_encoding_test.exe timers_test.exe transport_metadata_test.exe transport_security_test.exe chttp2_fake_security_bad_hostname_test.exe chttp2_fake_security_cancel_after_accept_test.exe chttp2_fake_security_cancel_after_accept_and_writes_closed_test.exe chttp2_fake_security_cancel_after_invoke_test.exe chttp2_fake_security_cancel_before_invoke_test.exe chttp2_fake_security_cancel_in_a_vacuum_test.exe chttp2_fake_security_census_simple_request_test.exe chttp2_fake_security_disappearing_server_test.exe chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_fake_security_early_server_shutdown_finishes_tags_test.exe chttp2_fake_security_empty_batch_test.exe chttp2_fake_security_graceful_server_shutdown_test.exe chttp2_fake_security_invoke_large_request_test.exe chttp2_fake_security_max_concurrent_streams_test.exe chttp2_fake_security_max_message_length_test.exe chttp2_fake_security_no_op_test.exe chttp2_fake_security_ping_pong_streaming_test.exe chttp2_fake_security_registered_call_test.exe chttp2_fake_security_request_response_with_binary_metadata_and_payload_test.exe chttp2_fake_security_request_response_with_metadata_and_payload_test.exe chttp2_fake_security_request_response_with_payload_test.exe chttp2_fake_security_request_response_with_payload_and_call_creds_test.exe chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test.exe chttp2_fake_security_request_with_large_metadata_test.exe chttp2_fake_security_request_with_payload_test.exe chttp2_fake_security_simple_delayed_request_test.exe chttp2_fake_security_simple_request_test.exe chttp2_fake_security_simple_request_with_high_initial_sequence_number_test.exe chttp2_fullstack_bad_hostname_test.exe chttp2_fullstack_cancel_after_accept_test.exe chttp2_fullstack_cancel_after_accept_and_writes_closed_test.exe chttp2_fullstack_cancel_after_invoke_test.exe chttp2_fullstack_cancel_before_invoke_test.exe chttp2_fullstack_cancel_in_a_vacuum_test.exe chttp2_fullstack_census_simple_request_test.exe chttp2_fullstack_disappearing_server_test.exe chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_fullstack_early_server_shutdown_finishes_tags_test.exe chttp2_fullstack_empty_batch_test.exe chttp2_fullstack_graceful_server_shutdown_test.exe chttp2_fullstack_invoke_large_request_test.exe chttp2_fullstack_max_concurrent_streams_test.exe chttp2_fullstack_max_message_length_test.exe chttp2_fullstack_no_op_test.exe chttp2_fullstack_ping_pong_streaming_test.exe chttp2_fullstack_registered_call_test.exe chttp2_fullstack_request_response_with_binary_metadata_and_payload_test.exe chttp2_fullstack_request_response_with_metadata_and_payload_test.exe chttp2_fullstack_request_response_with_payload_test.exe chttp2_fullstack_request_response_with_payload_and_call_creds_test.exe chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test.exe chttp2_fullstack_request_with_large_metadata_test.exe chttp2_fullstack_request_with_payload_test.exe chttp2_fullstack_simple_delayed_request_test.exe chttp2_fullstack_simple_request_test.exe chttp2_fullstack_simple_request_with_high_initial_sequence_number_test.exe chttp2_simple_ssl_fullstack_bad_hostname_test.exe chttp2_simple_ssl_fullstack_cancel_after_accept_test.exe chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test.exe chttp2_simple_ssl_fullstack_cancel_after_invoke_test.exe chttp2_simple_ssl_fullstack_cancel_before_invoke_test.exe chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test.exe chttp2_simple_ssl_fullstack_census_simple_request_test.exe chttp2_simple_ssl_fullstack_disappearing_server_test.exe chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test.exe chttp2_simple_ssl_fullstack_empty_batch_test.exe chttp2_simple_ssl_fullstack_graceful_server_shutdown_test.exe chttp2_simple_ssl_fullstack_invoke_large_request_test.exe chttp2_simple_ssl_fullstack_max_concurrent_streams_test.exe chttp2_simple_ssl_fullstack_max_message_length_test.exe chttp2_simple_ssl_fullstack_no_op_test.exe chttp2_simple_ssl_fullstack_ping_pong_streaming_test.exe chttp2_simple_ssl_fullstack_registered_call_test.exe chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test.exe chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test.exe chttp2_simple_ssl_fullstack_request_response_with_payload_test.exe chttp2_simple_ssl_fullstack_request_response_with_payload_and_call_creds_test.exe chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test.exe chttp2_simple_ssl_fullstack_request_with_large_metadata_test.exe chttp2_simple_ssl_fullstack_request_with_payload_test.exe chttp2_simple_ssl_fullstack_simple_delayed_request_test.exe chttp2_simple_ssl_fullstack_simple_request_test.exe chttp2_simple_ssl_fullstack_simple_request_with_high_initial_sequence_number_test.exe chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test.exe chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test.exe chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test.exe chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test.exe chttp2_simple_ssl_with_oauth2_fullstack_empty_batch_test.exe chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test.exe chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test.exe chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test.exe chttp2_simple_ssl_with_oauth2_fullstack_max_message_length_test.exe chttp2_simple_ssl_with_oauth2_fullstack_no_op_test.exe chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test.exe chttp2_simple_ssl_with_oauth2_fullstack_registered_call_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_and_call_creds_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test.exe chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test.exe chttp2_simple_ssl_with_oauth2_fullstack_simple_request_with_high_initial_sequence_number_test.exe chttp2_socket_pair_bad_hostname_test.exe chttp2_socket_pair_cancel_after_accept_test.exe chttp2_socket_pair_cancel_after_accept_and_writes_closed_test.exe chttp2_socket_pair_cancel_after_invoke_test.exe chttp2_socket_pair_cancel_before_invoke_test.exe chttp2_socket_pair_cancel_in_a_vacuum_test.exe chttp2_socket_pair_census_simple_request_test.exe chttp2_socket_pair_disappearing_server_test.exe chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_socket_pair_early_server_shutdown_finishes_tags_test.exe chttp2_socket_pair_empty_batch_test.exe chttp2_socket_pair_graceful_server_shutdown_test.exe chttp2_socket_pair_invoke_large_request_test.exe chttp2_socket_pair_max_concurrent_streams_test.exe chttp2_socket_pair_max_message_length_test.exe chttp2_socket_pair_no_op_test.exe chttp2_socket_pair_ping_pong_streaming_test.exe chttp2_socket_pair_registered_call_test.exe chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test.exe chttp2_socket_pair_request_response_with_metadata_and_payload_test.exe chttp2_socket_pair_request_response_with_payload_test.exe chttp2_socket_pair_request_response_with_payload_and_call_creds_test.exe chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test.exe chttp2_socket_pair_request_with_large_metadata_test.exe chttp2_socket_pair_request_with_payload_test.exe chttp2_socket_pair_simple_delayed_request_test.exe chttp2_socket_pair_simple_request_test.exe chttp2_socket_pair_simple_request_with_high_initial_sequence_number_test.exe chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test.exe chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test.exe chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test.exe chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test.exe chttp2_socket_pair_one_byte_at_a_time_empty_batch_test.exe chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test.exe chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test.exe chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test.exe chttp2_socket_pair_one_byte_at_a_time_max_message_length_test.exe chttp2_socket_pair_one_byte_at_a_time_no_op_test.exe chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test.exe chttp2_socket_pair_one_byte_at_a_time_registered_call_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_and_call_creds_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_request_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_test.exe chttp2_fullstack_bad_hostname_unsecure_test.exe chttp2_fullstack_cancel_after_accept_unsecure_test.exe chttp2_fullstack_cancel_after_accept_and_writes_closed_unsecure_test.exe chttp2_fullstack_cancel_after_invoke_unsecure_test.exe chttp2_fullstack_cancel_before_invoke_unsecure_test.exe chttp2_fullstack_cancel_in_a_vacuum_unsecure_test.exe chttp2_fullstack_census_simple_request_unsecure_test.exe chttp2_fullstack_disappearing_server_unsecure_test.exe chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_unsecure_test.exe chttp2_fullstack_early_server_shutdown_finishes_tags_unsecure_test.exe chttp2_fullstack_empty_batch_unsecure_test.exe chttp2_fullstack_graceful_server_shutdown_unsecure_test.exe chttp2_fullstack_invoke_large_request_unsecure_test.exe chttp2_fullstack_max_concurrent_streams_unsecure_test.exe chttp2_fullstack_max_message_length_unsecure_test.exe chttp2_fullstack_no_op_unsecure_test.exe chttp2_fullstack_ping_pong_streaming_unsecure_test.exe chttp2_fullstack_registered_call_unsecure_test.exe chttp2_fullstack_request_response_with_binary_metadata_and_payload_unsecure_test.exe chttp2_fullstack_request_response_with_metadata_and_payload_unsecure_test.exe chttp2_fullstack_request_response_with_payload_unsecure_test.exe chttp2_fullstack_request_response_with_trailing_metadata_and_payload_unsecure_test.exe chttp2_fullstack_request_with_large_metadata_unsecure_test.exe chttp2_fullstack_request_with_payload_unsecure_test.exe chttp2_fullstack_simple_delayed_request_unsecure_test.exe chttp2_fullstack_simple_request_unsecure_test.exe chttp2_fullstack_simple_request_with_high_initial_sequence_number_unsecure_test.exe chttp2_socket_pair_bad_hostname_unsecure_test.exe chttp2_socket_pair_cancel_after_accept_unsecure_test.exe chttp2_socket_pair_cancel_after_accept_and_writes_closed_unsecure_test.exe chttp2_socket_pair_cancel_after_invoke_unsecure_test.exe chttp2_socket_pair_cancel_before_invoke_unsecure_test.exe chttp2_socket_pair_cancel_in_a_vacuum_unsecure_test.exe chttp2_socket_pair_census_simple_request_unsecure_test.exe chttp2_socket_pair_disappearing_server_unsecure_test.exe chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_unsecure_test.exe chttp2_socket_pair_early_server_shutdown_finishes_tags_unsecure_test.exe chttp2_socket_pair_empty_batch_unsecure_test.exe chttp2_socket_pair_graceful_server_shutdown_unsecure_test.exe chttp2_socket_pair_invoke_large_request_unsecure_test.exe chttp2_socket_pair_max_concurrent_streams_unsecure_test.exe chttp2_socket_pair_max_message_length_unsecure_test.exe chttp2_socket_pair_no_op_unsecure_test.exe chttp2_socket_pair_ping_pong_streaming_unsecure_test.exe chttp2_socket_pair_registered_call_unsecure_test.exe chttp2_socket_pair_request_response_with_binary_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_request_response_with_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_request_response_with_payload_unsecure_test.exe chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_request_with_large_metadata_unsecure_test.exe chttp2_socket_pair_request_with_payload_unsecure_test.exe chttp2_socket_pair_simple_delayed_request_unsecure_test.exe chttp2_socket_pair_simple_request_unsecure_test.exe chttp2_socket_pair_simple_request_with_high_initial_sequence_number_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_bad_hostname_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_census_simple_request_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_disappearing_server_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_empty_batch_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_max_message_length_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_no_op_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_registered_call_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_request_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_unsecure_test.exe +buildtests_c: alarm_heap_test.exe alarm_list_test.exe alarm_test.exe alpn_test.exe bin_encoder_test.exe chttp2_status_conversion_test.exe chttp2_stream_encoder_test.exe chttp2_stream_map_test.exe fling_client.exe fling_server.exe gpr_cancellable_test.exe gpr_cmdline_test.exe gpr_env_test.exe gpr_file_test.exe gpr_histogram_test.exe gpr_host_port_test.exe gpr_log_test.exe gpr_slice_buffer_test.exe gpr_slice_test.exe gpr_string_test.exe gpr_sync_test.exe gpr_thd_test.exe gpr_time_test.exe gpr_tls_test.exe gpr_useful_test.exe grpc_base64_test.exe grpc_byte_buffer_reader_test.exe grpc_channel_stack_test.exe grpc_completion_queue_test.exe grpc_credentials_test.exe grpc_json_token_test.exe grpc_stream_op_test.exe hpack_parser_test.exe hpack_table_test.exe httpcli_format_request_test.exe httpcli_parser_test.exe httpcli_test.exe json_rewrite.exe json_rewrite_test.exe json_test.exe lame_client_test.exe message_compress_test.exe multi_init_test.exe murmur_hash_test.exe no_server_test.exe resolve_address_test.exe secure_endpoint_test.exe sockaddr_utils_test.exe time_averaged_stats_test.exe time_test.exe timeout_encoding_test.exe timers_test.exe transport_metadata_test.exe transport_security_test.exe chttp2_fake_security_bad_hostname_test.exe chttp2_fake_security_cancel_after_accept_test.exe chttp2_fake_security_cancel_after_accept_and_writes_closed_test.exe chttp2_fake_security_cancel_after_invoke_test.exe chttp2_fake_security_cancel_before_invoke_test.exe chttp2_fake_security_cancel_in_a_vacuum_test.exe chttp2_fake_security_census_simple_request_test.exe chttp2_fake_security_disappearing_server_test.exe chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_fake_security_early_server_shutdown_finishes_tags_test.exe chttp2_fake_security_empty_batch_test.exe chttp2_fake_security_graceful_server_shutdown_test.exe chttp2_fake_security_invoke_large_request_test.exe chttp2_fake_security_max_concurrent_streams_test.exe chttp2_fake_security_max_message_length_test.exe chttp2_fake_security_no_op_test.exe chttp2_fake_security_ping_pong_streaming_test.exe chttp2_fake_security_registered_call_test.exe chttp2_fake_security_request_response_with_binary_metadata_and_payload_test.exe chttp2_fake_security_request_response_with_metadata_and_payload_test.exe chttp2_fake_security_request_response_with_payload_test.exe chttp2_fake_security_request_response_with_payload_and_call_creds_test.exe chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test.exe chttp2_fake_security_request_with_large_metadata_test.exe chttp2_fake_security_request_with_payload_test.exe chttp2_fake_security_simple_delayed_request_test.exe chttp2_fake_security_simple_request_test.exe chttp2_fake_security_simple_request_with_high_initial_sequence_number_test.exe chttp2_fullstack_bad_hostname_test.exe chttp2_fullstack_cancel_after_accept_test.exe chttp2_fullstack_cancel_after_accept_and_writes_closed_test.exe chttp2_fullstack_cancel_after_invoke_test.exe chttp2_fullstack_cancel_before_invoke_test.exe chttp2_fullstack_cancel_in_a_vacuum_test.exe chttp2_fullstack_census_simple_request_test.exe chttp2_fullstack_disappearing_server_test.exe chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_fullstack_early_server_shutdown_finishes_tags_test.exe chttp2_fullstack_empty_batch_test.exe chttp2_fullstack_graceful_server_shutdown_test.exe chttp2_fullstack_invoke_large_request_test.exe chttp2_fullstack_max_concurrent_streams_test.exe chttp2_fullstack_max_message_length_test.exe chttp2_fullstack_no_op_test.exe chttp2_fullstack_ping_pong_streaming_test.exe chttp2_fullstack_registered_call_test.exe chttp2_fullstack_request_response_with_binary_metadata_and_payload_test.exe chttp2_fullstack_request_response_with_metadata_and_payload_test.exe chttp2_fullstack_request_response_with_payload_test.exe chttp2_fullstack_request_response_with_payload_and_call_creds_test.exe chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test.exe chttp2_fullstack_request_with_large_metadata_test.exe chttp2_fullstack_request_with_payload_test.exe chttp2_fullstack_simple_delayed_request_test.exe chttp2_fullstack_simple_request_test.exe chttp2_fullstack_simple_request_with_high_initial_sequence_number_test.exe chttp2_simple_ssl_fullstack_bad_hostname_test.exe chttp2_simple_ssl_fullstack_cancel_after_accept_test.exe chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test.exe chttp2_simple_ssl_fullstack_cancel_after_invoke_test.exe chttp2_simple_ssl_fullstack_cancel_before_invoke_test.exe chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test.exe chttp2_simple_ssl_fullstack_census_simple_request_test.exe chttp2_simple_ssl_fullstack_disappearing_server_test.exe chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test.exe chttp2_simple_ssl_fullstack_empty_batch_test.exe chttp2_simple_ssl_fullstack_graceful_server_shutdown_test.exe chttp2_simple_ssl_fullstack_invoke_large_request_test.exe chttp2_simple_ssl_fullstack_max_concurrent_streams_test.exe chttp2_simple_ssl_fullstack_max_message_length_test.exe chttp2_simple_ssl_fullstack_no_op_test.exe chttp2_simple_ssl_fullstack_ping_pong_streaming_test.exe chttp2_simple_ssl_fullstack_registered_call_test.exe chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test.exe chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test.exe chttp2_simple_ssl_fullstack_request_response_with_payload_test.exe chttp2_simple_ssl_fullstack_request_response_with_payload_and_call_creds_test.exe chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test.exe chttp2_simple_ssl_fullstack_request_with_large_metadata_test.exe chttp2_simple_ssl_fullstack_request_with_payload_test.exe chttp2_simple_ssl_fullstack_simple_delayed_request_test.exe chttp2_simple_ssl_fullstack_simple_request_test.exe chttp2_simple_ssl_fullstack_simple_request_with_high_initial_sequence_number_test.exe chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test.exe chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test.exe chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test.exe chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test.exe chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test.exe chttp2_simple_ssl_with_oauth2_fullstack_empty_batch_test.exe chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test.exe chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test.exe chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test.exe chttp2_simple_ssl_with_oauth2_fullstack_max_message_length_test.exe chttp2_simple_ssl_with_oauth2_fullstack_no_op_test.exe chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test.exe chttp2_simple_ssl_with_oauth2_fullstack_registered_call_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_and_call_creds_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_test.exe chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_test.exe chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test.exe chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test.exe chttp2_simple_ssl_with_oauth2_fullstack_simple_request_with_high_initial_sequence_number_test.exe chttp2_socket_pair_bad_hostname_test.exe chttp2_socket_pair_cancel_after_accept_test.exe chttp2_socket_pair_cancel_after_accept_and_writes_closed_test.exe chttp2_socket_pair_cancel_after_invoke_test.exe chttp2_socket_pair_cancel_before_invoke_test.exe chttp2_socket_pair_cancel_in_a_vacuum_test.exe chttp2_socket_pair_census_simple_request_test.exe chttp2_socket_pair_disappearing_server_test.exe chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_socket_pair_early_server_shutdown_finishes_tags_test.exe chttp2_socket_pair_empty_batch_test.exe chttp2_socket_pair_graceful_server_shutdown_test.exe chttp2_socket_pair_invoke_large_request_test.exe chttp2_socket_pair_max_concurrent_streams_test.exe chttp2_socket_pair_max_message_length_test.exe chttp2_socket_pair_no_op_test.exe chttp2_socket_pair_ping_pong_streaming_test.exe chttp2_socket_pair_registered_call_test.exe chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test.exe chttp2_socket_pair_request_response_with_metadata_and_payload_test.exe chttp2_socket_pair_request_response_with_payload_test.exe chttp2_socket_pair_request_response_with_payload_and_call_creds_test.exe chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test.exe chttp2_socket_pair_request_with_large_metadata_test.exe chttp2_socket_pair_request_with_payload_test.exe chttp2_socket_pair_simple_delayed_request_test.exe chttp2_socket_pair_simple_request_test.exe chttp2_socket_pair_simple_request_with_high_initial_sequence_number_test.exe chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test.exe chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test.exe chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test.exe chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test.exe chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test.exe chttp2_socket_pair_one_byte_at_a_time_empty_batch_test.exe chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test.exe chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test.exe chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test.exe chttp2_socket_pair_one_byte_at_a_time_max_message_length_test.exe chttp2_socket_pair_one_byte_at_a_time_no_op_test.exe chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test.exe chttp2_socket_pair_one_byte_at_a_time_registered_call_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_and_call_creds_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_payload_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_request_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_test.exe chttp2_fullstack_bad_hostname_unsecure_test.exe chttp2_fullstack_cancel_after_accept_unsecure_test.exe chttp2_fullstack_cancel_after_accept_and_writes_closed_unsecure_test.exe chttp2_fullstack_cancel_after_invoke_unsecure_test.exe chttp2_fullstack_cancel_before_invoke_unsecure_test.exe chttp2_fullstack_cancel_in_a_vacuum_unsecure_test.exe chttp2_fullstack_census_simple_request_unsecure_test.exe chttp2_fullstack_disappearing_server_unsecure_test.exe chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_unsecure_test.exe chttp2_fullstack_early_server_shutdown_finishes_tags_unsecure_test.exe chttp2_fullstack_empty_batch_unsecure_test.exe chttp2_fullstack_graceful_server_shutdown_unsecure_test.exe chttp2_fullstack_invoke_large_request_unsecure_test.exe chttp2_fullstack_max_concurrent_streams_unsecure_test.exe chttp2_fullstack_max_message_length_unsecure_test.exe chttp2_fullstack_no_op_unsecure_test.exe chttp2_fullstack_ping_pong_streaming_unsecure_test.exe chttp2_fullstack_registered_call_unsecure_test.exe chttp2_fullstack_request_response_with_binary_metadata_and_payload_unsecure_test.exe chttp2_fullstack_request_response_with_metadata_and_payload_unsecure_test.exe chttp2_fullstack_request_response_with_payload_unsecure_test.exe chttp2_fullstack_request_response_with_trailing_metadata_and_payload_unsecure_test.exe chttp2_fullstack_request_with_large_metadata_unsecure_test.exe chttp2_fullstack_request_with_payload_unsecure_test.exe chttp2_fullstack_simple_delayed_request_unsecure_test.exe chttp2_fullstack_simple_request_unsecure_test.exe chttp2_fullstack_simple_request_with_high_initial_sequence_number_unsecure_test.exe chttp2_socket_pair_bad_hostname_unsecure_test.exe chttp2_socket_pair_cancel_after_accept_unsecure_test.exe chttp2_socket_pair_cancel_after_accept_and_writes_closed_unsecure_test.exe chttp2_socket_pair_cancel_after_invoke_unsecure_test.exe chttp2_socket_pair_cancel_before_invoke_unsecure_test.exe chttp2_socket_pair_cancel_in_a_vacuum_unsecure_test.exe chttp2_socket_pair_census_simple_request_unsecure_test.exe chttp2_socket_pair_disappearing_server_unsecure_test.exe chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_unsecure_test.exe chttp2_socket_pair_early_server_shutdown_finishes_tags_unsecure_test.exe chttp2_socket_pair_empty_batch_unsecure_test.exe chttp2_socket_pair_graceful_server_shutdown_unsecure_test.exe chttp2_socket_pair_invoke_large_request_unsecure_test.exe chttp2_socket_pair_max_concurrent_streams_unsecure_test.exe chttp2_socket_pair_max_message_length_unsecure_test.exe chttp2_socket_pair_no_op_unsecure_test.exe chttp2_socket_pair_ping_pong_streaming_unsecure_test.exe chttp2_socket_pair_registered_call_unsecure_test.exe chttp2_socket_pair_request_response_with_binary_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_request_response_with_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_request_response_with_payload_unsecure_test.exe chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_request_with_large_metadata_unsecure_test.exe chttp2_socket_pair_request_with_payload_unsecure_test.exe chttp2_socket_pair_simple_delayed_request_unsecure_test.exe chttp2_socket_pair_simple_request_unsecure_test.exe chttp2_socket_pair_simple_request_with_high_initial_sequence_number_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_bad_hostname_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_census_simple_request_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_disappearing_server_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_empty_batch_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_max_message_length_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_no_op_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_registered_call_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_request_with_payload_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_request_unsecure_test.exe chttp2_socket_pair_one_byte_at_a_time_simple_request_with_high_initial_sequence_number_unsecure_test.exe echo All tests built. buildtests_cxx: interop_client.exe interop_server.exe @@ -98,62 +98,6 @@ bin_encoder_test.exe: build_libs $(OUT_DIR) bin_encoder_test: bin_encoder_test.exe echo Running bin_encoder_test $(OUT_DIR)\bin_encoder_test.exe -census_hash_table_test.exe: build_libs $(OUT_DIR) - echo Building census_hash_table_test - $(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\test\core\statistics\hash_table_test.c - $(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\census_hash_table_test.exe" Debug\grpc_test_util.lib Debug\grpc.lib Debug\gpr_test_util.lib Debug\gpr.lib $(LIBS) $(OUT_DIR)\hash_table_test.obj -census_hash_table_test: census_hash_table_test.exe - echo Running census_hash_table_test - $(OUT_DIR)\census_hash_table_test.exe -census_statistics_multiple_writers_circular_buffer_test.exe: build_libs $(OUT_DIR) - echo Building census_statistics_multiple_writers_circular_buffer_test - $(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\test\core\statistics\multiple_writers_circular_buffer_test.c - $(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\census_statistics_multiple_writers_circular_buffer_test.exe" Debug\grpc_test_util.lib Debug\grpc.lib Debug\gpr_test_util.lib Debug\gpr.lib $(LIBS) $(OUT_DIR)\multiple_writers_circular_buffer_test.obj -census_statistics_multiple_writers_circular_buffer_test: census_statistics_multiple_writers_circular_buffer_test.exe - echo Running census_statistics_multiple_writers_circular_buffer_test - $(OUT_DIR)\census_statistics_multiple_writers_circular_buffer_test.exe -census_statistics_multiple_writers_test.exe: build_libs $(OUT_DIR) - echo Building census_statistics_multiple_writers_test - $(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\test\core\statistics\multiple_writers_test.c - $(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\census_statistics_multiple_writers_test.exe" Debug\grpc_test_util.lib Debug\grpc.lib Debug\gpr_test_util.lib Debug\gpr.lib $(LIBS) $(OUT_DIR)\multiple_writers_test.obj -census_statistics_multiple_writers_test: census_statistics_multiple_writers_test.exe - echo Running census_statistics_multiple_writers_test - $(OUT_DIR)\census_statistics_multiple_writers_test.exe -census_statistics_performance_test.exe: build_libs $(OUT_DIR) - echo Building census_statistics_performance_test - $(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\test\core\statistics\performance_test.c - $(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\census_statistics_performance_test.exe" Debug\grpc_test_util.lib Debug\grpc.lib Debug\gpr_test_util.lib Debug\gpr.lib $(LIBS) $(OUT_DIR)\performance_test.obj -census_statistics_performance_test: census_statistics_performance_test.exe - echo Running census_statistics_performance_test - $(OUT_DIR)\census_statistics_performance_test.exe -census_statistics_quick_test.exe: build_libs $(OUT_DIR) - echo Building census_statistics_quick_test - $(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\test\core\statistics\quick_test.c - $(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\census_statistics_quick_test.exe" Debug\grpc_test_util.lib Debug\grpc.lib Debug\gpr_test_util.lib Debug\gpr.lib $(LIBS) $(OUT_DIR)\quick_test.obj -census_statistics_quick_test: census_statistics_quick_test.exe - echo Running census_statistics_quick_test - $(OUT_DIR)\census_statistics_quick_test.exe -census_statistics_small_log_test.exe: build_libs $(OUT_DIR) - echo Building census_statistics_small_log_test - $(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\test\core\statistics\small_log_test.c - $(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\census_statistics_small_log_test.exe" Debug\grpc_test_util.lib Debug\grpc.lib Debug\gpr_test_util.lib Debug\gpr.lib $(LIBS) $(OUT_DIR)\small_log_test.obj -census_statistics_small_log_test: census_statistics_small_log_test.exe - echo Running census_statistics_small_log_test - $(OUT_DIR)\census_statistics_small_log_test.exe -census_stub_test.exe: build_libs $(OUT_DIR) - echo Building census_stub_test - $(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\test\core\statistics\census_stub_test.c - $(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\census_stub_test.exe" Debug\grpc_test_util.lib Debug\grpc.lib Debug\gpr_test_util.lib Debug\gpr.lib $(LIBS) $(OUT_DIR)\census_stub_test.obj -census_stub_test: census_stub_test.exe - echo Running census_stub_test - $(OUT_DIR)\census_stub_test.exe -census_window_stats_test.exe: build_libs $(OUT_DIR) - echo Building census_window_stats_test - $(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\test\core\statistics\window_stats_test.c - $(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\census_window_stats_test.exe" Debug\grpc_test_util.lib Debug\grpc.lib Debug\gpr_test_util.lib Debug\gpr.lib $(LIBS) $(OUT_DIR)\window_stats_test.obj -census_window_stats_test: census_window_stats_test.exe - echo Running census_window_stats_test - $(OUT_DIR)\census_window_stats_test.exe chttp2_status_conversion_test.exe: build_libs $(OUT_DIR) echo Building chttp2_status_conversion_test $(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\test\core\transport\chttp2\status_conversion_test.c diff --git a/vsprojects/grpc/grpc.vcxproj b/vsprojects/grpc/grpc.vcxproj index 1c965388bba..3684047783d 100644 --- a/vsprojects/grpc/grpc.vcxproj +++ b/vsprojects/grpc/grpc.vcxproj @@ -152,6 +152,7 @@ + @@ -170,7 +171,7 @@ - + @@ -219,12 +220,6 @@ - - - - - - @@ -257,6 +252,7 @@ + @@ -301,7 +297,7 @@ - + @@ -405,18 +401,6 @@ - - - - - - - - - - - - @@ -495,6 +479,10 @@ + + + + diff --git a/vsprojects/grpc/grpc.vcxproj.filters b/vsprojects/grpc/grpc.vcxproj.filters index ff6afb2ecaa..e31df4b87df 100644 --- a/vsprojects/grpc/grpc.vcxproj.filters +++ b/vsprojects/grpc/grpc.vcxproj.filters @@ -64,8 +64,8 @@ src\core\tsi - - src\core\channel + + src\core\census src\core\channel @@ -220,24 +220,6 @@ src\core\profiling - - src\core\statistics - - - src\core\statistics - - - src\core\statistics - - - src\core\statistics - - - src\core\statistics - - - src\core\statistics - src\core\surface @@ -355,6 +337,12 @@ src\core\transport + + src\core\census + + + src\core\census + @@ -372,6 +360,9 @@ include\grpc + + include\grpc + @@ -422,8 +413,8 @@ src\core\tsi - - src\core\channel + + src\core\census src\core\channel @@ -569,24 +560,6 @@ src\core\profiling - - src\core\statistics - - - src\core\statistics - - - src\core\statistics - - - src\core\statistics - - - src\core\statistics - - - src\core\statistics - src\core\surface @@ -683,6 +656,9 @@ src\core\transport + + src\core\census + @@ -698,6 +674,9 @@ {ea745680-21ea-9c5e-679b-64dc40562d08} + + {fb3aefc2-8205-b0bf-525f-ab5e339f7f76} + {d897b6c3-c555-234e-a589-b4f008063615} @@ -722,9 +701,6 @@ {1d850ac6-e639-4eab-5338-4ba40272fcc9} - - {0ef49896-2313-4a3f-1ce2-716fa0e5c6ca} - {aeb18e82-5d25-0aad-8b02-a0a3470073ce} diff --git a/vsprojects/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/grpc_test_util/grpc_test_util.vcxproj index 4198703d770..e5288f4d447 100644 --- a/vsprojects/grpc_test_util/grpc_test_util.vcxproj +++ b/vsprojects/grpc_test_util/grpc_test_util.vcxproj @@ -156,8 +156,6 @@ - - diff --git a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj index 3dfda32eaa1..06ae7318f25 100644 --- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj @@ -150,9 +150,10 @@ + - + @@ -201,12 +202,6 @@ - - - - - - @@ -239,11 +234,12 @@ + - + @@ -347,18 +343,6 @@ - - - - - - - - - - - - @@ -437,6 +421,10 @@ + + + + diff --git a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters index 4c9c86eecd3..1603757a6ea 100644 --- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -4,8 +4,8 @@ src\core\surface - - src\core\channel + + src\core\census src\core\channel @@ -160,24 +160,6 @@ src\core\profiling - - src\core\statistics - - - src\core\statistics - - - src\core\statistics - - - src\core\statistics - - - src\core\statistics - - - src\core\statistics - src\core\surface @@ -295,6 +277,12 @@ src\core\transport + + src\core\census + + + src\core\census + @@ -309,10 +297,13 @@ include\grpc + + include\grpc + - - src\core\channel + + src\core\census src\core\channel @@ -458,24 +449,6 @@ src\core\profiling - - src\core\statistics - - - src\core\statistics - - - src\core\statistics - - - src\core\statistics - - - src\core\statistics - - - src\core\statistics - src\core\surface @@ -572,6 +545,9 @@ src\core\transport + + src\core\census + @@ -587,6 +563,9 @@ {88491077-386b-2039-d14c-0c40136b5f7a} + + {a7596ee2-afee-3a82-7e6e-bd8b8f904e04} + {cc102c4b-66ff-cf4c-2288-d76327e1a183} @@ -605,9 +584,6 @@ {7f91d9bf-c9de-835a-d74d-b16f843b89a9} - - {e084164c-a069-00e3-db35-4e0b1cd6f0b7} - {6cd0127e-c24b-d43c-38f5-198db8d4322a} From a2918d2e04e8df462225ea846fd3487e5d0f6a15 Mon Sep 17 00:00:00 2001 From: Masood Malekghassemi Date: Wed, 6 May 2015 12:41:43 -0700 Subject: [PATCH 05/52] Move batch API exposure to Python layer Exposes the C core batch API to the Python layers. Provides a shim to enable the old Python API to remain the same (for now). --- src/python/src/grpc/_adapter/_c.c | 86 --- .../grpc/_adapter/{_server.h => _c/module.c} | 30 +- .../{_completion_queue.h => _c/types.c} | 35 +- src/python/src/grpc/_adapter/_c/types.h | 271 ++++++++ src/python/src/grpc/_adapter/_c/types/call.c | 163 +++++ .../src/grpc/_adapter/_c/types/channel.c | 134 ++++ .../_adapter/_c/types/client_credentials.c | 286 ++++++++ .../grpc/_adapter/_c/types/completion_queue.c | 124 ++++ .../src/grpc/_adapter/_c/types/server.c | 183 +++++ .../_adapter/_c/types/server_credentials.c | 146 ++++ src/python/src/grpc/_adapter/_c/utility.c | 460 ++++++++++++ src/python/src/grpc/_adapter/_c_test.py | 188 +---- src/python/src/grpc/_adapter/_call.c | 438 ------------ src/python/src/grpc/_adapter/_call.h | 77 --- src/python/src/grpc/_adapter/_channel.c | 135 ---- src/python/src/grpc/_adapter/_channel.h | 49 -- .../src/grpc/_adapter/_client_credentials.c | 121 ---- .../src/grpc/_adapter/_client_credentials.h | 49 -- .../src/grpc/_adapter/_completion_queue.c | 653 ------------------ src/python/src/grpc/_adapter/_datatypes.py | 86 --- src/python/src/grpc/_adapter/_error.c | 79 --- src/python/src/grpc/_adapter/_error.h | 42 -- .../src/grpc/_adapter/_intermediary_low.py | 258 +++++++ .../grpc/_adapter/_intermediary_low_test.py | 421 +++++++++++ src/python/src/grpc/_adapter/_low.py | 104 ++- src/python/src/grpc/_adapter/_low_test.py | 485 ++++--------- src/python/src/grpc/_adapter/_server.c | 202 ------ .../src/grpc/_adapter/_server_credentials.c | 152 ---- .../src/grpc/_adapter/_server_credentials.h | 49 -- src/python/src/grpc/_adapter/_tag.c | 65 -- src/python/src/grpc/_adapter/_tag.h | 70 -- src/python/src/grpc/_adapter/_types.py | 368 ++++++++++ src/python/src/grpc/_adapter/fore.py | 4 +- src/python/src/grpc/_adapter/rear.py | 4 +- src/python/src/setup.py | 18 +- tools/run_tests/python_tests.json | 19 +- 36 files changed, 3097 insertions(+), 2957 deletions(-) delete mode 100644 src/python/src/grpc/_adapter/_c.c rename src/python/src/grpc/_adapter/{_server.h => _c/module.c} (73%) rename src/python/src/grpc/_adapter/{_completion_queue.h => _c/types.c} (71%) create mode 100644 src/python/src/grpc/_adapter/_c/types.h create mode 100644 src/python/src/grpc/_adapter/_c/types/call.c create mode 100644 src/python/src/grpc/_adapter/_c/types/channel.c create mode 100644 src/python/src/grpc/_adapter/_c/types/client_credentials.c create mode 100644 src/python/src/grpc/_adapter/_c/types/completion_queue.c create mode 100644 src/python/src/grpc/_adapter/_c/types/server.c create mode 100644 src/python/src/grpc/_adapter/_c/types/server_credentials.c create mode 100644 src/python/src/grpc/_adapter/_c/utility.c delete mode 100644 src/python/src/grpc/_adapter/_call.c delete mode 100644 src/python/src/grpc/_adapter/_call.h delete mode 100644 src/python/src/grpc/_adapter/_channel.c delete mode 100644 src/python/src/grpc/_adapter/_channel.h delete mode 100644 src/python/src/grpc/_adapter/_client_credentials.c delete mode 100644 src/python/src/grpc/_adapter/_client_credentials.h delete mode 100644 src/python/src/grpc/_adapter/_completion_queue.c delete mode 100644 src/python/src/grpc/_adapter/_datatypes.py delete mode 100644 src/python/src/grpc/_adapter/_error.c delete mode 100644 src/python/src/grpc/_adapter/_error.h create mode 100644 src/python/src/grpc/_adapter/_intermediary_low.py create mode 100644 src/python/src/grpc/_adapter/_intermediary_low_test.py delete mode 100644 src/python/src/grpc/_adapter/_server.c delete mode 100644 src/python/src/grpc/_adapter/_server_credentials.c delete mode 100644 src/python/src/grpc/_adapter/_server_credentials.h delete mode 100644 src/python/src/grpc/_adapter/_tag.c delete mode 100644 src/python/src/grpc/_adapter/_tag.h create mode 100644 src/python/src/grpc/_adapter/_types.py diff --git a/src/python/src/grpc/_adapter/_c.c b/src/python/src/grpc/_adapter/_c.c deleted file mode 100644 index f096a55b618..00000000000 --- a/src/python/src/grpc/_adapter/_c.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include -#include - -#include "grpc/_adapter/_completion_queue.h" -#include "grpc/_adapter/_channel.h" -#include "grpc/_adapter/_call.h" -#include "grpc/_adapter/_server.h" -#include "grpc/_adapter/_client_credentials.h" -#include "grpc/_adapter/_server_credentials.h" - -static PyObject *init(PyObject *self) { - grpc_init(); - Py_RETURN_NONE; -} - -static PyObject *shutdown(PyObject *self) { - grpc_shutdown(); - Py_RETURN_NONE; -} - -static PyMethodDef _c_methods[] = { - {"init", (PyCFunction)init, METH_NOARGS, - "Initialize the module's static state."}, - {"shut_down", (PyCFunction)shutdown, METH_NOARGS, - "Shut down the module's static state."}, - {NULL}, -}; - -PyMODINIT_FUNC init_c(void) { - PyObject *module; - - module = Py_InitModule3("_c", _c_methods, - "Wrappings of C structures and functions."); - - if (pygrpc_add_completion_queue(module) == -1) { - return; - } - if (pygrpc_add_channel(module) == -1) { - return; - } - if (pygrpc_add_call(module) == -1) { - return; - } - if (pygrpc_add_server(module) == -1) { - return; - } - if (pygrpc_add_client_credentials(module) == -1) { - return; - } - if (pygrpc_add_server_credentials(module) == -1) { - return; - } -} diff --git a/src/python/src/grpc/_adapter/_server.h b/src/python/src/grpc/_adapter/_c/module.c similarity index 73% rename from src/python/src/grpc/_adapter/_server.h rename to src/python/src/grpc/_adapter/_c/module.c index d31d4e678b0..1f3aedd9d85 100644 --- a/src/python/src/grpc/_adapter/_server.h +++ b/src/python/src/grpc/_adapter/_c/module.c @@ -31,21 +31,31 @@ * */ -#ifndef _ADAPTER__SERVER_H_ -#define _ADAPTER__SERVER_H_ +#include +#define PY_SSIZE_T_CLEAN #include #include -#include "grpc/_adapter/_completion_queue.h" +#include "grpc/_adapter/_c/types.h" -typedef struct { - PyObject_HEAD +static PyMethodDef c_methods[] = { + {NULL} +}; - CompletionQueue *completion_queue; - grpc_server *c_server; -} Server; +PyMODINIT_FUNC init_c(void) { + PyObject *module; -int pygrpc_add_server(PyObject *module); + module = Py_InitModule3("_c", c_methods, + "Wrappings of C structures and functions."); -#endif /* _ADAPTER__SERVER_H_ */ + if (pygrpc_module_add_types(module) < 0) { + return; + } + + /* GRPC maintains an internal counter of how many times it has been + initialized and handles multiple pairs of grpc_init()/grpc_shutdown() + invocations accordingly. */ + grpc_init(); + atexit(&grpc_shutdown); +} diff --git a/src/python/src/grpc/_adapter/_completion_queue.h b/src/python/src/grpc/_adapter/_c/types.c similarity index 71% rename from src/python/src/grpc/_adapter/_completion_queue.h rename to src/python/src/grpc/_adapter/_c/types.c index 516694daa19..8855c32ca6d 100644 --- a/src/python/src/grpc/_adapter/_completion_queue.h +++ b/src/python/src/grpc/_adapter/_c/types.c @@ -31,19 +31,30 @@ * */ -#ifndef _ADAPTER__COMPLETION_QUEUE_H_ -#define _ADAPTER__COMPLETION_QUEUE_H_ +#include "grpc/_adapter/_c/types.h" +#define PY_SSIZE_T_CLEAN #include #include -typedef struct { - PyObject_HEAD - grpc_completion_queue *c_completion_queue; -} CompletionQueue; - -extern PyTypeObject pygrpc_CompletionQueueType; - -int pygrpc_add_completion_queue(PyObject *module); - -#endif /* _ADAPTER__COMPLETION_QUEUE_H_ */ +int pygrpc_module_add_types(PyObject *module) { + int i; + PyTypeObject *types[] = { + &pygrpc_ClientCredentials_type, + &pygrpc_ServerCredentials_type, + &pygrpc_CompletionQueue_type, + &pygrpc_Call_type, + &pygrpc_Channel_type, + &pygrpc_Server_type + }; + for (i = 0; i < sizeof(types)/sizeof(PyTypeObject *); ++i) { + if (PyType_Ready(types[i]) < 0) { + return -1; + } + } + for (i = 0; i < sizeof(types)/sizeof(PyTypeObject *); ++i) { + Py_INCREF(types[i]); + PyModule_AddObject(module, types[i]->tp_name, (PyObject *)types[i]); + } + return 0; +} diff --git a/src/python/src/grpc/_adapter/_c/types.h b/src/python/src/grpc/_adapter/_c/types.h new file mode 100644 index 00000000000..e189ae25660 --- /dev/null +++ b/src/python/src/grpc/_adapter/_c/types.h @@ -0,0 +1,271 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC__ADAPTER__C_TYPES_H_ +#define GRPC__ADAPTER__C_TYPES_H_ + +#define PY_SSIZE_T_CLEAN +#include +#include +#include + + +/*=========================*/ +/* Client-side credentials */ +/*=========================*/ + +typedef struct ClientCredentials { + PyObject_HEAD + grpc_credentials *c_creds; +} ClientCredentials; +void pygrpc_ClientCredentials_dealloc(ClientCredentials *self); +ClientCredentials *pygrpc_ClientCredentials_google_default( + PyTypeObject *type, PyObject *ignored); +ClientCredentials *pygrpc_ClientCredentials_ssl( + PyTypeObject *type, PyObject *args, PyObject *kwargs); +ClientCredentials *pygrpc_ClientCredentials_composite( + PyTypeObject *type, PyObject *args, PyObject *kwargs); +ClientCredentials *pygrpc_ClientCredentials_compute_engine( + PyTypeObject *type, PyObject *ignored); +ClientCredentials *pygrpc_ClientCredentials_service_account( + PyTypeObject *type, PyObject *args, PyObject *kwargs); +ClientCredentials *pygrpc_ClientCredentials_jwt( + PyTypeObject *type, PyObject *args, PyObject *kwargs); +ClientCredentials *pygrpc_ClientCredentials_refresh_token( + PyTypeObject *type, PyObject *args, PyObject *kwargs); +ClientCredentials *pygrpc_ClientCredentials_fake_transport_security( + PyTypeObject *type, PyObject *ignored); +ClientCredentials *pygrpc_ClientCredentials_iam( + PyTypeObject *type, PyObject *args, PyObject *kwargs); +extern PyTypeObject pygrpc_ClientCredentials_type; + + +/*=========================*/ +/* Server-side credentials */ +/*=========================*/ + +typedef struct ServerCredentials { + PyObject_HEAD + grpc_server_credentials *c_creds; +} ServerCredentials; +void pygrpc_ServerCredentials_dealloc(ServerCredentials *self); +ServerCredentials *pygrpc_ServerCredentials_ssl( + PyTypeObject *type, PyObject *args, PyObject *kwargs); +ServerCredentials *pygrpc_ServerCredentials_fake_transport_security( + PyTypeObject *type, PyObject *ignored); +extern PyTypeObject pygrpc_ServerCredentials_type; + + +/*==================*/ +/* Completion queue */ +/*==================*/ + +typedef struct CompletionQueue { + PyObject_HEAD + grpc_completion_queue *c_cq; +} CompletionQueue; +CompletionQueue *pygrpc_CompletionQueue_new( + PyTypeObject *type, PyObject *args, PyObject *kwargs); +void pygrpc_CompletionQueue_dealloc(CompletionQueue *self); +PyObject *pygrpc_CompletionQueue_next( + CompletionQueue *self, PyObject *args, PyObject *kwargs); +PyObject *pygrpc_CompletionQueue_shutdown( + CompletionQueue *self, PyObject *ignored); +extern PyTypeObject pygrpc_CompletionQueue_type; + + +/*======*/ +/* Call */ +/*======*/ + +typedef struct Call { + PyObject_HEAD + grpc_call *c_call; + CompletionQueue *cq; +} Call; +Call *pygrpc_Call_new_empty(CompletionQueue *cq); +void pygrpc_Call_dealloc(Call *self); +PyObject *pygrpc_Call_start_batch(Call *self, PyObject *args, PyObject *kwargs); +PyObject *pygrpc_Call_cancel(Call *self, PyObject *args, PyObject *kwargs); +extern PyTypeObject pygrpc_Call_type; + + +/*=========*/ +/* Channel */ +/*=========*/ + +typedef struct Channel { + PyObject_HEAD + grpc_channel *c_chan; +} Channel; +Channel *pygrpc_Channel_new( + PyTypeObject *type, PyObject *args, PyObject *kwargs); +void pygrpc_Channel_dealloc(Channel *self); +Call *pygrpc_Channel_create_call( + Channel *self, PyObject *args, PyObject *kwargs); +extern PyTypeObject pygrpc_Channel_type; + + +/*========*/ +/* Server */ +/*========*/ + +typedef struct Server { + PyObject_HEAD + grpc_server *c_serv; + CompletionQueue *cq; +} Server; +Server *pygrpc_Server_new(PyTypeObject *type, PyObject *args, PyObject *kwargs); +void pygrpc_Server_dealloc(Server *self); +PyObject *pygrpc_Server_request_call( + Server *self, PyObject *args, PyObject *kwargs); +PyObject *pygrpc_Server_add_http2_port( + Server *self, PyObject *args, PyObject *kwargs); +PyObject *pygrpc_Server_start(Server *self, PyObject *ignored); +PyObject *pygrpc_Server_shutdown( + Server *self, PyObject *args, PyObject *kwargs); +extern PyTypeObject pygrpc_Server_type; + +/*=========*/ +/* Utility */ +/*=========*/ + +/* Every tag that passes from Python GRPC to GRPC core is of this type. */ +typedef struct pygrpc_tag { + PyObject *user_tag; + Call *call; + grpc_call_details request_call_details; + grpc_metadata_array request_metadata; + grpc_op *ops; + size_t nops; + int is_new_call; +} pygrpc_tag; + +/* Construct a tag associated with a batch call. Does not take ownership of the + resources in the elements of ops. */ +pygrpc_tag *pygrpc_produce_batch_tag(PyObject *user_tag, Call *call, + grpc_op *ops, size_t nops); + + +/* Construct a tag associated with a server request. The calling code should + use the appropriate fields of the produced tag in the invocation of + grpc_server_request_call. */ +pygrpc_tag *pygrpc_produce_request_tag(PyObject *user_tag, Call *empty_call); + +/* Construct a tag associated with a server shutdown. */ +pygrpc_tag *pygrpc_produce_server_shutdown_tag(PyObject *user_tag); + +/* Frees all resources owned by the tag and the tag itself. */ +void pygrpc_discard_tag(pygrpc_tag *tag); + +/* Consumes an event and its associated tag, providing a Python tuple of the + form `(type, tag, call, call_details, results)` (where type is an integer + corresponding to a grpc_completion_type, tag is an arbitrary PyObject, call + is the call object associated with the event [if any], call_details is a + tuple of form `(method, host, deadline)` [if such details are available], + and resultd is a list of tuples of form `(type, metadata, message, status, + cancelled)` [where type corresponds to a grpc_op_type, metadata is a + sequence of 2-sequences of strings, message is a byte string, and status is + a 2-tuple of an integer corresponding to grpc_status_code and a string of + status details]). + + Frees all resources associated with the event tag. */ +PyObject *pygrpc_consume_event(grpc_event event); + +/* Transliterate the Python tuple of form `(type, metadata, message, + status)` (where type is an integer corresponding to a grpc_op_type, metadata + is a sequence of 2-sequences of strings, message is a byte string, and + status is 2-tuple of an integer corresponding to grpc_status_code and a + string of status details) to a grpc_op suitable for use in a + grpc_call_start_batch invocation. The grpc_op is a 'directory' of resources + that must be freed after GRPC core is done with them. + + Calls gpr_malloc (or the appropriate type-specific grpc_*_create function) + to populate the appropriate union-discriminated members of the op. + + Returns true on success, false on failure. */ +int pygrpc_produce_op(PyObject *op, grpc_op *result); + +/* Discards all resources associated with the passed in op that was produced by + pygrpc_produce_op. */ +void pygrpc_discard_op(grpc_op op); + +/* Transliterate the grpc_ops (which have been sent through a + grpc_call_start_batch invocation and whose corresponding event has appeared + on a completion queue) to a Python tuple of form `(type, metadata, message, + status, cancelled)` (where type is an integer corresponding to a + grpc_op_type, metadata is a sequence of 2-sequences of strings, message is a + byte string, and status is 2-tuple of an integer corresponding to + grpc_status_code and a string of status details). + + Calls gpr_free (or the appropriate type-specific grpc_*_destroy function) on + the appropriate union-discriminated populated members of the ops. */ +PyObject *pygrpc_consume_ops(grpc_op *op, size_t nops); + +/* Transliterate from a gpr_timespec to a double (in units of seconds, either + from the epoch if interpreted absolutely or as a delta otherwise). */ +double pygrpc_cast_gpr_timespec_to_double(gpr_timespec timespec); + +/* Transliterate from a double (in units of seconds from the epoch if + interpreted absolutely or as a delta otherwise) to a gpr_timespec. */ +gpr_timespec pygrpc_cast_double_to_gpr_timespec(double seconds); + +/* Returns true on success, false on failure. */ +int pygrpc_cast_pylist_to_send_metadata( + PyObject *pylist, grpc_metadata **metadata, size_t *count); +/* Returns a metadata array as a Python object on success, else NULL. */ +PyObject *pygrpc_cast_metadata_array_to_pylist(grpc_metadata_array metadata); + +/* Transliterate from a list of python channel arguments (2-tuples of string + and string|integer|None) to a grpc_channel_args object. The strings placed + in the grpc_channel_args object's grpc_arg elements are views of the Python + object. The Python object must live long enough for the grpc_channel_args + to be used. Arguments set to None are silently ignored. Returns true on + success, false on failure. */ +int pygrpc_produce_channel_args(PyObject *py_args, grpc_channel_args *c_args); +void pygrpc_discard_channel_args(grpc_channel_args args); + +/* Read the bytes from grpc_byte_buffer to a gpr_malloc'd array of bytes; + output to result and result_size. */ +void pygrpc_byte_buffer_to_bytes( + grpc_byte_buffer *buffer, char **result, size_t *result_size); + + +/*========*/ +/* Module */ +/*========*/ + +/* Returns 0 on success, -1 on failure. */ +int pygrpc_module_add_types(PyObject *module); + +#endif /* GRPC__ADAPTER__C_TYPES_H_ */ diff --git a/src/python/src/grpc/_adapter/_c/types/call.c b/src/python/src/grpc/_adapter/_c/types/call.c new file mode 100644 index 00000000000..0739070044a --- /dev/null +++ b/src/python/src/grpc/_adapter/_c/types/call.c @@ -0,0 +1,163 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "grpc/_adapter/_c/types.h" + +#define PY_SSIZE_T_CLEAN +#include +#include +#include + + +PyMethodDef pygrpc_Call_methods[] = { + {"start_batch", (PyCFunction)pygrpc_Call_start_batch, METH_KEYWORDS, ""}, + {"cancel", (PyCFunction)pygrpc_Call_cancel, METH_KEYWORDS, ""}, + {NULL} +}; +const char pygrpc_Call_doc[] = "See grpc._adapter._types.Call."; +PyTypeObject pygrpc_Call_type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "Call", /* tp_name */ + sizeof(Call), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)pygrpc_Call_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + pygrpc_Call_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + pygrpc_Call_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0 /* tp_new */ +}; + +Call *pygrpc_Call_new_empty(CompletionQueue *cq) { + Call *call = (Call *)pygrpc_Call_type.tp_alloc(&pygrpc_Call_type, 0); + call->c_call = NULL; + call->cq = cq; + Py_XINCREF(call->cq); + return call; +} +void pygrpc_Call_dealloc(Call *self) { + if (self->c_call) { + grpc_call_destroy(self->c_call); + } + Py_XDECREF(self->cq); + self->ob_type->tp_free((PyObject *)self); +} +PyObject *pygrpc_Call_start_batch(Call *self, PyObject *args, PyObject *kwargs) { + PyObject *op_list; + PyObject *user_tag; + grpc_op *ops; + size_t nops; + size_t i; + size_t j; + pygrpc_tag *tag; + grpc_call_error errcode; + static char *keywords[] = {"ops", "tag", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO:start_batch", keywords, + &op_list, &user_tag)) { + return NULL; + } + if (!PyList_Check(op_list)) { + PyErr_SetString(PyExc_TypeError, "expected a list of OpArgs"); + return NULL; + } + nops = PyList_Size(op_list); + ops = gpr_malloc(sizeof(grpc_op) * nops); + for (i = 0; i < nops; ++i) { + PyObject *item = PyList_GET_ITEM(op_list, i); + if (!pygrpc_produce_op(item, &ops[i])) { + for (j = 0; j < i; ++j) { + pygrpc_discard_op(ops[j]); + } + return NULL; + } + } + tag = pygrpc_produce_batch_tag(user_tag, self, ops, nops); + errcode = grpc_call_start_batch(self->c_call, tag->ops, tag->nops, tag); + gpr_free(ops); + return PyInt_FromLong(errcode); +} +PyObject *pygrpc_Call_cancel(Call *self, PyObject *args, PyObject *kwargs) { + PyObject *py_code = NULL; + grpc_call_error errcode; + int code; + char *details = NULL; + static char *keywords[] = {"code", "details", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Os:start_batch", keywords, + &py_code, &details)) { + return NULL; + } + if (py_code != NULL && details != NULL) { + if (!PyInt_Check(py_code)) { + PyErr_SetString(PyExc_TypeError, "expected integer code"); + return NULL; + } + code = PyInt_AsLong(py_code); + errcode = grpc_call_cancel_with_status(self->c_call, code, details); + } else if (py_code != NULL || details != NULL) { + PyErr_SetString(PyExc_ValueError, + "if `code` is specified, so must `details`"); + return NULL; + } else { + errcode = grpc_call_cancel(self->c_call); + } + return PyInt_FromLong(errcode); +} diff --git a/src/python/src/grpc/_adapter/_c/types/channel.c b/src/python/src/grpc/_adapter/_c/types/channel.c new file mode 100644 index 00000000000..c235597466c --- /dev/null +++ b/src/python/src/grpc/_adapter/_c/types/channel.c @@ -0,0 +1,134 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "grpc/_adapter/_c/types.h" + +#define PY_SSIZE_T_CLEAN +#include +#include + + +PyMethodDef pygrpc_Channel_methods[] = { + {"create_call", (PyCFunction)pygrpc_Channel_create_call, METH_KEYWORDS, ""}, + {NULL} +}; +const char pygrpc_Channel_doc[] = "See grpc._adapter._types.Channel."; +PyTypeObject pygrpc_Channel_type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "Channel", /* tp_name */ + sizeof(Channel), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)pygrpc_Channel_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + pygrpc_Channel_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + pygrpc_Channel_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)pygrpc_Channel_new /* tp_new */ +}; + +Channel *pygrpc_Channel_new( + PyTypeObject *type, PyObject *args, PyObject *kwargs) { + Channel *self; + const char *target; + PyObject *py_args; + ClientCredentials *creds = NULL; + grpc_channel_args c_args; + char *keywords[] = {"target", "args", "creds", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|O!:Channel", keywords, + &target, &py_args, &pygrpc_ClientCredentials_type, &creds)) { + return NULL; + } + if (!pygrpc_produce_channel_args(py_args, &c_args)) { + return NULL; + } + self = (Channel *)type->tp_alloc(type, 0); + if (creds) { + self->c_chan = grpc_secure_channel_create(creds->c_creds, target, &c_args); + } else { + self->c_chan = grpc_channel_create(target, &c_args); + } + pygrpc_discard_channel_args(c_args); + return self; +} +void pygrpc_Channel_dealloc(Channel *self) { + grpc_channel_destroy(self->c_chan); + self->ob_type->tp_free((PyObject *)self); +} + +Call *pygrpc_Channel_create_call( + Channel *self, PyObject *args, PyObject *kwargs) { + Call *call; + CompletionQueue *cq; + const char *method; + const char *host; + double deadline; + char *keywords[] = {"cq", "method", "host", "deadline", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!ssd:create_call", keywords, + &pygrpc_CompletionQueue_type, &cq, &method, &host, &deadline)) { + return NULL; + } + call = pygrpc_Call_new_empty(cq); + call->c_call = grpc_channel_create_call( + self->c_chan, cq->c_cq, method, host, + pygrpc_cast_double_to_gpr_timespec(deadline)); + return call; +} diff --git a/src/python/src/grpc/_adapter/_c/types/client_credentials.c b/src/python/src/grpc/_adapter/_c/types/client_credentials.c new file mode 100644 index 00000000000..6a4561c0606 --- /dev/null +++ b/src/python/src/grpc/_adapter/_c/types/client_credentials.c @@ -0,0 +1,286 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "grpc/_adapter/_c/types.h" + +#define PY_SSIZE_T_CLEAN +#include +#include +#include + + +PyMethodDef pygrpc_ClientCredentials_methods[] = { + {"google_default", (PyCFunction)pygrpc_ClientCredentials_google_default, + METH_CLASS|METH_NOARGS, ""}, + {"ssl", (PyCFunction)pygrpc_ClientCredentials_ssl, + METH_CLASS|METH_KEYWORDS, ""}, + {"composite", (PyCFunction)pygrpc_ClientCredentials_composite, + METH_CLASS|METH_KEYWORDS, ""}, + {"compute_engine", (PyCFunction)pygrpc_ClientCredentials_compute_engine, + METH_CLASS|METH_NOARGS, ""}, + {"service_account", (PyCFunction)pygrpc_ClientCredentials_service_account, + METH_CLASS|METH_KEYWORDS, ""}, + {"jwt", (PyCFunction)pygrpc_ClientCredentials_jwt, + METH_CLASS|METH_KEYWORDS, ""}, + {"refresh_token", (PyCFunction)pygrpc_ClientCredentials_refresh_token, + METH_CLASS|METH_KEYWORDS, ""}, + {"fake_transport_security", + (PyCFunction)pygrpc_ClientCredentials_fake_transport_security, + METH_CLASS|METH_NOARGS, ""}, + {"iam", (PyCFunction)pygrpc_ClientCredentials_iam, + METH_CLASS|METH_KEYWORDS, ""}, + {NULL} +}; +const char pygrpc_ClientCredentials_doc[] = ""; +PyTypeObject pygrpc_ClientCredentials_type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "ClientCredentials", /* tp_name */ + sizeof(ClientCredentials), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)pygrpc_ClientCredentials_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + pygrpc_ClientCredentials_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + pygrpc_ClientCredentials_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0 /* tp_new */ +}; + +void pygrpc_ClientCredentials_dealloc(ClientCredentials *self) { + grpc_credentials_release(self->c_creds); + self->ob_type->tp_free((PyObject *)self); +} + +ClientCredentials *pygrpc_ClientCredentials_google_default( + PyTypeObject *type, PyObject *ignored) { + ClientCredentials *self = (ClientCredentials *)type->tp_alloc(type, 0); + self->c_creds = grpc_google_default_credentials_create(); + if (!self->c_creds) { + Py_DECREF(self); + PyErr_SetString(PyExc_RuntimeError, + "couldn't create Google default credentials"); + return NULL; + } + return self; +} + +ClientCredentials *pygrpc_ClientCredentials_ssl( + PyTypeObject *type, PyObject *args, PyObject *kwargs) { + ClientCredentials *self; + const char *root_certs; + const char *private_key = NULL; + const char *cert_chain = NULL; + grpc_ssl_pem_key_cert_pair key_cert_pair; + static char *keywords[] = {"root_certs", "private_key", "cert_chain", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|zz:ssl", keywords, + &root_certs, &private_key, &cert_chain)) { + return NULL; + } + self = (ClientCredentials *)type->tp_alloc(type, 0); + if (private_key && cert_chain) { + key_cert_pair.private_key = private_key; + key_cert_pair.cert_chain = cert_chain; + self->c_creds = grpc_ssl_credentials_create(root_certs, &key_cert_pair); + } else { + self->c_creds = grpc_ssl_credentials_create(root_certs, NULL); + } + if (!self->c_creds) { + Py_DECREF(self); + PyErr_SetString(PyExc_RuntimeError, "couldn't create ssl credentials"); + return NULL; + } + return self; +} + +ClientCredentials *pygrpc_ClientCredentials_composite( + PyTypeObject *type, PyObject *args, PyObject *kwargs) { + ClientCredentials *self; + ClientCredentials *creds1; + ClientCredentials *creds2; + static char *keywords[] = {"creds1", "creds2", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!O!:composite", keywords, + &pygrpc_ClientCredentials_type, &creds1, + &pygrpc_ClientCredentials_type, &creds2)) { + return NULL; + } + self = (ClientCredentials *)type->tp_alloc(type, 0); + self->c_creds = grpc_composite_credentials_create( + creds1->c_creds, creds2->c_creds); + if (!self->c_creds) { + Py_DECREF(self); + PyErr_SetString(PyExc_RuntimeError, "couldn't create composite credentials"); + return NULL; + } + return self; +} + +ClientCredentials *pygrpc_ClientCredentials_compute_engine( + PyTypeObject *type, PyObject *ignored) { + ClientCredentials *self = (ClientCredentials *)type->tp_alloc(type, 0); + self->c_creds = grpc_compute_engine_credentials_create(); + if (!self->c_creds) { + Py_DECREF(self); + PyErr_SetString(PyExc_RuntimeError, + "couldn't create compute engine credentials"); + return NULL; + } + return self; +} + +ClientCredentials *pygrpc_ClientCredentials_service_account( + PyTypeObject *type, PyObject *args, PyObject *kwargs) { + ClientCredentials *self; + const char *json_key; + const char *scope; + double lifetime; + static char *keywords[] = {"json_key", "scope", "token_lifetime", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ssd:service_account", keywords, + &json_key, &scope, &lifetime)) { + return NULL; + } + self = (ClientCredentials *)type->tp_alloc(type, 0); + self->c_creds = grpc_service_account_credentials_create( + json_key, scope, pygrpc_cast_double_to_gpr_timespec(lifetime)); + if (!self->c_creds) { + Py_DECREF(self); + PyErr_SetString(PyExc_RuntimeError, + "couldn't create service account credentials"); + return NULL; + } + return self; +} + +ClientCredentials *pygrpc_ClientCredentials_jwt( + PyTypeObject *type, PyObject *args, PyObject *kwargs) { + ClientCredentials *self; + const char *json_key; + double lifetime; + static char *keywords[] = {"json_key", "token_lifetime", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sd:jwt", keywords, + &json_key, &lifetime)) { + return NULL; + } + self = (ClientCredentials *)type->tp_alloc(type, 0); + self->c_creds = grpc_jwt_credentials_create( + json_key, pygrpc_cast_double_to_gpr_timespec(lifetime)); + if (!self->c_creds) { + Py_DECREF(self); + PyErr_SetString(PyExc_RuntimeError, "couldn't create JWT credentials"); + return NULL; + } + return self; +} + +ClientCredentials *pygrpc_ClientCredentials_refresh_token( + PyTypeObject *type, PyObject *args, PyObject *kwargs) { + ClientCredentials *self; + const char *json_refresh_token; + static char *keywords[] = {"json_refresh_token", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:refresh_token", keywords, + &json_refresh_token)) { + return NULL; + } + self = (ClientCredentials *)type->tp_alloc(type, 0); + self->c_creds = grpc_refresh_token_credentials_create(json_refresh_token); + if (!self->c_creds) { + Py_DECREF(self); + PyErr_SetString(PyExc_RuntimeError, + "couldn't create credentials from refresh token"); + return NULL; + } + return self; +} + +ClientCredentials *pygrpc_ClientCredentials_fake_transport_security( + PyTypeObject *type, PyObject *ignored) { + ClientCredentials *self = (ClientCredentials *)type->tp_alloc(type, 0); + self->c_creds = grpc_fake_transport_security_credentials_create(); + if (!self->c_creds) { + Py_DECREF(self); + PyErr_SetString(PyExc_RuntimeError, + "couldn't create fake credentials; " + "something is horribly wrong with the universe"); + return NULL; + } + return self; +} + +ClientCredentials *pygrpc_ClientCredentials_iam( + PyTypeObject *type, PyObject *args, PyObject *kwargs) { + ClientCredentials *self; + const char *authorization_token; + const char *authority_selector; + static char *keywords[] = {"authorization_token", "authority_selector", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss:iam", keywords, + &authorization_token, &authority_selector)) { + return NULL; + } + self = (ClientCredentials *)type->tp_alloc(type, 0); + self->c_creds = grpc_iam_credentials_create(authorization_token, + authority_selector); + if (!self->c_creds) { + Py_DECREF(self); + PyErr_SetString(PyExc_RuntimeError, "couldn't create IAM credentials"); + return NULL; + } + return self; +} + diff --git a/src/python/src/grpc/_adapter/_c/types/completion_queue.c b/src/python/src/grpc/_adapter/_c/types/completion_queue.c new file mode 100644 index 00000000000..2dd44b6ddd8 --- /dev/null +++ b/src/python/src/grpc/_adapter/_c/types/completion_queue.c @@ -0,0 +1,124 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "grpc/_adapter/_c/types.h" + +#define PY_SSIZE_T_CLEAN +#include +#include + + +PyMethodDef pygrpc_CompletionQueue_methods[] = { + {"next", (PyCFunction)pygrpc_CompletionQueue_next, METH_KEYWORDS, ""}, + {"shutdown", (PyCFunction)pygrpc_CompletionQueue_shutdown, METH_NOARGS, ""}, + {NULL} +}; +const char pygrpc_CompletionQueue_doc[] = + "See grpc._adapter._types.CompletionQueue."; +PyTypeObject pygrpc_CompletionQueue_type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "CompletionQueue", /* tp_name */ + sizeof(CompletionQueue), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)pygrpc_CompletionQueue_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + pygrpc_CompletionQueue_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + pygrpc_CompletionQueue_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)pygrpc_CompletionQueue_new /* tp_new */ +}; + +CompletionQueue *pygrpc_CompletionQueue_new( + PyTypeObject *type, PyObject *args, PyObject *kwargs) { + CompletionQueue *self = (CompletionQueue *)type->tp_alloc(type, 0); + self->c_cq = grpc_completion_queue_create(); + return self; +} + +void pygrpc_CompletionQueue_dealloc(CompletionQueue *self) { + grpc_completion_queue_destroy(self->c_cq); + self->ob_type->tp_free((PyObject *)self); +} + +PyObject *pygrpc_CompletionQueue_next( + CompletionQueue *self, PyObject *args, PyObject *kwargs) { + double deadline; + grpc_event event; + PyObject *transliterated_event; + static char *keywords[] = {"deadline", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "d:next", keywords, + &deadline)) { + return NULL; + } + Py_BEGIN_ALLOW_THREADS; + event = grpc_completion_queue_next( + self->c_cq, pygrpc_cast_double_to_gpr_timespec(deadline)); + Py_END_ALLOW_THREADS; + transliterated_event = pygrpc_consume_event(event); + return transliterated_event; +} + +PyObject *pygrpc_CompletionQueue_shutdown( + CompletionQueue *self, PyObject *ignored) { + grpc_completion_queue_shutdown(self->c_cq); + Py_RETURN_NONE; +} diff --git a/src/python/src/grpc/_adapter/_c/types/server.c b/src/python/src/grpc/_adapter/_c/types/server.c new file mode 100644 index 00000000000..65d84b58fe8 --- /dev/null +++ b/src/python/src/grpc/_adapter/_c/types/server.c @@ -0,0 +1,183 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "grpc/_adapter/_c/types.h" + +#define PY_SSIZE_T_CLEAN +#include +#include + + +PyMethodDef pygrpc_Server_methods[] = { + {"request_call", (PyCFunction)pygrpc_Server_request_call, + METH_KEYWORDS, ""}, + {"add_http2_port", (PyCFunction)pygrpc_Server_add_http2_port, + METH_KEYWORDS, ""}, + {"start", (PyCFunction)pygrpc_Server_start, METH_NOARGS, ""}, + {"shutdown", (PyCFunction)pygrpc_Server_shutdown, METH_KEYWORDS, ""}, + {NULL} +}; +const char pygrpc_Server_doc[] = "See grpc._adapter._types.Server."; +PyTypeObject pygrpc_Server_type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "Server", /* tp_name */ + sizeof(Server), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)pygrpc_Server_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + pygrpc_Server_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + pygrpc_Server_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + (newfunc)pygrpc_Server_new /* tp_new */ +}; + +Server *pygrpc_Server_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { + Server *self; + CompletionQueue *cq; + PyObject *py_args; + grpc_channel_args c_args; + char *keywords[] = {"cq", "args", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!O:Channel", keywords, + &pygrpc_CompletionQueue_type, &cq, &py_args)) { + return NULL; + } + if (!pygrpc_produce_channel_args(py_args, &c_args)) { + return NULL; + } + self = (Server *)type->tp_alloc(type, 0); + self->c_serv = grpc_server_create(&c_args); + pygrpc_discard_channel_args(c_args); + self->cq = cq; + Py_INCREF(self->cq); + return self; +} + +void pygrpc_Server_dealloc(Server *self) { + grpc_server_destroy(self->c_serv); + Py_XDECREF(self->cq); + self->ob_type->tp_free((PyObject *)self); +} + +PyObject *pygrpc_Server_request_call( + Server *self, PyObject *args, PyObject *kwargs) { + CompletionQueue *cq; + PyObject *user_tag; + pygrpc_tag *tag; + Call *empty_call; + grpc_call_error errcode; + static char *keywords[] = {"cq", "tag", NULL}; + if (!PyArg_ParseTupleAndKeywords( + args, kwargs, "O!O", keywords, + &pygrpc_CompletionQueue_type, &cq, &user_tag)) { + return NULL; + } + empty_call = pygrpc_Call_new_empty(cq); + tag = pygrpc_produce_request_tag(user_tag, empty_call); + errcode = grpc_server_request_call( + self->c_serv, &tag->call->c_call, &tag->request_call_details, + &tag->request_metadata, tag->call->cq->c_cq, self->cq->c_cq, tag); + Py_DECREF(empty_call); + return PyInt_FromLong(errcode); +} + +PyObject *pygrpc_Server_add_http2_port( + Server *self, PyObject *args, PyObject *kwargs) { + const char *addr; + ServerCredentials *creds = NULL; + int port; + static char *keywords[] = {"addr", "creds", NULL}; + if (!PyArg_ParseTupleAndKeywords( + args, kwargs, "s|O!:add_http2_port", keywords, + &addr, &pygrpc_ServerCredentials_type, &creds)) { + return NULL; + } + if (creds) { + port = grpc_server_add_secure_http2_port( + self->c_serv, addr, creds->c_creds); + } else { + port = grpc_server_add_http2_port(self->c_serv, addr); + } + return PyInt_FromLong(port); + +} + +PyObject *pygrpc_Server_start(Server *self, PyObject *ignored) { + grpc_server_start(self->c_serv); + Py_RETURN_NONE; +} + +PyObject *pygrpc_Server_shutdown( + Server *self, PyObject *args, PyObject *kwargs) { + PyObject *user_tag = NULL; + pygrpc_tag *tag; + static char *keywords[] = {"tag", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", keywords, &user_tag)) { + return NULL; + } + if (user_tag) { + tag = pygrpc_produce_server_shutdown_tag(user_tag); + grpc_server_shutdown_and_notify(self->c_serv, tag); + } else { + grpc_server_shutdown(self->c_serv); + } + Py_RETURN_NONE; +} diff --git a/src/python/src/grpc/_adapter/_c/types/server_credentials.c b/src/python/src/grpc/_adapter/_c/types/server_credentials.c new file mode 100644 index 00000000000..2e02c8fe816 --- /dev/null +++ b/src/python/src/grpc/_adapter/_c/types/server_credentials.c @@ -0,0 +1,146 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "grpc/_adapter/_c/types.h" + +#define PY_SSIZE_T_CLEAN +#include +#include +#include +#include + + +PyMethodDef pygrpc_ServerCredentials_methods[] = { + {"ssl", (PyCFunction)pygrpc_ServerCredentials_ssl, + METH_CLASS|METH_KEYWORDS, ""}, + {"fake_transport_security", + (PyCFunction)pygrpc_ServerCredentials_fake_transport_security, + METH_CLASS|METH_NOARGS, ""}, + {NULL} +}; +const char pygrpc_ServerCredentials_doc[] = ""; +PyTypeObject pygrpc_ServerCredentials_type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "ServerCredentials", /* tp_name */ + sizeof(ServerCredentials), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)pygrpc_ServerCredentials_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + pygrpc_ServerCredentials_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + pygrpc_ServerCredentials_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0 /* tp_new */ +}; + +void pygrpc_ServerCredentials_dealloc(ServerCredentials *self) { + grpc_server_credentials_release(self->c_creds); + self->ob_type->tp_free((PyObject *)self); +} + +ServerCredentials *pygrpc_ServerCredentials_ssl( + PyTypeObject *type, PyObject *args, PyObject *kwargs) { + ServerCredentials *self; + const char *root_certs; + PyObject *py_key_cert_pairs; + grpc_ssl_pem_key_cert_pair *key_cert_pairs; + size_t num_key_cert_pairs; + size_t i; + static char *keywords[] = {"root_certs", "key_cert_pairs", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "zO:ssl", keywords, + &root_certs, &py_key_cert_pairs)) { + return NULL; + } + if (!PyList_Check(py_key_cert_pairs)) { + PyErr_SetString(PyExc_TypeError, "expected a list of 2-tuples of strings"); + return NULL; + } + num_key_cert_pairs = PyList_Size(py_key_cert_pairs); + key_cert_pairs = + gpr_malloc(sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs); + for (i = 0; i < num_key_cert_pairs; ++i) { + PyObject *item = PyList_GET_ITEM(py_key_cert_pairs, i); + const char *key; + const char *cert; + if (!PyArg_ParseTuple(item, "zz", &key, &cert)) { + gpr_free(key_cert_pairs); + PyErr_SetString(PyExc_TypeError, + "expected a list of 2-tuples of strings"); + return NULL; + } + key_cert_pairs[i].private_key = key; + key_cert_pairs[i].cert_chain = cert; + } + + self = (ServerCredentials *)type->tp_alloc(type, 0); + self->c_creds = grpc_ssl_server_credentials_create( + root_certs, key_cert_pairs, num_key_cert_pairs); + gpr_free(key_cert_pairs); + return self; +} + +ServerCredentials *pygrpc_ServerCredentials_fake_transport_security( + PyTypeObject *type, PyObject *ignored) { + ServerCredentials *self = (ServerCredentials *)type->tp_alloc(type, 0); + self->c_creds = grpc_fake_transport_security_server_credentials_create(); + return self; +} + diff --git a/src/python/src/grpc/_adapter/_c/utility.c b/src/python/src/grpc/_adapter/_c/utility.c new file mode 100644 index 00000000000..6d228c73fe6 --- /dev/null +++ b/src/python/src/grpc/_adapter/_c/utility.c @@ -0,0 +1,460 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#define PY_SSIZE_T_CLEAN +#include +#include +#include +#include +#include + +#include "grpc/_adapter/_c/types.h" + +pygrpc_tag *pygrpc_produce_batch_tag( + PyObject *user_tag, Call *call, grpc_op *ops, size_t nops) { + pygrpc_tag *tag = gpr_malloc(sizeof(pygrpc_tag)); + tag->user_tag = user_tag; + Py_XINCREF(tag->user_tag); + tag->call = call; + Py_XINCREF(tag->call); + tag->ops = gpr_malloc(sizeof(grpc_op)*nops); + memcpy(tag->ops, ops, sizeof(grpc_op)*nops); + tag->nops = nops; + grpc_call_details_init(&tag->request_call_details); + grpc_metadata_array_init(&tag->request_metadata); + tag->is_new_call = 0; + return tag; +} + +pygrpc_tag *pygrpc_produce_request_tag(PyObject *user_tag, Call *empty_call) { + pygrpc_tag *tag = gpr_malloc(sizeof(pygrpc_tag)); + tag->user_tag = user_tag; + Py_XINCREF(tag->user_tag); + tag->call = empty_call; + Py_XINCREF(tag->call); + tag->ops = NULL; + tag->nops = 0; + grpc_call_details_init(&tag->request_call_details); + grpc_metadata_array_init(&tag->request_metadata); + tag->is_new_call = 1; + return tag; +} + +pygrpc_tag *pygrpc_produce_server_shutdown_tag(PyObject *user_tag) { + pygrpc_tag *tag = gpr_malloc(sizeof(pygrpc_tag)); + tag->user_tag = user_tag; + Py_XINCREF(tag->user_tag); + tag->call = NULL; + tag->ops = NULL; + tag->nops = 0; + grpc_call_details_init(&tag->request_call_details); + grpc_metadata_array_init(&tag->request_metadata); + tag->is_new_call = 0; + return tag; +} + +void pygrpc_discard_tag(pygrpc_tag *tag) { + if (!tag) { + return; + } + Py_XDECREF(tag->user_tag); + Py_XDECREF(tag->call); + gpr_free(tag->ops); + grpc_call_details_destroy(&tag->request_call_details); + grpc_metadata_array_destroy(&tag->request_metadata); + gpr_free(tag); +} + +PyObject *pygrpc_consume_event(grpc_event event) { + pygrpc_tag *tag; + PyObject *result; + if (event.type == GRPC_QUEUE_TIMEOUT) { + Py_RETURN_NONE; + } + tag = event.tag; + switch (event.type) { + case GRPC_QUEUE_SHUTDOWN: + result = Py_BuildValue("iOOOOO", GRPC_QUEUE_SHUTDOWN, + Py_None, Py_None, Py_None, Py_None, Py_True); + break; + case GRPC_OP_COMPLETE: + if (tag->is_new_call) { + result = Py_BuildValue( + "iOO(ssd)[(iNOOOO)]O", GRPC_OP_COMPLETE, tag->user_tag, tag->call, + tag->request_call_details.method, tag->request_call_details.host, + pygrpc_cast_gpr_timespec_to_double(tag->request_call_details.deadline), + GRPC_OP_RECV_INITIAL_METADATA, + pygrpc_cast_metadata_array_to_pylist(tag->request_metadata), Py_None, + Py_None, Py_None, Py_None, + event.success ? Py_True : Py_False); + } else { + result = Py_BuildValue("iOOONO", GRPC_OP_COMPLETE, tag->user_tag, + tag->call, Py_None, pygrpc_consume_ops(tag->ops, tag->nops), + event.success ? Py_True : Py_False); + } + break; + default: + PyErr_SetString(PyExc_ValueError, + "unknown completion type; could not translate event"); + return NULL; + } + pygrpc_discard_tag(tag); + return result; +} + +int pygrpc_produce_op(PyObject *op, grpc_op *result) { + static const int OP_TUPLE_SIZE = 5; + static const int STATUS_TUPLE_SIZE = 2; + static const int TYPE_INDEX = 0; + static const int INITIAL_METADATA_INDEX = 1; + static const int TRAILING_METADATA_INDEX = 2; + static const int MESSAGE_INDEX = 3; + static const int STATUS_INDEX = 4; + static const int STATUS_CODE_INDEX = 0; + static const int STATUS_DETAILS_INDEX = 1; + grpc_op c_op; + if (!PyTuple_Check(op)) { + PyErr_SetString(PyExc_TypeError, "expected tuple op"); + return 0; + } + if (PyTuple_Size(op) != OP_TUPLE_SIZE) { + char buf[64]; + snprintf(buf, sizeof(buf), "expected tuple op of length %d", OP_TUPLE_SIZE); + PyErr_SetString(PyExc_ValueError, buf); + return 0; + } + int type = PyInt_AsLong(PyTuple_GET_ITEM(op, TYPE_INDEX)); + if (PyErr_Occurred()) { + return 0; + } + Py_ssize_t message_size; + char *message; + char *status_details; + gpr_slice message_slice; + c_op.op = type; + switch (type) { + case GRPC_OP_SEND_INITIAL_METADATA: + if (!pygrpc_cast_pylist_to_send_metadata( + PyTuple_GetItem(op, INITIAL_METADATA_INDEX), + &c_op.data.send_initial_metadata.metadata, + &c_op.data.send_initial_metadata.count)) { + return 0; + } + break; + case GRPC_OP_SEND_MESSAGE: + PyString_AsStringAndSize( + PyTuple_GET_ITEM(op, MESSAGE_INDEX), &message, &message_size); + message_slice = gpr_slice_from_copied_buffer(message, message_size); + c_op.data.send_message = grpc_byte_buffer_create(&message_slice, 1); + gpr_slice_unref(message_slice); + break; + case GRPC_OP_SEND_CLOSE_FROM_CLIENT: + /* Don't need to fill in any other fields. */ + break; + case GRPC_OP_SEND_STATUS_FROM_SERVER: + if (!pygrpc_cast_pylist_to_send_metadata( + PyTuple_GetItem(op, TRAILING_METADATA_INDEX), + &c_op.data.send_status_from_server.trailing_metadata, + &c_op.data.send_status_from_server.trailing_metadata_count)) { + return 0; + } + if (!PyTuple_Check(PyTuple_GET_ITEM(op, STATUS_INDEX))) { + char buf[64]; + snprintf(buf, sizeof(buf), "expected tuple status in op of length %d", + STATUS_TUPLE_SIZE); + PyErr_SetString(PyExc_TypeError, buf); + return 0; + } + c_op.data.send_status_from_server.status = PyInt_AsLong( + PyTuple_GET_ITEM(PyTuple_GET_ITEM(op, STATUS_INDEX), STATUS_CODE_INDEX)); + status_details = PyString_AsString( + PyTuple_GET_ITEM(PyTuple_GET_ITEM(op, STATUS_INDEX), STATUS_DETAILS_INDEX)); + if (PyErr_Occurred()) { + return 0; + } + c_op.data.send_status_from_server.status_details = + gpr_malloc(strlen(status_details) + 1); + strcpy((char *)c_op.data.send_status_from_server.status_details, + status_details); + break; + case GRPC_OP_RECV_INITIAL_METADATA: + c_op.data.recv_initial_metadata = gpr_malloc(sizeof(grpc_metadata_array)); + grpc_metadata_array_init(c_op.data.recv_initial_metadata); + break; + case GRPC_OP_RECV_MESSAGE: + c_op.data.recv_message = gpr_malloc(sizeof(grpc_byte_buffer *)); + break; + case GRPC_OP_RECV_STATUS_ON_CLIENT: + c_op.data.recv_status_on_client.trailing_metadata = + gpr_malloc(sizeof(grpc_metadata_array)); + grpc_metadata_array_init(c_op.data.recv_status_on_client.trailing_metadata); + c_op.data.recv_status_on_client.status = + gpr_malloc(sizeof(grpc_status_code *)); + c_op.data.recv_status_on_client.status_details = + gpr_malloc(sizeof(char *)); + *c_op.data.recv_status_on_client.status_details = NULL; + c_op.data.recv_status_on_client.status_details_capacity = + gpr_malloc(sizeof(size_t)); + *c_op.data.recv_status_on_client.status_details_capacity = 0; + break; + case GRPC_OP_RECV_CLOSE_ON_SERVER: + c_op.data.recv_close_on_server.cancelled = gpr_malloc(sizeof(int)); + break; + default: + return 0; + } + *result = c_op; + return 1; +} + +void pygrpc_discard_op(grpc_op op) { + switch(op.op) { + case GRPC_OP_SEND_INITIAL_METADATA: + gpr_free(op.data.send_initial_metadata.metadata); + break; + case GRPC_OP_SEND_MESSAGE: + grpc_byte_buffer_destroy(op.data.send_message); + break; + case GRPC_OP_SEND_CLOSE_FROM_CLIENT: + /* Don't need to free any fields. */ + break; + case GRPC_OP_SEND_STATUS_FROM_SERVER: + gpr_free(op.data.send_status_from_server.trailing_metadata); + gpr_free((char *)op.data.send_status_from_server.status_details); + break; + case GRPC_OP_RECV_INITIAL_METADATA: + grpc_metadata_array_destroy(op.data.recv_initial_metadata); + gpr_free(op.data.recv_initial_metadata); + break; + case GRPC_OP_RECV_MESSAGE: + grpc_byte_buffer_destroy(*op.data.recv_message); + gpr_free(op.data.recv_message); + break; + case GRPC_OP_RECV_STATUS_ON_CLIENT: + grpc_metadata_array_destroy(op.data.recv_status_on_client.trailing_metadata); + gpr_free(op.data.recv_status_on_client.trailing_metadata); + gpr_free(op.data.recv_status_on_client.status); + gpr_free(*op.data.recv_status_on_client.status_details); + gpr_free(op.data.recv_status_on_client.status_details); + gpr_free(op.data.recv_status_on_client.status_details_capacity); + break; + case GRPC_OP_RECV_CLOSE_ON_SERVER: + gpr_free(op.data.recv_close_on_server.cancelled); + break; + } +} + +PyObject *pygrpc_consume_ops(grpc_op *op, size_t nops) { + static const int TYPE_INDEX = 0; + static const int INITIAL_METADATA_INDEX = 1; + static const int TRAILING_METADATA_INDEX = 2; + static const int MESSAGE_INDEX = 3; + static const int STATUS_INDEX = 4; + static const int CANCELLED_INDEX = 5; + static const int OPRESULT_LENGTH = 6; + PyObject *list; + size_t i; + size_t j; + char *bytes; + size_t bytes_size; + PyObject *results = PyList_New(nops); + if (!results) { + return NULL; + } + for (i = 0; i < nops; ++i) { + PyObject *result = PyTuple_Pack(OPRESULT_LENGTH, Py_None, Py_None, Py_None, + Py_None, Py_None, Py_None); + PyTuple_SetItem(result, TYPE_INDEX, PyInt_FromLong(op[i].op)); + switch(op[i].op) { + case GRPC_OP_RECV_INITIAL_METADATA: + PyTuple_SetItem(result, INITIAL_METADATA_INDEX, + list=PyList_New(op[i].data.recv_initial_metadata->count)); + for (j = 0; j < op[i].data.recv_initial_metadata->count; ++j) { + grpc_metadata md = op[i].data.recv_initial_metadata->metadata[j]; + PyList_SetItem(list, j, Py_BuildValue("ss#", md.key, md.value, + (Py_ssize_t)md.value_length)); + } + break; + case GRPC_OP_RECV_MESSAGE: + if (*op[i].data.recv_message) { + pygrpc_byte_buffer_to_bytes( + *op[i].data.recv_message, &bytes, &bytes_size); + PyTuple_SetItem(result, MESSAGE_INDEX, + PyString_FromStringAndSize(bytes, bytes_size)); + gpr_free(bytes); + } else { + PyTuple_SetItem(result, MESSAGE_INDEX, Py_BuildValue("")); + } + break; + case GRPC_OP_RECV_STATUS_ON_CLIENT: + PyTuple_SetItem( + result, TRAILING_METADATA_INDEX, + list = PyList_New(op[i].data.recv_status_on_client.trailing_metadata->count)); + for (j = 0; j < op[i].data.recv_status_on_client.trailing_metadata->count; ++j) { + grpc_metadata md = + op[i].data.recv_status_on_client.trailing_metadata->metadata[j]; + PyList_SetItem(list, j, Py_BuildValue("ss#", md.key, md.value, + (Py_ssize_t)md.value_length)); + } + PyTuple_SetItem( + result, STATUS_INDEX, Py_BuildValue( + "is", *op[i].data.recv_status_on_client.status, + *op[i].data.recv_status_on_client.status_details)); + break; + case GRPC_OP_RECV_CLOSE_ON_SERVER: + PyTuple_SetItem( + result, CANCELLED_INDEX, + PyBool_FromLong(*op[i].data.recv_close_on_server.cancelled)); + break; + default: + break; + } + pygrpc_discard_op(op[i]); + PyList_SetItem(results, i, result); + } + return results; +} + +double pygrpc_cast_gpr_timespec_to_double(gpr_timespec timespec) { + return timespec.tv_sec + 1e-9*timespec.tv_nsec; +} + +gpr_timespec pygrpc_cast_double_to_gpr_timespec(double seconds) { + gpr_timespec result; + if isinf(seconds) { + result = seconds > 0.0 ? gpr_inf_future : gpr_inf_past; + } else { + result.tv_sec = (time_t)seconds; + result.tv_nsec = ((seconds - result.tv_sec) * 1e9); + } + return result; +} + +int pygrpc_produce_channel_args(PyObject *py_args, grpc_channel_args *c_args) { + size_t num_args = PyList_Size(py_args); + size_t i; + grpc_channel_args args = {num_args, gpr_malloc(sizeof(grpc_arg) * num_args)}; + for (i = 0; i < args.num_args; ++i) { + char *key; + PyObject *value; + if (!PyArg_ParseTuple(PyList_GetItem(py_args, i), "zO", &key, &value)) { + gpr_free(args.args); + args.num_args = 0; + args.args = NULL; + PyErr_SetString(PyExc_TypeError, + "expected a list of 2-tuple of str and str|int|None"); + return 0; + } + args.args[i].key = key; + if (PyInt_Check(value)) { + args.args[i].type = GRPC_ARG_INTEGER; + args.args[i].value.integer = PyInt_AsLong(value); + } else if (PyString_Check(value)) { + args.args[i].type = GRPC_ARG_STRING; + args.args[i].value.string = PyString_AsString(value); + } else if (value == Py_None) { + --args.num_args; + --i; + continue; + } else { + gpr_free(args.args); + args.num_args = 0; + args.args = NULL; + PyErr_SetString(PyExc_TypeError, + "expected a list of 2-tuple of str and str|int|None"); + return 0; + } + } + *c_args = args; + return 1; +} + +void pygrpc_discard_channel_args(grpc_channel_args args) { + gpr_free(args.args); +} + +int pygrpc_cast_pylist_to_send_metadata( + PyObject *pylist, grpc_metadata **metadata, size_t *count) { + size_t i; + Py_ssize_t value_length; + *count = PyList_Size(pylist); + *metadata = gpr_malloc(sizeof(grpc_metadata) * *count); + for (i = 0; i < *count; ++i) { + if (!PyArg_ParseTuple( + PyList_GetItem(pylist, i), "ss#", + &(*metadata)[i].key, &(*metadata)[i].value, &value_length)) { + gpr_free(*metadata); + *count = 0; + *metadata = NULL; + return 0; + } + (*metadata)[i].value_length = value_length; + } + return 1; +} + +PyObject *pygrpc_cast_metadata_array_to_pylist(grpc_metadata_array metadata) { + PyObject *result = PyList_New(metadata.count); + size_t i; + for (i = 0; i < metadata.count; ++i) { + PyList_SetItem( + result, i, Py_BuildValue( + "ss#", metadata.metadata[i].key, metadata.metadata[i].value, + (Py_ssize_t)metadata.metadata[i].value_length)); + if (PyErr_Occurred()) { + Py_DECREF(result); + return NULL; + } + } + return result; +} + +void pygrpc_byte_buffer_to_bytes( + grpc_byte_buffer *buffer, char **result, size_t *result_size) { + grpc_byte_buffer_reader *reader = grpc_byte_buffer_reader_create(buffer); + gpr_slice slice; + char *read_result = NULL; + size_t size = 0; + while (grpc_byte_buffer_reader_next(reader, &slice)) { + read_result = gpr_realloc(read_result, size + GPR_SLICE_LENGTH(slice)); + memcpy(read_result + size, GPR_SLICE_START_PTR(slice), + GPR_SLICE_LENGTH(slice)); + size = size + GPR_SLICE_LENGTH(slice); + gpr_slice_unref(slice); + } + grpc_byte_buffer_reader_destroy(reader); + *result_size = size; + *result = read_result; +} diff --git a/src/python/src/grpc/_adapter/_c_test.py b/src/python/src/grpc/_adapter/_c_test.py index b06215f0e53..133b124072c 100644 --- a/src/python/src/grpc/_adapter/_c_test.py +++ b/src/python/src/grpc/_adapter/_c_test.py @@ -27,192 +27,40 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -"""Tests for _adapter._c.""" - -import threading import time import unittest from grpc._adapter import _c -from grpc._adapter import _datatypes - -_TIMEOUT = 3 -_FUTURE = time.time() + 60 * 60 * 24 -_IDEMPOTENCE_DEMONSTRATION = 7 - - -class _CTest(unittest.TestCase): - - def testUpAndDown(self): - _c.init() - _c.shut_down() - - def testCompletionQueue(self): - _c.init() - - completion_queue = _c.CompletionQueue() - event = completion_queue.get(0) - self.assertIsNone(event) - event = completion_queue.get(time.time()) - self.assertIsNone(event) - event = completion_queue.get(time.time() + _TIMEOUT) - self.assertIsNone(event) - completion_queue.stop() - for _ in range(_IDEMPOTENCE_DEMONSTRATION): - event = completion_queue.get(time.time() + _TIMEOUT) - self.assertIs(event.kind, _datatypes.Event.Kind.STOP) - - del completion_queue - del event +from grpc._adapter import _types - _c.shut_down() - def testChannel(self): - _c.init() - - channel = _c.Channel( - 'test host:12345', None, server_host_override='ignored') - del channel - - _c.shut_down() - - def testCall(self): - method = 'test method' - host = 'test host' - - _c.init() - - channel = _c.Channel('%s:%d' % (host, 12345), None) - completion_queue = _c.CompletionQueue() - call = _c.Call(channel, completion_queue, method, host, - time.time() + _TIMEOUT) - del call - del completion_queue - del channel +class CTypeSmokeTest(unittest.TestCase): - _c.shut_down() + def testClientCredentialsUpDown(self): + credentials = _c.ClientCredentials.fake_transport_security() + del credentials - def testServer(self): - _c.init() + def testServerCredentialsUpDown(self): + credentials = _c.ServerCredentials.fake_transport_security() + del credentials + def testCompletionQueueUpDown(self): completion_queue = _c.CompletionQueue() - server = _c.Server(completion_queue) - server.add_http2_addr('[::]:0') - server.start() - server.stop() - completion_queue.stop() - del server del completion_queue - service_tag = object() + def testServerUpDown(self): completion_queue = _c.CompletionQueue() - server = _c.Server(completion_queue) - server.add_http2_addr('[::]:0') - server.start() - server.service(service_tag) - server.stop() - completion_queue.stop() - event = completion_queue.get(time.time() + _TIMEOUT) - self.assertIs(event.kind, _datatypes.Event.Kind.SERVICE_ACCEPTED) - self.assertIs(event.tag, service_tag) - self.assertIsNone(event.service_acceptance) - for _ in range(_IDEMPOTENCE_DEMONSTRATION): - event = completion_queue.get(time.time() + _TIMEOUT) - self.assertIs(event.kind, _datatypes.Event.Kind.STOP) - del server + serv = _c.Server(completion_queue, []) + del serv del completion_queue - completion_queue = _c.CompletionQueue() - server = _c.Server(completion_queue) - server.add_http2_addr('[::]:0') - server.start() - thread = threading.Thread(target=completion_queue.get, args=(_FUTURE,)) - thread.start() - time.sleep(1) - server.stop() - completion_queue.stop() - for _ in range(_IDEMPOTENCE_DEMONSTRATION): - event = completion_queue.get(time.time() + _TIMEOUT) - self.assertIs(event.kind, _datatypes.Event.Kind.STOP) - thread.join() - del server - del completion_queue - - _c.shut_down() - - def test_client_credentials(self): - root_certificates = b'Trust starts here. Really.' - private_key = b'This is a really bad private key, yo.' - certificate_chain = b'Trust me! Do I not look trustworty?' - - _c.init() - - client_credentials = _c.ClientCredentials( - None, None, None) - self.assertIsNotNone(client_credentials) - client_credentials = _c.ClientCredentials( - root_certificates, None, None) - self.assertIsNotNone(client_credentials) - client_credentials = _c.ClientCredentials( - None, private_key, certificate_chain) - self.assertIsNotNone(client_credentials) - client_credentials = _c.ClientCredentials( - root_certificates, private_key, certificate_chain) - self.assertIsNotNone(client_credentials) - del client_credentials - - _c.shut_down() - - def test_server_credentials(self): - root_certificates = b'Trust starts here. Really.' - first_private_key = b'This is a really bad private key, yo.' - first_certificate_chain = b'Trust me! Do I not look trustworty?' - second_private_key = b'This is another bad private key, yo.' - second_certificate_chain = b'Look into my eyes; you can totes trust me.' - - _c.init() - - server_credentials = _c.ServerCredentials( - None, ((first_private_key, first_certificate_chain),)) - del server_credentials - server_credentials = _c.ServerCredentials( - root_certificates, ((first_private_key, first_certificate_chain),)) - del server_credentials - server_credentials = _c.ServerCredentials( - root_certificates, - ((first_private_key, first_certificate_chain), - (second_private_key, second_certificate_chain),)) - del server_credentials - with self.assertRaises(TypeError): - _c.ServerCredentials( - root_certificates, first_private_key, second_certificate_chain) - - _c.shut_down() - - @unittest.skip('TODO(nathaniel): find and use real-enough test credentials') - def test_secure_server(self): - _c.init() - - server_credentials = _c.ServerCredentials( - 'root certificate', (('private key', 'certificate chain'),)) - - completion_queue = _c.CompletionQueue() - server = _c.Server(completion_queue, server_credentials) - server.add_http2_addr('[::]:0') - server.start() - thread = threading.Thread(target=completion_queue.get, args=(_FUTURE,)) - thread.start() - time.sleep(1) - server.stop() - completion_queue.stop() - for _ in range(_IDEMPOTENCE_DEMONSTRATION): - event = completion_queue.get(time.time() + _TIMEOUT) - self.assertIs(event.kind, _datatypes.Event.Kind.STOP) - thread.join() - del server - del completion_queue + def testChannelUpDown(self): + channel = _c.Channel('[::]:0', []) + del channel - _c.shut_down() + def testSecureChannelUpDown(self): + channel = _c.Channel('[::]:0', [], _c.ClientCredentials.fake_transport_security()) + del channel if __name__ == '__main__': diff --git a/src/python/src/grpc/_adapter/_call.c b/src/python/src/grpc/_adapter/_call.c deleted file mode 100644 index d833268fc9d..00000000000 --- a/src/python/src/grpc/_adapter/_call.c +++ /dev/null @@ -1,438 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "grpc/_adapter/_call.h" - -#include -#include -#include -#include - -#include "grpc/_adapter/_channel.h" -#include "grpc/_adapter/_completion_queue.h" -#include "grpc/_adapter/_error.h" -#include "grpc/_adapter/_tag.h" - -static PyObject *pygrpc_call_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - Call *self = (Call *)type->tp_alloc(type, 0); - Channel *channel; - CompletionQueue *completion_queue; - const char *method; - const char *host; - double deadline; - static char *kwlist[] = {"channel", "completion_queue", - "method", "host", "deadline", NULL}; - - if (!PyArg_ParseTupleAndKeywords( - args, kwds, "O!O!ssd:Call", kwlist, - &pygrpc_ChannelType, &channel, - &pygrpc_CompletionQueueType, &completion_queue, - &method, &host, &deadline)) { - return NULL; - } - - /* TODO(nathaniel): Hoist the gpr_timespec <-> PyFloat arithmetic into its own - * function with its own test coverage. - */ - self->c_call = grpc_channel_create_call( - channel->c_channel, completion_queue->c_completion_queue, method, host, - gpr_time_from_nanos(deadline * GPR_NS_PER_SEC)); - self->completion_queue = completion_queue; - Py_INCREF(self->completion_queue); - self->channel = channel; - Py_INCREF(self->channel); - grpc_call_details_init(&self->call_details); - grpc_metadata_array_init(&self->recv_metadata); - grpc_metadata_array_init(&self->recv_trailing_metadata); - self->send_metadata = NULL; - self->send_metadata_count = 0; - self->send_trailing_metadata = NULL; - self->send_trailing_metadata_count = 0; - self->send_message = NULL; - self->recv_message = NULL; - self->adding_to_trailing = 0; - - return (PyObject *)self; -} - -static void pygrpc_call_dealloc(Call *self) { - if (self->c_call != NULL) { - grpc_call_destroy(self->c_call); - } - Py_XDECREF(self->completion_queue); - Py_XDECREF(self->channel); - Py_XDECREF(self->server); - grpc_call_details_destroy(&self->call_details); - grpc_metadata_array_destroy(&self->recv_metadata); - grpc_metadata_array_destroy(&self->recv_trailing_metadata); - if (self->send_message) { - grpc_byte_buffer_destroy(self->send_message); - } - if (self->recv_message) { - grpc_byte_buffer_destroy(self->recv_message); - } - gpr_free(self->status_details); - gpr_free(self->send_metadata); - gpr_free(self->send_trailing_metadata); - self->ob_type->tp_free((PyObject *)self); -} - -static const PyObject *pygrpc_call_invoke(Call *self, PyObject *args) { - PyObject *completion_queue; - PyObject *metadata_tag; - PyObject *finish_tag; - grpc_call_error call_error; - const PyObject *result; - pygrpc_tag *c_init_metadata_tag; - pygrpc_tag *c_metadata_tag; - pygrpc_tag *c_finish_tag; - grpc_op send_initial_metadata; - grpc_op recv_initial_metadata; - grpc_op recv_status_on_client; - - if (!(PyArg_ParseTuple(args, "O!OO:invoke", &pygrpc_CompletionQueueType, - &completion_queue, &metadata_tag, &finish_tag))) { - return NULL; - } - send_initial_metadata.op = GRPC_OP_SEND_INITIAL_METADATA; - send_initial_metadata.data.send_initial_metadata.metadata = self->send_metadata; - send_initial_metadata.data.send_initial_metadata.count = self->send_metadata_count; - recv_initial_metadata.op = GRPC_OP_RECV_INITIAL_METADATA; - recv_initial_metadata.data.recv_initial_metadata = &self->recv_metadata; - recv_status_on_client.op = GRPC_OP_RECV_STATUS_ON_CLIENT; - recv_status_on_client.data.recv_status_on_client.trailing_metadata = &self->recv_trailing_metadata; - recv_status_on_client.data.recv_status_on_client.status = &self->status; - recv_status_on_client.data.recv_status_on_client.status_details = &self->status_details; - recv_status_on_client.data.recv_status_on_client.status_details_capacity = &self->status_details_capacity; - c_init_metadata_tag = pygrpc_tag_new(PYGRPC_INITIAL_METADATA, NULL, self); - c_metadata_tag = pygrpc_tag_new(PYGRPC_CLIENT_METADATA_READ, metadata_tag, self); - c_finish_tag = pygrpc_tag_new(PYGRPC_FINISHED_CLIENT, finish_tag, self); - - call_error = grpc_call_start_batch(self->c_call, &send_initial_metadata, 1, c_init_metadata_tag); - result = pygrpc_translate_call_error(call_error); - if (result == NULL) { - pygrpc_tag_destroy(c_init_metadata_tag); - pygrpc_tag_destroy(c_metadata_tag); - pygrpc_tag_destroy(c_finish_tag); - return result; - } - call_error = grpc_call_start_batch(self->c_call, &recv_initial_metadata, 1, c_metadata_tag); - result = pygrpc_translate_call_error(call_error); - if (result == NULL) { - pygrpc_tag_destroy(c_metadata_tag); - pygrpc_tag_destroy(c_finish_tag); - return result; - } - call_error = grpc_call_start_batch(self->c_call, &recv_status_on_client, 1, c_finish_tag); - result = pygrpc_translate_call_error(call_error); - if (result == NULL) { - pygrpc_tag_destroy(c_finish_tag); - return result; - } - - return result; -} - -static const PyObject *pygrpc_call_write(Call *self, PyObject *args) { - const char *bytes; - int length; - PyObject *tag; - gpr_slice slice; - grpc_byte_buffer *byte_buffer; - grpc_call_error call_error; - const PyObject *result; - pygrpc_tag *c_tag; - grpc_op op; - - if (!(PyArg_ParseTuple(args, "s#O:write", &bytes, &length, &tag))) { - return NULL; - } - c_tag = pygrpc_tag_new(PYGRPC_WRITE_ACCEPTED, tag, self); - - slice = gpr_slice_from_copied_buffer(bytes, length); - byte_buffer = grpc_byte_buffer_create(&slice, 1); - gpr_slice_unref(slice); - - if (self->send_message) { - grpc_byte_buffer_destroy(self->send_message); - } - self->send_message = byte_buffer; - - op.op = GRPC_OP_SEND_MESSAGE; - op.data.send_message = self->send_message; - - call_error = grpc_call_start_batch(self->c_call, &op, 1, c_tag); - - result = pygrpc_translate_call_error(call_error); - if (result == NULL) { - pygrpc_tag_destroy(c_tag); - } - return result; -} - -static const PyObject *pygrpc_call_complete(Call *self, PyObject *tag) { - grpc_call_error call_error; - const PyObject *result; - pygrpc_tag *c_tag = pygrpc_tag_new(PYGRPC_FINISH_ACCEPTED, tag, self); - grpc_op op; - - op.op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - - call_error = grpc_call_start_batch(self->c_call, &op, 1, c_tag); - - result = pygrpc_translate_call_error(call_error); - if (result == NULL) { - pygrpc_tag_destroy(c_tag); - } - return result; -} - -static const PyObject *pygrpc_call_accept(Call *self, PyObject *args) { - PyObject *completion_queue; - PyObject *tag; - grpc_call_error call_error; - const PyObject *result; - pygrpc_tag *c_tag; - grpc_op op; - - if (!(PyArg_ParseTuple(args, "O!O:accept", &pygrpc_CompletionQueueType, - &completion_queue, &tag))) { - return NULL; - } - - op.op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op.data.recv_close_on_server.cancelled = &self->cancelled; - c_tag = pygrpc_tag_new(PYGRPC_FINISHED_SERVER, tag, self); - - call_error = grpc_call_start_batch(self->c_call, &op, 1, c_tag); - result = pygrpc_translate_call_error(call_error); - if (result == NULL) { - pygrpc_tag_destroy(c_tag); - } - return result; -} - -static const PyObject *pygrpc_call_add_metadata(Call *self, PyObject *args) { - const char* key = NULL; - const char* value = NULL; - int value_length = 0; - grpc_metadata metadata; - if (!PyArg_ParseTuple(args, "ss#", &key, &value, &value_length)) { - return NULL; - } - metadata.key = key; - metadata.value = value; - metadata.value_length = value_length; - if (self->adding_to_trailing) { - self->send_trailing_metadata = gpr_realloc(self->send_trailing_metadata, (self->send_trailing_metadata_count + 1) * sizeof(grpc_metadata)); - self->send_trailing_metadata[self->send_trailing_metadata_count] = metadata; - self->send_trailing_metadata_count = self->send_trailing_metadata_count + 1; - } else { - self->send_metadata = gpr_realloc(self->send_metadata, (self->send_metadata_count + 1) * sizeof(grpc_metadata)); - self->send_metadata[self->send_metadata_count] = metadata; - self->send_metadata_count = self->send_metadata_count + 1; - } - return pygrpc_translate_call_error(GRPC_CALL_OK); -} - -static const PyObject *pygrpc_call_premetadata(Call *self) { - grpc_op op; - grpc_call_error call_error; - const PyObject *result; - pygrpc_tag *c_tag = pygrpc_tag_new(PYGRPC_INITIAL_METADATA, NULL, self); - op.op = GRPC_OP_SEND_INITIAL_METADATA; - op.data.send_initial_metadata.metadata = self->send_metadata; - op.data.send_initial_metadata.count = self->send_metadata_count; - self->adding_to_trailing = 1; - - call_error = grpc_call_start_batch(self->c_call, &op, 1, c_tag); - result = pygrpc_translate_call_error(call_error); - if (result == NULL) { - pygrpc_tag_destroy(c_tag); - } - return result; -} - -static const PyObject *pygrpc_call_read(Call *self, PyObject *tag) { - grpc_op op; - grpc_call_error call_error; - const PyObject *result; - pygrpc_tag *c_tag = pygrpc_tag_new(PYGRPC_READ, tag, self); - - op.op = GRPC_OP_RECV_MESSAGE; - if (self->recv_message) { - grpc_byte_buffer_destroy(self->recv_message); - self->recv_message = NULL; - } - op.data.recv_message = &self->recv_message; - call_error = grpc_call_start_batch(self->c_call, &op, 1, c_tag); - result = pygrpc_translate_call_error(call_error); - if (result == NULL) { - pygrpc_tag_destroy(c_tag); - } - return result; -} - -static const PyObject *pygrpc_call_status(Call *self, PyObject *args) { - PyObject *status; - PyObject *code; - PyObject *details; - PyObject *tag; - grpc_status_code c_code; - char *c_message; - grpc_call_error call_error; - const PyObject *result; - pygrpc_tag *c_tag; - grpc_op op; - - if (!(PyArg_ParseTuple(args, "OO:status", &status, &tag))) { - return NULL; - } - c_tag = pygrpc_tag_new(PYGRPC_FINISH_ACCEPTED, tag, self); - - code = PyObject_GetAttrString(status, "code"); - if (code == NULL) { - return NULL; - } - details = PyObject_GetAttrString(status, "details"); - if (details == NULL) { - Py_DECREF(code); - return NULL; - } - c_code = PyInt_AsLong(code); - Py_DECREF(code); - if (c_code == -1 && PyErr_Occurred()) { - Py_DECREF(details); - return NULL; - } - c_message = PyBytes_AsString(details); - Py_DECREF(details); - if (c_message == NULL) { - return NULL; - } - if (self->status_details) { - gpr_free(self->status_details); - } - self->status_details = gpr_malloc(strlen(c_message)+1); - strcpy(self->status_details, c_message); - op.op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op.data.send_status_from_server.trailing_metadata_count = self->send_trailing_metadata_count; - op.data.send_status_from_server.trailing_metadata = self->send_trailing_metadata; - op.data.send_status_from_server.status = c_code; - op.data.send_status_from_server.status_details = self->status_details; - - call_error = grpc_call_start_batch(self->c_call, &op, 1, c_tag); - result = pygrpc_translate_call_error(call_error); - if (result == NULL) { - pygrpc_tag_destroy(c_tag); - } - return result; -} - -static const PyObject *pygrpc_call_cancel(Call *self) { - return pygrpc_translate_call_error(grpc_call_cancel(self->c_call)); -} - -static PyMethodDef methods[] = { - {"invoke", (PyCFunction)pygrpc_call_invoke, METH_VARARGS, - "Invoke this call."}, - {"write", (PyCFunction)pygrpc_call_write, METH_VARARGS, - "Write bytes to this call."}, - {"complete", (PyCFunction)pygrpc_call_complete, METH_O, - "Complete writes to this call."}, - {"accept", (PyCFunction)pygrpc_call_accept, METH_VARARGS, "Accept an RPC."}, - {"add_metadata", (PyCFunction)pygrpc_call_add_metadata, METH_VARARGS, - "Add metadata to the call. May not be called after invoke on the client " - "side. On the server side: when called before premetadata it provides " - "'leading' metadata, when called after premetadata but before status it " - "provides 'trailing metadata'; may not be called after status."}, - {"premetadata", (PyCFunction)pygrpc_call_premetadata, METH_VARARGS, - "Indicate the end of leading metadata in the response."}, - {"read", (PyCFunction)pygrpc_call_read, METH_O, - "Read bytes from this call."}, - {"status", (PyCFunction)pygrpc_call_status, METH_VARARGS, - "Report this call's status."}, - {"cancel", (PyCFunction)pygrpc_call_cancel, METH_NOARGS, - "Cancel this call."}, - {NULL}}; - -PyTypeObject pygrpc_CallType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_grpc.Call", /*tp_name*/ - sizeof(Call), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)pygrpc_call_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - "Wrapping of grpc_call.", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - pygrpc_call_new, /* tp_new */ -}; - -int pygrpc_add_call(PyObject *module) { - if (PyType_Ready(&pygrpc_CallType) < 0) { - return -1; - } - if (PyModule_AddObject(module, "Call", (PyObject *)&pygrpc_CallType) == -1) { - return -1; - } - return 0; -} diff --git a/src/python/src/grpc/_adapter/_call.h b/src/python/src/grpc/_adapter/_call.h deleted file mode 100644 index b4cf9d7ec99..00000000000 --- a/src/python/src/grpc/_adapter/_call.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef _ADAPTER__CALL_H_ -#define _ADAPTER__CALL_H_ - -#include -#include - -#include "grpc/_adapter/_completion_queue.h" -#include "grpc/_adapter/_channel.h" -#include "grpc/_adapter/_server.h" - -typedef struct { - PyObject_HEAD - - CompletionQueue *completion_queue; - Channel *channel; - Server *server; - - /* Legacy state. */ - grpc_call_details call_details; - grpc_metadata_array recv_metadata; - grpc_metadata_array recv_trailing_metadata; - grpc_metadata *send_metadata; - size_t send_metadata_count; - grpc_metadata *send_trailing_metadata; - size_t send_trailing_metadata_count; - int adding_to_trailing; - - grpc_byte_buffer *send_message; - grpc_byte_buffer *recv_message; - - grpc_status_code status; - char *status_details; - size_t status_details_capacity; - - int cancelled; - - grpc_call *c_call; -} Call; - -extern PyTypeObject pygrpc_CallType; - -int pygrpc_add_call(PyObject *module); - -#endif /* _ADAPTER__CALL_H_ */ diff --git a/src/python/src/grpc/_adapter/_channel.c b/src/python/src/grpc/_adapter/_channel.c deleted file mode 100644 index 6be8f1c3643..00000000000 --- a/src/python/src/grpc/_adapter/_channel.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "grpc/_adapter/_channel.h" - -#include -#include -#include - -#include "grpc/_adapter/_client_credentials.h" - -static int pygrpc_channel_init(Channel *self, PyObject *args, PyObject *kwds) { - const char *hostport; - PyObject *client_credentials; - char *server_host_override = NULL; - static char *kwlist[] = {"hostport", "client_credentials", - "server_host_override", NULL}; - grpc_arg server_host_override_arg; - grpc_channel_args channel_args; - - if (!(PyArg_ParseTupleAndKeywords(args, kwds, "sO|z:Channel", kwlist, - &hostport, &client_credentials, - &server_host_override))) { - return -1; - } - if (client_credentials == Py_None) { - self->c_channel = grpc_channel_create(hostport, NULL); - return 0; - } else { - if (server_host_override == NULL) { - self->c_channel = grpc_secure_channel_create( - ((ClientCredentials *)client_credentials)->c_client_credentials, - hostport, NULL); - } else { - server_host_override_arg.type = GRPC_ARG_STRING; - server_host_override_arg.key = GRPC_SSL_TARGET_NAME_OVERRIDE_ARG; - server_host_override_arg.value.string = server_host_override; - channel_args.num_args = 1; - channel_args.args = &server_host_override_arg; - self->c_channel = grpc_secure_channel_create( - ((ClientCredentials *)client_credentials)->c_client_credentials, - hostport, &channel_args); - } - return 0; - } -} - -static void pygrpc_channel_dealloc(Channel *self) { - if (self->c_channel != NULL) { - grpc_channel_destroy(self->c_channel); - } - self->ob_type->tp_free((PyObject *)self); -} - -PyTypeObject pygrpc_ChannelType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_grpc.Channel", /*tp_name*/ - sizeof(Channel), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)pygrpc_channel_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - "Wrapping of grpc_channel.", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)pygrpc_channel_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ -}; - -int pygrpc_add_channel(PyObject *module) { - if (PyType_Ready(&pygrpc_ChannelType) < 0) { - return -1; - } - if (PyModule_AddObject(module, "Channel", (PyObject *)&pygrpc_ChannelType) == - -1) { - return -1; - } - return 0; -} diff --git a/src/python/src/grpc/_adapter/_channel.h b/src/python/src/grpc/_adapter/_channel.h deleted file mode 100644 index 65894939a23..00000000000 --- a/src/python/src/grpc/_adapter/_channel.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef _ADAPTER__CHANNEL_H_ -#define _ADAPTER__CHANNEL_H_ - -#include -#include - -typedef struct { - PyObject_HEAD - grpc_channel *c_channel; -} Channel; - -extern PyTypeObject pygrpc_ChannelType; - -int pygrpc_add_channel(PyObject *module); - -#endif /* _ADAPTER__CHANNEL_H_ */ diff --git a/src/python/src/grpc/_adapter/_client_credentials.c b/src/python/src/grpc/_adapter/_client_credentials.c deleted file mode 100644 index e8ccff8d17d..00000000000 --- a/src/python/src/grpc/_adapter/_client_credentials.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "grpc/_adapter/_client_credentials.h" - -#include -#include -#include - -static int pygrpc_client_credentials_init(ClientCredentials *self, - PyObject *args, PyObject *kwds) { - char *root_certificates; - grpc_ssl_pem_key_cert_pair key_certificate_pair; - static char *kwlist[] = {"root_certificates", "private_key", - "certificate_chain", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "zzz:ClientCredentials", kwlist, - &root_certificates, - &key_certificate_pair.private_key, - &key_certificate_pair.cert_chain)) { - return -1; - } - - if (key_certificate_pair.private_key != NULL && key_certificate_pair.cert_chain != NULL) { - self->c_client_credentials = - grpc_ssl_credentials_create(root_certificates, &key_certificate_pair); - } else { - self->c_client_credentials = - grpc_ssl_credentials_create(root_certificates, NULL); - } - return 0; -} - -static void pygrpc_client_credentials_dealloc(ClientCredentials *self) { - if (self->c_client_credentials != NULL) { - grpc_credentials_release(self->c_client_credentials); - } - self->ob_type->tp_free((PyObject *)self); -} - -PyTypeObject pygrpc_ClientCredentialsType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_grpc.ClientCredencials", /*tp_name*/ - sizeof(ClientCredentials), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)pygrpc_client_credentials_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - "Wrapping of grpc_credentials.", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)pygrpc_client_credentials_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ -}; - -int pygrpc_add_client_credentials(PyObject *module) { - if (PyType_Ready(&pygrpc_ClientCredentialsType) < 0) { - return -1; - } - if (PyModule_AddObject(module, "ClientCredentials", - (PyObject *)&pygrpc_ClientCredentialsType) == -1) { - return -1; - } - return 0; -} diff --git a/src/python/src/grpc/_adapter/_client_credentials.h b/src/python/src/grpc/_adapter/_client_credentials.h deleted file mode 100644 index fe04016d20c..00000000000 --- a/src/python/src/grpc/_adapter/_client_credentials.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef _ADAPTER__CLIENT_CREDENTIALS_H_ -#define _ADAPTER__CLIENT_CREDENTIALS_H_ - -#include -#include - -typedef struct { - PyObject_HEAD - grpc_credentials *c_client_credentials; -} ClientCredentials; - -extern PyTypeObject pygrpc_ClientCredentialsType; - -int pygrpc_add_client_credentials(PyObject *module); - -#endif /* _ADAPTER__CLIENT_CREDENTIALS_H_ */ diff --git a/src/python/src/grpc/_adapter/_completion_queue.c b/src/python/src/grpc/_adapter/_completion_queue.c deleted file mode 100644 index 97828e67ad7..00000000000 --- a/src/python/src/grpc/_adapter/_completion_queue.c +++ /dev/null @@ -1,653 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "grpc/_adapter/_completion_queue.h" - -#include -#include -#include - -#include "grpc/_adapter/_call.h" -#include "grpc/_adapter/_tag.h" - -static PyObject *status_class; -static PyObject *service_acceptance_class; -static PyObject *event_class; - -static PyObject *ok_status_code; -static PyObject *cancelled_status_code; -static PyObject *unknown_status_code; -static PyObject *invalid_argument_status_code; -static PyObject *expired_status_code; -static PyObject *not_found_status_code; -static PyObject *already_exists_status_code; -static PyObject *permission_denied_status_code; -static PyObject *unauthenticated_status_code; -static PyObject *resource_exhausted_status_code; -static PyObject *failed_precondition_status_code; -static PyObject *aborted_status_code; -static PyObject *out_of_range_status_code; -static PyObject *unimplemented_status_code; -static PyObject *internal_error_status_code; -static PyObject *unavailable_status_code; -static PyObject *data_loss_status_code; - -static PyObject *stop_event_kind; -static PyObject *write_event_kind; -static PyObject *complete_event_kind; -static PyObject *service_event_kind; -static PyObject *read_event_kind; -static PyObject *metadata_event_kind; -static PyObject *finish_event_kind; - -static PyObject *pygrpc_as_py_time(gpr_timespec *timespec) { - return PyFloat_FromDouble( - timespec->tv_sec + ((double)timespec->tv_nsec) / 1.0E9); -} - -static PyObject *pygrpc_status_code(grpc_status_code c_status_code) { - switch (c_status_code) { - case GRPC_STATUS_OK: - return ok_status_code; - case GRPC_STATUS_CANCELLED: - return cancelled_status_code; - case GRPC_STATUS_UNKNOWN: - return unknown_status_code; - case GRPC_STATUS_INVALID_ARGUMENT: - return invalid_argument_status_code; - case GRPC_STATUS_DEADLINE_EXCEEDED: - return expired_status_code; - case GRPC_STATUS_NOT_FOUND: - return not_found_status_code; - case GRPC_STATUS_ALREADY_EXISTS: - return already_exists_status_code; - case GRPC_STATUS_PERMISSION_DENIED: - return permission_denied_status_code; - case GRPC_STATUS_UNAUTHENTICATED: - return unauthenticated_status_code; - case GRPC_STATUS_RESOURCE_EXHAUSTED: - return resource_exhausted_status_code; - case GRPC_STATUS_FAILED_PRECONDITION: - return failed_precondition_status_code; - case GRPC_STATUS_ABORTED: - return aborted_status_code; - case GRPC_STATUS_OUT_OF_RANGE: - return out_of_range_status_code; - case GRPC_STATUS_UNIMPLEMENTED: - return unimplemented_status_code; - case GRPC_STATUS_INTERNAL: - return internal_error_status_code; - case GRPC_STATUS_UNAVAILABLE: - return unavailable_status_code; - case GRPC_STATUS_DATA_LOSS: - return data_loss_status_code; - default: - return NULL; - } -} - -static PyObject *pygrpc_metadata_collection_get( - grpc_metadata *metadata_elements, size_t count) { - PyObject *metadata = PyList_New(count); - size_t i; - for (i = 0; i < count; ++i) { - grpc_metadata elem = metadata_elements[i]; - PyObject *key = PyString_FromString(elem.key); - PyObject *value = PyString_FromStringAndSize(elem.value, elem.value_length); - PyObject* kvp = PyTuple_Pack(2, key, value); - /* n.b. PyList_SetItem *steals* a reference to the set element. */ - PyList_SetItem(metadata, i, kvp); - Py_DECREF(key); - Py_DECREF(value); - } - return metadata; -} - -static PyObject *pygrpc_stop_event_args(grpc_event *c_event) { - return PyTuple_Pack(8, stop_event_kind, Py_None, Py_None, Py_None, - Py_None, Py_None, Py_None, Py_None); -} - -static PyObject *pygrpc_write_event_args(grpc_event *c_event) { - pygrpc_tag *tag = (pygrpc_tag *)(c_event->tag); - PyObject *user_tag = tag->user_tag; - PyObject *write_accepted = Py_True; - return PyTuple_Pack(8, write_event_kind, user_tag, - write_accepted, Py_None, Py_None, Py_None, Py_None, - Py_None); -} - -static PyObject *pygrpc_complete_event_args(grpc_event *c_event) { - pygrpc_tag *tag = (pygrpc_tag *)(c_event->tag); - PyObject *user_tag = tag->user_tag; - PyObject *complete_accepted = Py_True; - return PyTuple_Pack(8, complete_event_kind, user_tag, - Py_None, complete_accepted, Py_None, Py_None, Py_None, - Py_None); -} - -static PyObject *pygrpc_service_event_args(grpc_event *c_event) { - pygrpc_tag *tag = (pygrpc_tag *)(c_event->tag); - PyObject *user_tag = tag->user_tag; - if (tag->call->call_details.method == NULL) { - return PyTuple_Pack( - 8, service_event_kind, user_tag, Py_None, Py_None, Py_None, Py_None, - Py_None, Py_None); - } else { - PyObject *method = NULL; - PyObject *host = NULL; - PyObject *service_deadline = NULL; - PyObject *service_acceptance = NULL; - PyObject *metadata = NULL; - PyObject *event_args = NULL; - - method = PyBytes_FromString(tag->call->call_details.method); - if (method == NULL) { - goto error; - } - host = PyBytes_FromString(tag->call->call_details.host); - if (host == NULL) { - goto error; - } - service_deadline = - pygrpc_as_py_time(&tag->call->call_details.deadline); - if (service_deadline == NULL) { - goto error; - } - - service_acceptance = - PyObject_CallFunctionObjArgs(service_acceptance_class, tag->call, - method, host, service_deadline, NULL); - if (service_acceptance == NULL) { - goto error; - } - - metadata = pygrpc_metadata_collection_get( - tag->call->recv_metadata.metadata, - tag->call->recv_metadata.count); - event_args = PyTuple_Pack(8, service_event_kind, - user_tag, Py_None, Py_None, - service_acceptance, Py_None, Py_None, - metadata); - - Py_DECREF(service_acceptance); - Py_DECREF(metadata); -error: - Py_XDECREF(method); - Py_XDECREF(host); - Py_XDECREF(service_deadline); - - return event_args; - } -} - -static PyObject *pygrpc_read_event_args(grpc_event *c_event) { - pygrpc_tag *tag = (pygrpc_tag *)(c_event->tag); - PyObject *user_tag = tag->user_tag; - if (tag->call->recv_message == NULL) { - return PyTuple_Pack(8, read_event_kind, user_tag, - Py_None, Py_None, Py_None, Py_None, Py_None, Py_None); - } else { - size_t length; - size_t offset; - grpc_byte_buffer_reader *reader; - gpr_slice slice; - char *c_bytes; - PyObject *bytes; - PyObject *event_args; - - length = grpc_byte_buffer_length(tag->call->recv_message); - reader = grpc_byte_buffer_reader_create(tag->call->recv_message); - c_bytes = gpr_malloc(length); - offset = 0; - while (grpc_byte_buffer_reader_next(reader, &slice)) { - memcpy(c_bytes + offset, GPR_SLICE_START_PTR(slice), - GPR_SLICE_LENGTH(slice)); - offset += GPR_SLICE_LENGTH(slice); - } - grpc_byte_buffer_reader_destroy(reader); - bytes = PyBytes_FromStringAndSize(c_bytes, length); - gpr_free(c_bytes); - if (bytes == NULL) { - return NULL; - } - event_args = PyTuple_Pack(8, read_event_kind, user_tag, - Py_None, Py_None, Py_None, bytes, Py_None, - Py_None); - Py_DECREF(bytes); - return event_args; - } -} - -static PyObject *pygrpc_metadata_event_args(grpc_event *c_event) { - pygrpc_tag *tag = (pygrpc_tag *)(c_event->tag); - PyObject *user_tag = tag->user_tag; - PyObject *metadata = pygrpc_metadata_collection_get( - tag->call->recv_metadata.metadata, - tag->call->recv_metadata.count); - PyObject* result = PyTuple_Pack( - 8, metadata_event_kind, user_tag, Py_None, Py_None, - Py_None, Py_None, Py_None, metadata); - Py_DECREF(metadata); - return result; -} - -static PyObject *pygrpc_finished_server_event_args(grpc_event *c_event) { - PyObject *code; - PyObject *details; - PyObject *status; - PyObject *event_args; - pygrpc_tag *tag = (pygrpc_tag *)(c_event->tag); - PyObject *user_tag = tag->user_tag; - - code = pygrpc_status_code(tag->call->cancelled ? GRPC_STATUS_CANCELLED : GRPC_STATUS_OK); - if (code == NULL) { - PyErr_SetString(PyExc_RuntimeError, "Unrecognized status code!"); - return NULL; - } - details = PyBytes_FromString(""); - if (details == NULL) { - return NULL; - } - status = PyObject_CallFunctionObjArgs(status_class, code, details, NULL); - Py_DECREF(details); - if (status == NULL) { - return NULL; - } - event_args = PyTuple_Pack(8, finish_event_kind, user_tag, - Py_None, Py_None, Py_None, Py_None, status, - Py_None); - Py_DECREF(status); - return event_args; -} - -static PyObject *pygrpc_finished_client_event_args(grpc_event *c_event) { - PyObject *code; - PyObject *details; - PyObject *status; - PyObject *event_args; - PyObject *metadata; - pygrpc_tag *tag = (pygrpc_tag *)(c_event->tag); - PyObject *user_tag = tag->user_tag; - - code = pygrpc_status_code(tag->call->status); - if (code == NULL) { - PyErr_SetString(PyExc_RuntimeError, "Unrecognized status code!"); - return NULL; - } - if (tag->call->status_details == NULL) { - details = PyBytes_FromString(""); - } else { - details = PyBytes_FromString(tag->call->status_details); - } - if (details == NULL) { - return NULL; - } - status = PyObject_CallFunctionObjArgs(status_class, code, details, NULL); - Py_DECREF(details); - if (status == NULL) { - return NULL; - } - metadata = pygrpc_metadata_collection_get( - tag->call->recv_trailing_metadata.metadata, - tag->call->recv_trailing_metadata.count); - event_args = PyTuple_Pack(8, finish_event_kind, user_tag, - Py_None, Py_None, Py_None, Py_None, status, - metadata); - Py_DECREF(status); - Py_DECREF(metadata); - return event_args; -} - -static int pygrpc_completion_queue_init(CompletionQueue *self, PyObject *args, - PyObject *kwds) { - static char *kwlist[] = {NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, ":CompletionQueue", kwlist)) { - return -1; - } - self->c_completion_queue = grpc_completion_queue_create(); - return 0; -} - -static void pygrpc_completion_queue_dealloc(CompletionQueue *self) { - grpc_completion_queue_destroy(self->c_completion_queue); - self->ob_type->tp_free((PyObject *)self); -} - -static PyObject *pygrpc_completion_queue_get(CompletionQueue *self, - PyObject *args) { - PyObject *deadline; - double double_deadline; - gpr_timespec deadline_timespec; - grpc_event c_event; - - PyObject *event_args; - PyObject *event; - - pygrpc_tag *tag; - - if (!(PyArg_ParseTuple(args, "O:get", &deadline))) { - return NULL; - } - - if (deadline == Py_None) { - deadline_timespec = gpr_inf_future; - } else { - double_deadline = PyFloat_AsDouble(deadline); - if (PyErr_Occurred()) { - return NULL; - } - deadline_timespec = gpr_time_from_nanos((long)(double_deadline * 1.0E9)); - } - - /* TODO(nathaniel): Suppress clang-format in this block and remove the - unnecessary and unPythonic semicolons trailing the _ALLOW_THREADS macros. - (Right now clang-format only understands //-demarcated suppressions.) */ - Py_BEGIN_ALLOW_THREADS; - c_event = - grpc_completion_queue_next(self->c_completion_queue, deadline_timespec); - Py_END_ALLOW_THREADS; - - tag = (pygrpc_tag *)c_event.tag; - - switch (c_event.type) { - case GRPC_QUEUE_TIMEOUT: - Py_RETURN_NONE; - break; - case GRPC_QUEUE_SHUTDOWN: - event_args = pygrpc_stop_event_args(&c_event); - break; - case GRPC_OP_COMPLETE: { - if (!tag) { - PyErr_SetString(PyExc_Exception, "Unrecognized event type!"); - return NULL; - } - switch (tag->type) { - case PYGRPC_INITIAL_METADATA: - if (tag) { - pygrpc_tag_destroy(tag); - } - return pygrpc_completion_queue_get(self, args); - case PYGRPC_WRITE_ACCEPTED: - event_args = pygrpc_write_event_args(&c_event); - break; - case PYGRPC_FINISH_ACCEPTED: - event_args = pygrpc_complete_event_args(&c_event); - break; - case PYGRPC_SERVER_RPC_NEW: - event_args = pygrpc_service_event_args(&c_event); - break; - case PYGRPC_READ: - event_args = pygrpc_read_event_args(&c_event); - break; - case PYGRPC_CLIENT_METADATA_READ: - event_args = pygrpc_metadata_event_args(&c_event); - break; - case PYGRPC_FINISHED_CLIENT: - event_args = pygrpc_finished_client_event_args(&c_event); - break; - case PYGRPC_FINISHED_SERVER: - event_args = pygrpc_finished_server_event_args(&c_event); - break; - default: - PyErr_SetString(PyExc_Exception, "Unrecognized op event type!"); - return NULL; - } - break; - } - default: - PyErr_SetString(PyExc_Exception, "Unrecognized event type!"); - return NULL; - } - - if (event_args == NULL) { - return NULL; - } - - event = PyObject_CallObject(event_class, event_args); - - Py_DECREF(event_args); - if (tag) { - pygrpc_tag_destroy(tag); - } - - return event; -} - -static PyObject *pygrpc_completion_queue_stop(CompletionQueue *self) { - grpc_completion_queue_shutdown(self->c_completion_queue); - - Py_RETURN_NONE; -} - -static PyMethodDef methods[] = { - {"get", (PyCFunction)pygrpc_completion_queue_get, METH_VARARGS, - "Get the next event."}, - {"stop", (PyCFunction)pygrpc_completion_queue_stop, METH_NOARGS, - "Stop this completion queue."}, - {NULL}}; - -PyTypeObject pygrpc_CompletionQueueType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_gprc.CompletionQueue", /*tp_name*/ - sizeof(CompletionQueue), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)pygrpc_completion_queue_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - "Wrapping of grpc_completion_queue.", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)pygrpc_completion_queue_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ -}; - -static int pygrpc_get_status_codes(PyObject *datatypes_module) { - PyObject *code_class = PyObject_GetAttrString(datatypes_module, "Code"); - if (code_class == NULL) { - return -1; - } - ok_status_code = PyObject_GetAttrString(code_class, "OK"); - if (ok_status_code == NULL) { - return -1; - } - cancelled_status_code = PyObject_GetAttrString(code_class, "CANCELLED"); - if (cancelled_status_code == NULL) { - return -1; - } - unknown_status_code = PyObject_GetAttrString(code_class, "UNKNOWN"); - if (unknown_status_code == NULL) { - return -1; - } - invalid_argument_status_code = - PyObject_GetAttrString(code_class, "INVALID_ARGUMENT"); - if (invalid_argument_status_code == NULL) { - return -1; - } - expired_status_code = PyObject_GetAttrString(code_class, "EXPIRED"); - if (expired_status_code == NULL) { - return -1; - } - not_found_status_code = PyObject_GetAttrString(code_class, "NOT_FOUND"); - if (not_found_status_code == NULL) { - return -1; - } - already_exists_status_code = - PyObject_GetAttrString(code_class, "ALREADY_EXISTS"); - if (already_exists_status_code == NULL) { - return -1; - } - permission_denied_status_code = - PyObject_GetAttrString(code_class, "PERMISSION_DENIED"); - if (permission_denied_status_code == NULL) { - return -1; - } - unauthenticated_status_code = - PyObject_GetAttrString(code_class, "UNAUTHENTICATED"); - if (unauthenticated_status_code == NULL) { - return -1; - } - resource_exhausted_status_code = - PyObject_GetAttrString(code_class, "RESOURCE_EXHAUSTED"); - if (resource_exhausted_status_code == NULL) { - return -1; - } - failed_precondition_status_code = - PyObject_GetAttrString(code_class, "FAILED_PRECONDITION"); - if (failed_precondition_status_code == NULL) { - return -1; - } - aborted_status_code = PyObject_GetAttrString(code_class, "ABORTED"); - if (aborted_status_code == NULL) { - return -1; - } - out_of_range_status_code = PyObject_GetAttrString(code_class, "OUT_OF_RANGE"); - if (out_of_range_status_code == NULL) { - return -1; - } - unimplemented_status_code = - PyObject_GetAttrString(code_class, "UNIMPLEMENTED"); - if (unimplemented_status_code == NULL) { - return -1; - } - internal_error_status_code = - PyObject_GetAttrString(code_class, "INTERNAL_ERROR"); - if (internal_error_status_code == NULL) { - return -1; - } - unavailable_status_code = PyObject_GetAttrString(code_class, "UNAVAILABLE"); - if (unavailable_status_code == NULL) { - return -1; - } - data_loss_status_code = PyObject_GetAttrString(code_class, "DATA_LOSS"); - if (data_loss_status_code == NULL) { - return -1; - } - Py_DECREF(code_class); - return 0; -} - -static int pygrpc_get_event_kinds(PyObject *event_class) { - PyObject *kind_class = PyObject_GetAttrString(event_class, "Kind"); - if (kind_class == NULL) { - return -1; - } - stop_event_kind = PyObject_GetAttrString(kind_class, "STOP"); - if (stop_event_kind == NULL) { - return -1; - } - write_event_kind = PyObject_GetAttrString(kind_class, "WRITE_ACCEPTED"); - if (write_event_kind == NULL) { - return -1; - } - complete_event_kind = PyObject_GetAttrString(kind_class, "COMPLETE_ACCEPTED"); - if (complete_event_kind == NULL) { - return -1; - } - service_event_kind = PyObject_GetAttrString(kind_class, "SERVICE_ACCEPTED"); - if (service_event_kind == NULL) { - return -1; - } - read_event_kind = PyObject_GetAttrString(kind_class, "READ_ACCEPTED"); - if (read_event_kind == NULL) { - return -1; - } - metadata_event_kind = PyObject_GetAttrString(kind_class, "METADATA_ACCEPTED"); - if (metadata_event_kind == NULL) { - return -1; - } - finish_event_kind = PyObject_GetAttrString(kind_class, "FINISH"); - if (finish_event_kind == NULL) { - return -1; - } - Py_DECREF(kind_class); - return 0; -} - -int pygrpc_add_completion_queue(PyObject *module) { - char *datatypes_module_path = "grpc._adapter._datatypes"; - PyObject *datatypes_module = PyImport_ImportModule(datatypes_module_path); - if (datatypes_module == NULL) { - return -1; - } - status_class = PyObject_GetAttrString(datatypes_module, "Status"); - service_acceptance_class = - PyObject_GetAttrString(datatypes_module, "ServiceAcceptance"); - event_class = PyObject_GetAttrString(datatypes_module, "Event"); - if (status_class == NULL || service_acceptance_class == NULL || - event_class == NULL) { - return -1; - } - if (pygrpc_get_status_codes(datatypes_module) == -1) { - return -1; - } - if (pygrpc_get_event_kinds(event_class) == -1) { - return -1; - } - Py_DECREF(datatypes_module); - - if (PyType_Ready(&pygrpc_CompletionQueueType) < 0) { - return -1; - } - if (PyModule_AddObject(module, "CompletionQueue", - (PyObject *)&pygrpc_CompletionQueueType) == -1) { - return -1; - } - return 0; -} diff --git a/src/python/src/grpc/_adapter/_datatypes.py b/src/python/src/grpc/_adapter/_datatypes.py deleted file mode 100644 index 3b227842432..00000000000 --- a/src/python/src/grpc/_adapter/_datatypes.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Datatypes passed between Python and C code.""" - -import collections -import enum - - -@enum.unique -class Code(enum.IntEnum): - """One Platform error codes (see status.h and codes.proto).""" - - OK = 0 - CANCELLED = 1 - UNKNOWN = 2 - INVALID_ARGUMENT = 3 - EXPIRED = 4 - NOT_FOUND = 5 - ALREADY_EXISTS = 6 - PERMISSION_DENIED = 7 - UNAUTHENTICATED = 16 - RESOURCE_EXHAUSTED = 8 - FAILED_PRECONDITION = 9 - ABORTED = 10 - OUT_OF_RANGE = 11 - UNIMPLEMENTED = 12 - INTERNAL_ERROR = 13 - UNAVAILABLE = 14 - DATA_LOSS = 15 - - -class Status(collections.namedtuple('Status', ['code', 'details'])): - """Describes an RPC's overall status.""" - - -class ServiceAcceptance( - collections.namedtuple( - 'ServiceAcceptance', ['call', 'method', 'host', 'deadline'])): - """Describes an RPC on the service side at the start of service.""" - - -class Event( - collections.namedtuple( - 'Event', - ['kind', 'tag', 'write_accepted', 'complete_accepted', - 'service_acceptance', 'bytes', 'status', 'metadata'])): - """Describes an event emitted from a completion queue.""" - - @enum.unique - class Kind(enum.Enum): - """Describes the kind of an event.""" - - STOP = object() - WRITE_ACCEPTED = object() - COMPLETE_ACCEPTED = object() - SERVICE_ACCEPTED = object() - READ_ACCEPTED = object() - METADATA_ACCEPTED = object() - FINISH = object() diff --git a/src/python/src/grpc/_adapter/_error.c b/src/python/src/grpc/_adapter/_error.c deleted file mode 100644 index a8a1dbc1bbf..00000000000 --- a/src/python/src/grpc/_adapter/_error.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "grpc/_adapter/_error.h" - -#include -#include - -const PyObject *pygrpc_translate_call_error(grpc_call_error call_error) { - switch (call_error) { - case GRPC_CALL_OK: - Py_RETURN_NONE; - case GRPC_CALL_ERROR: - PyErr_SetString(PyExc_Exception, "Defect: unknown defect!"); - return NULL; - case GRPC_CALL_ERROR_NOT_ON_SERVER: - PyErr_SetString(PyExc_Exception, - "Defect: client-only method called on server!"); - return NULL; - case GRPC_CALL_ERROR_NOT_ON_CLIENT: - PyErr_SetString(PyExc_Exception, - "Defect: server-only method called on client!"); - return NULL; - case GRPC_CALL_ERROR_ALREADY_ACCEPTED: - PyErr_SetString(PyExc_Exception, - "Defect: attempted to accept already-accepted call!"); - return NULL; - case GRPC_CALL_ERROR_ALREADY_INVOKED: - PyErr_SetString(PyExc_Exception, - "Defect: attempted to invoke already-invoked call!"); - return NULL; - case GRPC_CALL_ERROR_NOT_INVOKED: - PyErr_SetString(PyExc_Exception, "Defect: Call not yet invoked!"); - return NULL; - case GRPC_CALL_ERROR_ALREADY_FINISHED: - PyErr_SetString(PyExc_Exception, "Defect: Call already finished!"); - return NULL; - case GRPC_CALL_ERROR_TOO_MANY_OPERATIONS: - PyErr_SetString(PyExc_Exception, - "Defect: Attempted extra read or extra write on call!"); - return NULL; - case GRPC_CALL_ERROR_INVALID_FLAGS: - PyErr_SetString(PyExc_Exception, "Defect: invalid flags!"); - return NULL; - default: - PyErr_SetString(PyExc_Exception, "Defect: Unknown call error!"); - return NULL; - } -} diff --git a/src/python/src/grpc/_adapter/_error.h b/src/python/src/grpc/_adapter/_error.h deleted file mode 100644 index 6988b1c95ea..00000000000 --- a/src/python/src/grpc/_adapter/_error.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef _ADAPTER__ERROR_H_ -#define _ADAPTER__ERROR_H_ - -#include -#include - -const PyObject *pygrpc_translate_call_error(grpc_call_error call_error); - -#endif /* _ADAPTER__ERROR_H_ */ diff --git a/src/python/src/grpc/_adapter/_intermediary_low.py b/src/python/src/grpc/_adapter/_intermediary_low.py new file mode 100644 index 00000000000..a6e325c4e5b --- /dev/null +++ b/src/python/src/grpc/_adapter/_intermediary_low.py @@ -0,0 +1,258 @@ +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Temporary old _low-like layer. + +Eases refactoring burden while we overhaul the Python framework. + +Plan: + The layers used to look like: + ... # outside _adapter + fore.py + rear.py # visible outside _adapter + _low + _c + The layers currently look like: + ... # outside _adapter + fore.py + rear.py # visible outside _adapter + _low_intermediary # adapter for new '_low' to old '_low' + _low # new '_low' + _c # new '_c' + We will later remove _low_intermediary after refactoring of fore.py and + rear.py according to the ticket system refactoring and get: + ... # outside _adapter, refactored + fore.py + rear.py # visible outside _adapter, refactored + _low # new '_low' + _c # new '_c' +""" + +import collections +import enum + +from grpc._adapter import _low +from grpc._adapter import _types + +_IGNORE_ME_TAG = object() +Code = _types.StatusCode + + +class Status(collections.namedtuple('Status', ['code', 'details'])): + """Describes an RPC's overall status.""" + + +class ServiceAcceptance( + collections.namedtuple( + 'ServiceAcceptance', ['call', 'method', 'host', 'deadline'])): + """Describes an RPC on the service side at the start of service.""" + + +class Event( + collections.namedtuple( + 'Event', + ['kind', 'tag', 'write_accepted', 'complete_accepted', + 'service_acceptance', 'bytes', 'status', 'metadata'])): + """Describes an event emitted from a completion queue.""" + + @enum.unique + class Kind(enum.Enum): + """Describes the kind of an event.""" + + STOP = object() + WRITE_ACCEPTED = object() + COMPLETE_ACCEPTED = object() + SERVICE_ACCEPTED = object() + READ_ACCEPTED = object() + METADATA_ACCEPTED = object() + FINISH = object() + + +class _TagAdapter(collections.namedtuple('_TagAdapter', [ + 'user_tag', + 'kind' + ])): + pass + + +class Call(object): + """Adapter from old _low.Call interface to new _low.Call.""" + + def __init__(self, channel, completion_queue, method, host, deadline): + self._internal = channel._internal.create_call( + completion_queue._internal, method, host, deadline) + self._metadata = [] + + @staticmethod + def _from_internal(internal): + call = Call.__new__(Call) + call._internal = internal + call._metadata = [] + return call + + def invoke(self, completion_queue, metadata_tag, finish_tag): + err0 = self._internal.start_batch([ + _types.OpArgs.send_initial_metadata(self._metadata) + ], _IGNORE_ME_TAG) + err1 = self._internal.start_batch([ + _types.OpArgs.recv_initial_metadata() + ], _TagAdapter(metadata_tag, Event.Kind.METADATA_ACCEPTED)) + err2 = self._internal.start_batch([ + _types.OpArgs.recv_status_on_client() + ], _TagAdapter(finish_tag, Event.Kind.FINISH)) + return err0 if err0 != _types.CallError.OK else err1 if err1 != _types.CallError.OK else err2 if err2 != _types.CallError.OK else _types.CallError.OK + + def write(self, message, tag): + return self._internal.start_batch([ + _types.OpArgs.send_message(message) + ], _TagAdapter(tag, Event.Kind.WRITE_ACCEPTED)) + + def complete(self, tag): + return self._internal.start_batch([ + _types.OpArgs.send_close_from_client() + ], _TagAdapter(tag, Event.Kind.COMPLETE_ACCEPTED)) + + def accept(self, completion_queue, tag): + return self._internal.start_batch([ + _types.OpArgs.recv_close_on_server() + ], _TagAdapter(tag, Event.Kind.FINISH)) + + def add_metadata(self, key, value): + self._metadata.append((key, value)) + + def premetadata(self): + return self._internal.start_batch([ + _types.OpArgs.send_initial_metadata(self._metadata) + ], _IGNORE_ME_TAG) + self._metadata = [] + + def read(self, tag): + return self._internal.start_batch([ + _types.OpArgs.recv_message() + ], _TagAdapter(tag, Event.Kind.READ_ACCEPTED)) + + def status(self, status, tag): + return self._internal.start_batch([ + _types.OpArgs.send_status_from_server(self._metadata, status.code, status.details) + ], _TagAdapter(tag, Event.Kind.COMPLETE_ACCEPTED)) + + def cancel(self): + return self._internal.cancel() + + +class Channel(object): + """Adapter from old _low.Channel interface to new _low.Channel.""" + + def __init__(self, hostport, client_credentials, server_host_override=None): + args = [] + if server_host_override: + args.append((_types.GrpcChannelArgumentKeys.SSL_TARGET_NAME_OVERRIDE.value, server_host_override)) + creds = None + if client_credentials: + creds = client_credentials._internal + self._internal = _low.Channel(hostport, args, creds) + + +class CompletionQueue(object): + """Adapter from old _low.CompletionQueue interface to new _low.CompletionQueue.""" + + def __init__(self): + self._internal = _low.CompletionQueue() + + def get(self, deadline=None): + if deadline is None: + ev = self._internal.next() + else: + ev = self._internal.next(deadline) + if ev is None: + return None + elif ev.tag is _IGNORE_ME_TAG: + return self.get(deadline) + elif ev.type == _types.EventType.QUEUE_SHUTDOWN: + kind = Event.Kind.STOP + tag = None + write_accepted = None + complete_accepted = None + service_acceptance = None + message_bytes = None + status = None + metadata = None + elif ev.type == _types.EventType.OP_COMPLETE: + kind = ev.tag.kind + tag = ev.tag.user_tag + write_accepted = ev.success if kind == Event.Kind.WRITE_ACCEPTED else None + complete_accepted = ev.success if kind == Event.Kind.COMPLETE_ACCEPTED else None + service_acceptance = ServiceAcceptance(Call._from_internal(ev.call), ev.call_details.method, ev.call_details.host, ev.call_details.deadline) if kind == Event.Kind.SERVICE_ACCEPTED else None + message_bytes = ev.results[0].message if kind == Event.Kind.READ_ACCEPTED else None + status = Status(ev.results[0].status.code, ev.results[0].status.details) if (kind == Event.Kind.FINISH and ev.results[0].status) else Status(_types.StatusCode.CANCELLED if ev.results[0].cancelled else _types.StatusCode.OK, '') if ev.results[0].cancelled is not None else None + metadata = ev.results[0].initial_metadata if (kind in [Event.Kind.SERVICE_ACCEPTED, Event.Kind.METADATA_ACCEPTED]) else (ev.results[0].trailing_metadata if kind == Event.Kind.FINISH else None) + else: + raise RuntimeError('unknown event') + result_ev = Event(kind=kind, tag=tag, write_accepted=write_accepted, complete_accepted=complete_accepted, service_acceptance=service_acceptance, bytes=message_bytes, status=status, metadata=metadata) + return result_ev + + def stop(self): + self._internal.shutdown() + + +class Server(object): + """Adapter from old _low.Server interface to new _low.Server.""" + + def __init__(self, completion_queue): + self._internal = _low.Server(completion_queue._internal, []) + self._internal_cq = completion_queue._internal + + def add_http2_addr(self, addr): + return self._internal.add_http2_port(addr) + + def add_secure_http2_addr(self, addr, server_credentials): + if server_credentials is None: + return self._internal.add_http2_port(addr, None) + else: + return self._internal.add_http2_port(addr, server_credentials._internal) + + def start(self): + return self._internal.start() + + def service(self, tag): + return self._internal.request_call(self._internal_cq, _TagAdapter(tag, Event.Kind.SERVICE_ACCEPTED)) + + def stop(self): + return self._internal.shutdown() + + +class ClientCredentials(object): + """Adapter from old _low.ClientCredentials interface to new _low.ClientCredentials.""" + + def __init__(self, root_certificates, private_key, certificate_chain): + self._internal = _low.ClientCredentials.ssl(root_certificates, private_key, certificate_chain) + + +class ServerCredentials(object): + """Adapter from old _low.ServerCredentials interface to new _low.ServerCredentials.""" + + def __init__(self, root_credentials, pair_sequence): + self._internal = _low.ServerCredentials.ssl(root_credentials, list(pair_sequence)) diff --git a/src/python/src/grpc/_adapter/_intermediary_low_test.py b/src/python/src/grpc/_adapter/_intermediary_low_test.py new file mode 100644 index 00000000000..6ff51c43a69 --- /dev/null +++ b/src/python/src/grpc/_adapter/_intermediary_low_test.py @@ -0,0 +1,421 @@ +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Tests for the old '_low'.""" + +import time +import unittest + +from grpc._adapter import _intermediary_low as _low + +_STREAM_LENGTH = 300 +_TIMEOUT = 5 +_AFTER_DELAY = 2 +_FUTURE = time.time() + 60 * 60 * 24 +_BYTE_SEQUENCE = b'\abcdefghijklmnopqrstuvwxyz0123456789' * 200 +_BYTE_SEQUENCE_SEQUENCE = tuple( + bytes(bytearray((row + column) % 256 for column in range(row))) + for row in range(_STREAM_LENGTH)) + +class LonelyClientTest(unittest.TestCase): + + def testLonelyClient(self): + host = 'nosuchhostexists' + port = 54321 + method = 'test method' + deadline = time.time() + _TIMEOUT + after_deadline = deadline + _AFTER_DELAY + metadata_tag = object() + finish_tag = object() + + completion_queue = _low.CompletionQueue() + channel = _low.Channel('%s:%d' % (host, port), None) + client_call = _low.Call(channel, completion_queue, method, host, deadline) + + client_call.invoke(completion_queue, metadata_tag, finish_tag) + first_event = completion_queue.get(after_deadline) + self.assertIsNotNone(first_event) + second_event = completion_queue.get(after_deadline) + self.assertIsNotNone(second_event) + kinds = [event.kind for event in (first_event, second_event)] + self.assertItemsEqual( + (_low.Event.Kind.METADATA_ACCEPTED, _low.Event.Kind.FINISH), + kinds) + + self.assertIsNone(completion_queue.get(after_deadline)) + + completion_queue.stop() + stop_event = completion_queue.get(_FUTURE) + self.assertEqual(_low.Event.Kind.STOP, stop_event.kind) + + del client_call + del channel + del completion_queue + + +class EchoTest(unittest.TestCase): + + def setUp(self): + self.host = 'localhost' + + self.server_completion_queue = _low.CompletionQueue() + self.server = _low.Server(self.server_completion_queue) + port = self.server.add_http2_addr('[::]:0') + self.server.start() + + self.client_completion_queue = _low.CompletionQueue() + self.channel = _low.Channel('%s:%d' % (self.host, port), None) + + def tearDown(self): + self.server.stop() + # NOTE(nathaniel): Yep, this is weird; it's a consequence of + # grpc_server_destroy's being what has the effect of telling the server's + # completion queue to pump out all pending events/tags immediately rather + # than gracefully completing all outstanding RPCs while accepting no new + # ones. + # TODO(nathaniel): Deallocation of a Python object shouldn't have this kind + # of observable side effect let alone such an important one. + del self.server + self.server_completion_queue.stop() + self.client_completion_queue.stop() + while True: + event = self.server_completion_queue.get(_FUTURE) + if event is not None and event.kind is _low.Event.Kind.STOP: + break + while True: + event = self.client_completion_queue.get(_FUTURE) + if event is not None and event.kind is _low.Event.Kind.STOP: + break + self.server_completion_queue = None + self.client_completion_queue = None + + def _perform_echo_test(self, test_data): + method = 'test method' + details = 'test details' + server_leading_metadata_key = 'my_server_leading_key' + server_leading_metadata_value = 'my_server_leading_value' + server_trailing_metadata_key = 'my_server_trailing_key' + server_trailing_metadata_value = 'my_server_trailing_value' + client_metadata_key = 'my_client_key' + client_metadata_value = 'my_client_value' + server_leading_binary_metadata_key = 'my_server_leading_key-bin' + server_leading_binary_metadata_value = b'\0'*2047 + server_trailing_binary_metadata_key = 'my_server_trailing_key-bin' + server_trailing_binary_metadata_value = b'\0'*2047 + client_binary_metadata_key = 'my_client_key-bin' + client_binary_metadata_value = b'\0'*2047 + deadline = _FUTURE + metadata_tag = object() + finish_tag = object() + write_tag = object() + complete_tag = object() + service_tag = object() + read_tag = object() + status_tag = object() + + server_data = [] + client_data = [] + + client_call = _low.Call(self.channel, self.client_completion_queue, + method, self.host, deadline) + client_call.add_metadata(client_metadata_key, client_metadata_value) + client_call.add_metadata(client_binary_metadata_key, + client_binary_metadata_value) + + client_call.invoke(self.client_completion_queue, metadata_tag, finish_tag) + + self.server.service(service_tag) + service_accepted = self.server_completion_queue.get(_FUTURE) + self.assertIsNotNone(service_accepted) + self.assertIs(service_accepted.kind, _low.Event.Kind.SERVICE_ACCEPTED) + self.assertIs(service_accepted.tag, service_tag) + self.assertEqual(method, service_accepted.service_acceptance.method) + self.assertEqual(self.host, service_accepted.service_acceptance.host) + self.assertIsNotNone(service_accepted.service_acceptance.call) + metadata = dict(service_accepted.metadata) + self.assertIn(client_metadata_key, metadata) + self.assertEqual(client_metadata_value, metadata[client_metadata_key]) + self.assertIn(client_binary_metadata_key, metadata) + self.assertEqual(client_binary_metadata_value, + metadata[client_binary_metadata_key]) + server_call = service_accepted.service_acceptance.call + server_call.accept(self.server_completion_queue, finish_tag) + server_call.add_metadata(server_leading_metadata_key, + server_leading_metadata_value) + server_call.add_metadata(server_leading_binary_metadata_key, + server_leading_binary_metadata_value) + server_call.premetadata() + + metadata_accepted = self.client_completion_queue.get(_FUTURE) + self.assertIsNotNone(metadata_accepted) + self.assertEqual(_low.Event.Kind.METADATA_ACCEPTED, metadata_accepted.kind) + self.assertEqual(metadata_tag, metadata_accepted.tag) + metadata = dict(metadata_accepted.metadata) + self.assertIn(server_leading_metadata_key, metadata) + self.assertEqual(server_leading_metadata_value, + metadata[server_leading_metadata_key]) + self.assertIn(server_leading_binary_metadata_key, metadata) + self.assertEqual(server_leading_binary_metadata_value, + metadata[server_leading_binary_metadata_key]) + + for datum in test_data: + client_call.write(datum, write_tag) + write_accepted = self.client_completion_queue.get(_FUTURE) + self.assertIsNotNone(write_accepted) + self.assertIs(write_accepted.kind, _low.Event.Kind.WRITE_ACCEPTED) + self.assertIs(write_accepted.tag, write_tag) + self.assertIs(write_accepted.write_accepted, True) + + server_call.read(read_tag) + read_accepted = self.server_completion_queue.get(_FUTURE) + self.assertIsNotNone(read_accepted) + self.assertEqual(_low.Event.Kind.READ_ACCEPTED, read_accepted.kind) + self.assertEqual(read_tag, read_accepted.tag) + self.assertIsNotNone(read_accepted.bytes) + server_data.append(read_accepted.bytes) + + server_call.write(read_accepted.bytes, write_tag) + write_accepted = self.server_completion_queue.get(_FUTURE) + self.assertIsNotNone(write_accepted) + self.assertEqual(_low.Event.Kind.WRITE_ACCEPTED, write_accepted.kind) + self.assertEqual(write_tag, write_accepted.tag) + self.assertTrue(write_accepted.write_accepted) + + client_call.read(read_tag) + read_accepted = self.client_completion_queue.get(_FUTURE) + self.assertIsNotNone(read_accepted) + self.assertEqual(_low.Event.Kind.READ_ACCEPTED, read_accepted.kind) + self.assertEqual(read_tag, read_accepted.tag) + self.assertIsNotNone(read_accepted.bytes) + client_data.append(read_accepted.bytes) + + client_call.complete(complete_tag) + complete_accepted = self.client_completion_queue.get(_FUTURE) + self.assertIsNotNone(complete_accepted) + self.assertIs(complete_accepted.kind, _low.Event.Kind.COMPLETE_ACCEPTED) + self.assertIs(complete_accepted.tag, complete_tag) + self.assertIs(complete_accepted.complete_accepted, True) + + server_call.read(read_tag) + read_accepted = self.server_completion_queue.get(_FUTURE) + self.assertIsNotNone(read_accepted) + self.assertEqual(_low.Event.Kind.READ_ACCEPTED, read_accepted.kind) + self.assertEqual(read_tag, read_accepted.tag) + self.assertIsNone(read_accepted.bytes) + + server_call.add_metadata(server_trailing_metadata_key, + server_trailing_metadata_value) + server_call.add_metadata(server_trailing_binary_metadata_key, + server_trailing_binary_metadata_value) + + server_call.status(_low.Status(_low.Code.OK, details), status_tag) + server_terminal_event_one = self.server_completion_queue.get(_FUTURE) + server_terminal_event_two = self.server_completion_queue.get(_FUTURE) + if server_terminal_event_one.kind == _low.Event.Kind.COMPLETE_ACCEPTED: + status_accepted = server_terminal_event_one + rpc_accepted = server_terminal_event_two + else: + status_accepted = server_terminal_event_two + rpc_accepted = server_terminal_event_one + self.assertIsNotNone(status_accepted) + self.assertIsNotNone(rpc_accepted) + self.assertEqual(_low.Event.Kind.COMPLETE_ACCEPTED, status_accepted.kind) + self.assertEqual(status_tag, status_accepted.tag) + self.assertTrue(status_accepted.complete_accepted) + self.assertEqual(_low.Event.Kind.FINISH, rpc_accepted.kind) + self.assertEqual(finish_tag, rpc_accepted.tag) + self.assertEqual(_low.Status(_low.Code.OK, ''), rpc_accepted.status) + + client_call.read(read_tag) + client_terminal_event_one = self.client_completion_queue.get(_FUTURE) + client_terminal_event_two = self.client_completion_queue.get(_FUTURE) + if client_terminal_event_one.kind == _low.Event.Kind.READ_ACCEPTED: + read_accepted = client_terminal_event_one + finish_accepted = client_terminal_event_two + else: + read_accepted = client_terminal_event_two + finish_accepted = client_terminal_event_one + self.assertIsNotNone(read_accepted) + self.assertIsNotNone(finish_accepted) + self.assertEqual(_low.Event.Kind.READ_ACCEPTED, read_accepted.kind) + self.assertEqual(read_tag, read_accepted.tag) + self.assertIsNone(read_accepted.bytes) + self.assertEqual(_low.Event.Kind.FINISH, finish_accepted.kind) + self.assertEqual(finish_tag, finish_accepted.tag) + self.assertEqual(_low.Status(_low.Code.OK, details), finish_accepted.status) + metadata = dict(finish_accepted.metadata) + self.assertIn(server_trailing_metadata_key, metadata) + self.assertEqual(server_trailing_metadata_value, + metadata[server_trailing_metadata_key]) + self.assertIn(server_trailing_binary_metadata_key, metadata) + self.assertEqual(server_trailing_binary_metadata_value, + metadata[server_trailing_binary_metadata_key]) + + server_timeout_none_event = self.server_completion_queue.get(0) + self.assertIsNone(server_timeout_none_event) + client_timeout_none_event = self.client_completion_queue.get(0) + self.assertIsNone(client_timeout_none_event) + + self.assertSequenceEqual(test_data, server_data) + self.assertSequenceEqual(test_data, client_data) + + def testNoEcho(self): + self._perform_echo_test(()) + + def testOneByteEcho(self): + self._perform_echo_test([b'\x07']) + + def testOneManyByteEcho(self): + self._perform_echo_test([_BYTE_SEQUENCE]) + + def testManyOneByteEchoes(self): + self._perform_echo_test(_BYTE_SEQUENCE) + + def testManyManyByteEchoes(self): + self._perform_echo_test(_BYTE_SEQUENCE_SEQUENCE) + + +class CancellationTest(unittest.TestCase): + + def setUp(self): + self.host = 'localhost' + + self.server_completion_queue = _low.CompletionQueue() + self.server = _low.Server(self.server_completion_queue) + port = self.server.add_http2_addr('[::]:0') + self.server.start() + + self.client_completion_queue = _low.CompletionQueue() + self.channel = _low.Channel('%s:%d' % (self.host, port), None) + + def tearDown(self): + self.server.stop() + del self.server + self.server_completion_queue.stop() + self.client_completion_queue.stop() + while True: + event = self.server_completion_queue.get(0) + if event is not None and event.kind is _low.Event.Kind.STOP: + break + while True: + event = self.client_completion_queue.get(0) + if event is not None and event.kind is _low.Event.Kind.STOP: + break + + def testCancellation(self): + method = 'test method' + deadline = _FUTURE + metadata_tag = object() + finish_tag = object() + write_tag = object() + service_tag = object() + read_tag = object() + test_data = _BYTE_SEQUENCE_SEQUENCE + + server_data = [] + client_data = [] + + client_call = _low.Call(self.channel, self.client_completion_queue, + method, self.host, deadline) + + client_call.invoke(self.client_completion_queue, metadata_tag, finish_tag) + + self.server.service(service_tag) + service_accepted = self.server_completion_queue.get(_FUTURE) + server_call = service_accepted.service_acceptance.call + + server_call.accept(self.server_completion_queue, finish_tag) + server_call.premetadata() + + metadata_accepted = self.client_completion_queue.get(_FUTURE) + self.assertIsNotNone(metadata_accepted) + + for datum in test_data: + client_call.write(datum, write_tag) + write_accepted = self.client_completion_queue.get(_FUTURE) + + server_call.read(read_tag) + read_accepted = self.server_completion_queue.get(_FUTURE) + server_data.append(read_accepted.bytes) + + server_call.write(read_accepted.bytes, write_tag) + write_accepted = self.server_completion_queue.get(_FUTURE) + self.assertIsNotNone(write_accepted) + + client_call.read(read_tag) + read_accepted = self.client_completion_queue.get(_FUTURE) + client_data.append(read_accepted.bytes) + + client_call.cancel() + # cancel() is idempotent. + client_call.cancel() + client_call.cancel() + client_call.cancel() + + server_call.read(read_tag) + + server_terminal_event_one = self.server_completion_queue.get(_FUTURE) + server_terminal_event_two = self.server_completion_queue.get(_FUTURE) + if server_terminal_event_one.kind == _low.Event.Kind.READ_ACCEPTED: + read_accepted = server_terminal_event_one + rpc_accepted = server_terminal_event_two + else: + read_accepted = server_terminal_event_two + rpc_accepted = server_terminal_event_one + self.assertIsNotNone(read_accepted) + self.assertIsNotNone(rpc_accepted) + self.assertEqual(_low.Event.Kind.READ_ACCEPTED, read_accepted.kind) + self.assertIsNone(read_accepted.bytes) + self.assertEqual(_low.Event.Kind.FINISH, rpc_accepted.kind) + self.assertEqual(_low.Status(_low.Code.CANCELLED, ''), rpc_accepted.status) + + finish_event = self.client_completion_queue.get(_FUTURE) + self.assertEqual(_low.Event.Kind.FINISH, finish_event.kind) + self.assertEqual(_low.Status(_low.Code.CANCELLED, 'Cancelled'), + finish_event.status) + + server_timeout_none_event = self.server_completion_queue.get(0) + self.assertIsNone(server_timeout_none_event) + client_timeout_none_event = self.client_completion_queue.get(0) + self.assertIsNone(client_timeout_none_event) + + self.assertSequenceEqual(test_data, server_data) + self.assertSequenceEqual(test_data, client_data) + + +class ExpirationTest(unittest.TestCase): + + @unittest.skip('TODO(nathaniel): Expiration test!') + def testExpiration(self): + pass + + +if __name__ == '__main__': + unittest.main(verbosity=2) + diff --git a/src/python/src/grpc/_adapter/_low.py b/src/python/src/grpc/_adapter/_low.py index a24baaeb3e7..0c1d3b40a5b 100644 --- a/src/python/src/grpc/_adapter/_low.py +++ b/src/python/src/grpc/_adapter/_low.py @@ -27,31 +27,85 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -"""A Python interface for GRPC C core structures and behaviors.""" - -import atexit -import gc - from grpc._adapter import _c -from grpc._adapter import _datatypes - -def _shut_down(): - # force garbage collection before shutting down grpc, to ensure all grpc - # objects are cleaned up - gc.collect() - _c.shut_down() - -_c.init() -atexit.register(_shut_down) - -# pylint: disable=invalid-name -Code = _datatypes.Code -Status = _datatypes.Status -Event = _datatypes.Event -Call = _c.Call -Channel = _c.Channel -CompletionQueue = _c.CompletionQueue -Server = _c.Server +from grpc._adapter import _types + ClientCredentials = _c.ClientCredentials ServerCredentials = _c.ServerCredentials -# pylint: enable=invalid-name + + +class CompletionQueue(_types.CompletionQueue): + + def __init__(self): + self.completion_queue = _c.CompletionQueue() + + def next(self, deadline=float('+inf')): + raw_event = self.completion_queue.next(deadline) + if raw_event is None: + return None + event = _types.Event(*raw_event) + if event.call is not None: + event = event._replace(call=Call(event.call)) + if event.call_details is not None: + event = event._replace(call_details=_types.CallDetails(*event.call_details)) + if event.results is not None: + new_results = [_types.OpResult(*r) for r in event.results] + new_results = [r if r.status is None else r._replace(status=_types.Status(_types.StatusCode(r.status[0]), r.status[1])) for r in new_results] + event = event._replace(results=new_results) + return event + + def shutdown(self): + self.completion_queue.shutdown() + + +class Call(_types.Call): + + def __init__(self, call): + self.call = call + + def start_batch(self, ops, tag): + return self.call.start_batch(ops, tag) + + def cancel(self, code=None, details=None): + if code is None and details is None: + return self.call.cancel() + else: + return self.call.cancel(code, details) + + +class Channel(_types.Channel): + + def __init__(self, target, args, creds=None): + if creds is None: + self.channel = _c.Channel(target, args) + else: + self.channel = _c.Channel(target, args, creds) + + def create_call(self, completion_queue, method, host, deadline=None): + return Call(self.channel.create_call(completion_queue.completion_queue, method, host, deadline)) + + +_NO_TAG = object() + +class Server(_types.Server): + + def __init__(self, completion_queue, args): + self.server = _c.Server(completion_queue.completion_queue, args) + + def add_http2_port(self, addr, creds=None): + if creds is None: + return self.server.add_http2_port(addr) + else: + return self.server.add_http2_port(addr, creds) + + def start(self): + return self.server.start() + + def shutdown(self, tag=_NO_TAG): + if tag is _NO_TAG: + return self.server.shutdown() + else: + return self.server.shutdown(tag) + + def request_call(self, completion_queue, tag): + return self.server.request_call(completion_queue.completion_queue, tag) diff --git a/src/python/src/grpc/_adapter/_low_test.py b/src/python/src/grpc/_adapter/_low_test.py index d4b628c2aea..e53b176caf9 100644 --- a/src/python/src/grpc/_adapter/_low_test.py +++ b/src/python/src/grpc/_adapter/_low_test.py @@ -27,388 +27,141 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -"""Tests for _adapter._low.""" - import time import unittest +from grpc._adapter import _types from grpc._adapter import _low -_STREAM_LENGTH = 300 -_TIMEOUT = 5 -_AFTER_DELAY = 2 -_FUTURE = time.time() + 60 * 60 * 24 -_BYTE_SEQUENCE = b'\abcdefghijklmnopqrstuvwxyz0123456789' * 200 -_BYTE_SEQUENCE_SEQUENCE = tuple( - bytes(bytearray((row + column) % 256 for column in range(row))) - for row in range(_STREAM_LENGTH)) - -class LonelyClientTest(unittest.TestCase): - - def testLonelyClient(self): - host = 'nosuchhostexists' - port = 54321 - method = 'test method' - deadline = time.time() + _TIMEOUT - after_deadline = deadline + _AFTER_DELAY - metadata_tag = object() - finish_tag = object() - - completion_queue = _low.CompletionQueue() - channel = _low.Channel('%s:%d' % (host, port), None) - client_call = _low.Call(channel, completion_queue, method, host, deadline) - - client_call.invoke(completion_queue, metadata_tag, finish_tag) - first_event = completion_queue.get(after_deadline) - self.assertIsNotNone(first_event) - second_event = completion_queue.get(after_deadline) - self.assertIsNotNone(second_event) - kinds = [event.kind for event in (first_event, second_event)] - self.assertItemsEqual( - (_low.Event.Kind.METADATA_ACCEPTED, _low.Event.Kind.FINISH), - kinds) - - self.assertIsNone(completion_queue.get(after_deadline)) - - completion_queue.stop() - stop_event = completion_queue.get(_FUTURE) - self.assertEqual(_low.Event.Kind.STOP, stop_event.kind) - -class EchoTest(unittest.TestCase): +class InsecureServerInsecureClient(unittest.TestCase): def setUp(self): - self.host = 'localhost' - self.server_completion_queue = _low.CompletionQueue() - self.server = _low.Server(self.server_completion_queue) - port = self.server.add_http2_addr('[::]:0') - self.server.start() - + self.server = _low.Server(self.server_completion_queue, []) + self.port = self.server.add_http2_port('[::]:0') self.client_completion_queue = _low.CompletionQueue() - self.channel = _low.Channel('%s:%d' % (self.host, port), None) - - def tearDown(self): - self.server.stop() - # NOTE(nathaniel): Yep, this is weird; it's a consequence of - # grpc_server_destroy's being what has the effect of telling the server's - # completion queue to pump out all pending events/tags immediately rather - # than gracefully completing all outstanding RPCs while accepting no new - # ones. - # TODO(nathaniel): Deallocation of a Python object shouldn't have this kind - # of observable side effect let alone such an important one. - del self.server - self.server_completion_queue.stop() - self.client_completion_queue.stop() - while True: - event = self.server_completion_queue.get(_FUTURE) - if event is not None and event.kind is _low.Event.Kind.STOP: - break - while True: - event = self.client_completion_queue.get(_FUTURE) - if event is not None and event.kind is _low.Event.Kind.STOP: - break - self.server_completion_queue = None - self.client_completion_queue = None - - def _perform_echo_test(self, test_data): - method = 'test method' - details = 'test details' - server_leading_metadata_key = 'my_server_leading_key' - server_leading_metadata_value = 'my_server_leading_value' - server_trailing_metadata_key = 'my_server_trailing_key' - server_trailing_metadata_value = 'my_server_trailing_value' - client_metadata_key = 'my_client_key' - client_metadata_value = 'my_client_value' - server_leading_binary_metadata_key = 'my_server_leading_key-bin' - server_leading_binary_metadata_value = b'\0'*2047 - server_trailing_binary_metadata_key = 'my_server_trailing_key-bin' - server_trailing_binary_metadata_value = b'\0'*2047 - client_binary_metadata_key = 'my_client_key-bin' - client_binary_metadata_value = b'\0'*2047 - deadline = _FUTURE - metadata_tag = object() - finish_tag = object() - write_tag = object() - complete_tag = object() - service_tag = object() - read_tag = object() - status_tag = object() - - server_data = [] - client_data = [] - - client_call = _low.Call(self.channel, self.client_completion_queue, - method, self.host, deadline) - client_call.add_metadata(client_metadata_key, client_metadata_value) - client_call.add_metadata(client_binary_metadata_key, - client_binary_metadata_value) - - client_call.invoke(self.client_completion_queue, metadata_tag, finish_tag) - - self.server.service(service_tag) - service_accepted = self.server_completion_queue.get(_FUTURE) - self.assertIsNotNone(service_accepted) - self.assertIs(service_accepted.kind, _low.Event.Kind.SERVICE_ACCEPTED) - self.assertIs(service_accepted.tag, service_tag) - self.assertEqual(method, service_accepted.service_acceptance.method) - self.assertEqual(self.host, service_accepted.service_acceptance.host) - self.assertIsNotNone(service_accepted.service_acceptance.call) - metadata = dict(service_accepted.metadata) - self.assertIn(client_metadata_key, metadata) - self.assertEqual(client_metadata_value, metadata[client_metadata_key]) - self.assertIn(client_binary_metadata_key, metadata) - self.assertEqual(client_binary_metadata_value, - metadata[client_binary_metadata_key]) - server_call = service_accepted.service_acceptance.call - server_call.accept(self.server_completion_queue, finish_tag) - server_call.add_metadata(server_leading_metadata_key, - server_leading_metadata_value) - server_call.add_metadata(server_leading_binary_metadata_key, - server_leading_binary_metadata_value) - server_call.premetadata() - - metadata_accepted = self.client_completion_queue.get(_FUTURE) - self.assertIsNotNone(metadata_accepted) - self.assertEqual(_low.Event.Kind.METADATA_ACCEPTED, metadata_accepted.kind) - self.assertEqual(metadata_tag, metadata_accepted.tag) - metadata = dict(metadata_accepted.metadata) - self.assertIn(server_leading_metadata_key, metadata) - self.assertEqual(server_leading_metadata_value, - metadata[server_leading_metadata_key]) - self.assertIn(server_leading_binary_metadata_key, metadata) - self.assertEqual(server_leading_binary_metadata_value, - metadata[server_leading_binary_metadata_key]) - - for datum in test_data: - client_call.write(datum, write_tag) - write_accepted = self.client_completion_queue.get(_FUTURE) - self.assertIsNotNone(write_accepted) - self.assertIs(write_accepted.kind, _low.Event.Kind.WRITE_ACCEPTED) - self.assertIs(write_accepted.tag, write_tag) - self.assertIs(write_accepted.write_accepted, True) - - server_call.read(read_tag) - read_accepted = self.server_completion_queue.get(_FUTURE) - self.assertIsNotNone(read_accepted) - self.assertEqual(_low.Event.Kind.READ_ACCEPTED, read_accepted.kind) - self.assertEqual(read_tag, read_accepted.tag) - self.assertIsNotNone(read_accepted.bytes) - server_data.append(read_accepted.bytes) - - server_call.write(read_accepted.bytes, write_tag) - write_accepted = self.server_completion_queue.get(_FUTURE) - self.assertIsNotNone(write_accepted) - self.assertEqual(_low.Event.Kind.WRITE_ACCEPTED, write_accepted.kind) - self.assertEqual(write_tag, write_accepted.tag) - self.assertTrue(write_accepted.write_accepted) - - client_call.read(read_tag) - read_accepted = self.client_completion_queue.get(_FUTURE) - self.assertIsNotNone(read_accepted) - self.assertEqual(_low.Event.Kind.READ_ACCEPTED, read_accepted.kind) - self.assertEqual(read_tag, read_accepted.tag) - self.assertIsNotNone(read_accepted.bytes) - client_data.append(read_accepted.bytes) - - client_call.complete(complete_tag) - complete_accepted = self.client_completion_queue.get(_FUTURE) - self.assertIsNotNone(complete_accepted) - self.assertIs(complete_accepted.kind, _low.Event.Kind.COMPLETE_ACCEPTED) - self.assertIs(complete_accepted.tag, complete_tag) - self.assertIs(complete_accepted.complete_accepted, True) - - server_call.read(read_tag) - read_accepted = self.server_completion_queue.get(_FUTURE) - self.assertIsNotNone(read_accepted) - self.assertEqual(_low.Event.Kind.READ_ACCEPTED, read_accepted.kind) - self.assertEqual(read_tag, read_accepted.tag) - self.assertIsNone(read_accepted.bytes) - - server_call.add_metadata(server_trailing_metadata_key, - server_trailing_metadata_value) - server_call.add_metadata(server_trailing_binary_metadata_key, - server_trailing_binary_metadata_value) - - server_call.status(_low.Status(_low.Code.OK, details), status_tag) - server_terminal_event_one = self.server_completion_queue.get(_FUTURE) - server_terminal_event_two = self.server_completion_queue.get(_FUTURE) - if server_terminal_event_one.kind == _low.Event.Kind.COMPLETE_ACCEPTED: - status_accepted = server_terminal_event_one - rpc_accepted = server_terminal_event_two - else: - status_accepted = server_terminal_event_two - rpc_accepted = server_terminal_event_one - self.assertIsNotNone(status_accepted) - self.assertIsNotNone(rpc_accepted) - self.assertEqual(_low.Event.Kind.COMPLETE_ACCEPTED, status_accepted.kind) - self.assertEqual(status_tag, status_accepted.tag) - self.assertTrue(status_accepted.complete_accepted) - self.assertEqual(_low.Event.Kind.FINISH, rpc_accepted.kind) - self.assertEqual(finish_tag, rpc_accepted.tag) - self.assertEqual(_low.Status(_low.Code.OK, ''), rpc_accepted.status) - - client_call.read(read_tag) - client_terminal_event_one = self.client_completion_queue.get(_FUTURE) - client_terminal_event_two = self.client_completion_queue.get(_FUTURE) - if client_terminal_event_one.kind == _low.Event.Kind.READ_ACCEPTED: - read_accepted = client_terminal_event_one - finish_accepted = client_terminal_event_two - else: - read_accepted = client_terminal_event_two - finish_accepted = client_terminal_event_one - self.assertIsNotNone(read_accepted) - self.assertIsNotNone(finish_accepted) - self.assertEqual(_low.Event.Kind.READ_ACCEPTED, read_accepted.kind) - self.assertEqual(read_tag, read_accepted.tag) - self.assertIsNone(read_accepted.bytes) - self.assertEqual(_low.Event.Kind.FINISH, finish_accepted.kind) - self.assertEqual(finish_tag, finish_accepted.tag) - self.assertEqual(_low.Status(_low.Code.OK, details), finish_accepted.status) - metadata = dict(finish_accepted.metadata) - self.assertIn(server_trailing_metadata_key, metadata) - self.assertEqual(server_trailing_metadata_value, - metadata[server_trailing_metadata_key]) - self.assertIn(server_trailing_binary_metadata_key, metadata) - self.assertEqual(server_trailing_binary_metadata_value, - metadata[server_trailing_binary_metadata_key]) - - server_timeout_none_event = self.server_completion_queue.get(0) - self.assertIsNone(server_timeout_none_event) - client_timeout_none_event = self.client_completion_queue.get(0) - self.assertIsNone(client_timeout_none_event) - - self.assertSequenceEqual(test_data, server_data) - self.assertSequenceEqual(test_data, client_data) + self.client_channel = _low.Channel('localhost:%d'%self.port, []) - def testNoEcho(self): - self._perform_echo_test(()) - - def testOneByteEcho(self): - self._perform_echo_test([b'\x07']) - - def testOneManyByteEcho(self): - self._perform_echo_test([_BYTE_SEQUENCE]) - - def testManyOneByteEchoes(self): - self._perform_echo_test(_BYTE_SEQUENCE) - - def testManyManyByteEchoes(self): - self._perform_echo_test(_BYTE_SEQUENCE_SEQUENCE) - -class CancellationTest(unittest.TestCase): - - def setUp(self): - self.host = 'localhost' - - self.server_completion_queue = _low.CompletionQueue() - self.server = _low.Server(self.server_completion_queue) - port = self.server.add_http2_addr('[::]:0') self.server.start() - self.client_completion_queue = _low.CompletionQueue() - self.channel = _low.Channel('%s:%d' % (self.host, port), None) - def tearDown(self): - self.server.stop() + self.server.shutdown() + del self.client_channel del self.server - self.server_completion_queue.stop() - self.client_completion_queue.stop() - while True: - event = self.server_completion_queue.get(0) - if event is not None and event.kind is _low.Event.Kind.STOP: - break - while True: - event = self.client_completion_queue.get(0) - if event is not None and event.kind is _low.Event.Kind.STOP: - break - - def testCancellation(self): - method = 'test method' - deadline = _FUTURE - metadata_tag = object() - finish_tag = object() - write_tag = object() - service_tag = object() - read_tag = object() - test_data = _BYTE_SEQUENCE_SEQUENCE - - server_data = [] - client_data = [] - - client_call = _low.Call(self.channel, self.client_completion_queue, - method, self.host, deadline) - - client_call.invoke(self.client_completion_queue, metadata_tag, finish_tag) - - self.server.service(service_tag) - service_accepted = self.server_completion_queue.get(_FUTURE) - server_call = service_accepted.service_acceptance.call - - server_call.accept(self.server_completion_queue, finish_tag) - server_call.premetadata() - - metadata_accepted = self.client_completion_queue.get(_FUTURE) - self.assertIsNotNone(metadata_accepted) - - for datum in test_data: - client_call.write(datum, write_tag) - write_accepted = self.client_completion_queue.get(_FUTURE) - - server_call.read(read_tag) - read_accepted = self.server_completion_queue.get(_FUTURE) - server_data.append(read_accepted.bytes) - - server_call.write(read_accepted.bytes, write_tag) - write_accepted = self.server_completion_queue.get(_FUTURE) - self.assertIsNotNone(write_accepted) - - client_call.read(read_tag) - read_accepted = self.client_completion_queue.get(_FUTURE) - client_data.append(read_accepted.bytes) - - client_call.cancel() - # cancel() is idempotent. - client_call.cancel() - client_call.cancel() - client_call.cancel() - - server_call.read(read_tag) - - server_terminal_event_one = self.server_completion_queue.get(_FUTURE) - server_terminal_event_two = self.server_completion_queue.get(_FUTURE) - if server_terminal_event_one.kind == _low.Event.Kind.READ_ACCEPTED: - read_accepted = server_terminal_event_one - rpc_accepted = server_terminal_event_two - else: - read_accepted = server_terminal_event_two - rpc_accepted = server_terminal_event_one - self.assertIsNotNone(read_accepted) - self.assertIsNotNone(rpc_accepted) - self.assertEqual(_low.Event.Kind.READ_ACCEPTED, read_accepted.kind) - self.assertIsNone(read_accepted.bytes) - self.assertEqual(_low.Event.Kind.FINISH, rpc_accepted.kind) - self.assertEqual(_low.Status(_low.Code.CANCELLED, ''), rpc_accepted.status) - - finish_event = self.client_completion_queue.get(_FUTURE) - self.assertEqual(_low.Event.Kind.FINISH, finish_event.kind) - self.assertEqual(_low.Status(_low.Code.CANCELLED, 'Cancelled'), - finish_event.status) - - server_timeout_none_event = self.server_completion_queue.get(0) - self.assertIsNone(server_timeout_none_event) - client_timeout_none_event = self.client_completion_queue.get(0) - self.assertIsNone(client_timeout_none_event) - - self.assertSequenceEqual(test_data, server_data) - self.assertSequenceEqual(test_data, client_data) - - -class ExpirationTest(unittest.TestCase): - @unittest.skip('TODO(nathaniel): Expiration test!') - def testExpiration(self): - pass + self.client_completion_queue.shutdown() + while self.client_completion_queue.next().type != _types.EventType.QUEUE_SHUTDOWN: + pass + self.server_completion_queue.shutdown() + while self.server_completion_queue.next().type != _types.EventType.QUEUE_SHUTDOWN: + pass + + del self.client_completion_queue + del self.server_completion_queue + + def testEcho(self): + DEADLINE = time.time()+5 + DEADLINE_TOLERANCE = 0.25 + CLIENT_METADATA_ASCII_KEY = 'key' + CLIENT_METADATA_ASCII_VALUE = 'val' + CLIENT_METADATA_BIN_KEY = 'key-bin' + CLIENT_METADATA_BIN_VALUE = b'\0'*1000 + SERVER_INITIAL_METADATA_KEY = 'init_me_me_me' + SERVER_INITIAL_METADATA_VALUE = 'whodawha?' + SERVER_TRAILING_METADATA_KEY = 'California_is_in_a_drought' + SERVER_TRAILING_METADATA_VALUE = 'zomg it is' + SERVER_STATUS_CODE = _types.StatusCode.OK + SERVER_STATUS_DETAILS = 'our work is never over' + REQUEST = 'in death a member of project mayhem has a name' + RESPONSE = 'his name is robert paulson' + METHOD = 'twinkies' + HOST = 'hostess' + server_request_tag = object() + request_call_result = self.server.request_call(self.server_completion_queue, server_request_tag) + + self.assertEquals(_types.CallError.OK, request_call_result) + + client_call_tag = object() + client_call = self.client_channel.create_call(self.client_completion_queue, METHOD, HOST, DEADLINE) + client_initial_metadata = [(CLIENT_METADATA_ASCII_KEY, CLIENT_METADATA_ASCII_VALUE), (CLIENT_METADATA_BIN_KEY, CLIENT_METADATA_BIN_VALUE)] + client_start_batch_result = client_call.start_batch([ + _types.OpArgs.send_initial_metadata(client_initial_metadata), + _types.OpArgs.send_message(REQUEST), + _types.OpArgs.send_close_from_client(), + _types.OpArgs.recv_initial_metadata(), + _types.OpArgs.recv_message(), + _types.OpArgs.recv_status_on_client() + ], client_call_tag) + self.assertEquals(_types.CallError.OK, client_start_batch_result) + + request_event = self.server_completion_queue.next(DEADLINE) + self.assertEquals(_types.EventType.OP_COMPLETE, request_event.type) + self.assertIsInstance(request_event.call, _low.Call) + self.assertIs(server_request_tag, request_event.tag) + self.assertEquals(1, len(request_event.results)) + self.assertEquals(dict(client_initial_metadata), dict(request_event.results[0].initial_metadata)) + self.assertEquals(METHOD, request_event.call_details.method) + self.assertEquals(HOST, request_event.call_details.host) + self.assertLess(abs(DEADLINE - request_event.call_details.deadline), DEADLINE_TOLERANCE) + + server_call_tag = object() + server_call = request_event.call + server_initial_metadata = [(SERVER_INITIAL_METADATA_KEY, SERVER_INITIAL_METADATA_VALUE)] + server_trailing_metadata = [(SERVER_TRAILING_METADATA_KEY, SERVER_TRAILING_METADATA_VALUE)] + server_start_batch_result = server_call.start_batch([ + _types.OpArgs.send_initial_metadata(server_initial_metadata), + _types.OpArgs.recv_message(), + _types.OpArgs.send_message(RESPONSE), + _types.OpArgs.recv_close_on_server(), + _types.OpArgs.send_status_from_server(server_trailing_metadata, SERVER_STATUS_CODE, SERVER_STATUS_DETAILS) + ], server_call_tag) + self.assertEquals(_types.CallError.OK, server_start_batch_result) + + client_event = self.client_completion_queue.next(DEADLINE) + server_event = self.server_completion_queue.next(DEADLINE) + + self.assertEquals(6, len(client_event.results)) + found_client_op_types = set() + for client_result in client_event.results: + self.assertNotIn(client_result.type, found_client_op_types) # we expect each op type to be unique + found_client_op_types.add(client_result.type) + if client_result.type == _types.OpType.RECV_INITIAL_METADATA: + self.assertEquals(dict(server_initial_metadata), dict(client_result.initial_metadata)) + elif client_result.type == _types.OpType.RECV_MESSAGE: + self.assertEquals(RESPONSE, client_result.message) + elif client_result.type == _types.OpType.RECV_STATUS_ON_CLIENT: + self.assertEquals(dict(server_trailing_metadata), dict(client_result.trailing_metadata)) + self.assertEquals(SERVER_STATUS_DETAILS, client_result.status.details) + self.assertEquals(SERVER_STATUS_CODE, client_result.status.code) + self.assertEquals(set([ + _types.OpType.SEND_INITIAL_METADATA, + _types.OpType.SEND_MESSAGE, + _types.OpType.SEND_CLOSE_FROM_CLIENT, + _types.OpType.RECV_INITIAL_METADATA, + _types.OpType.RECV_MESSAGE, + _types.OpType.RECV_STATUS_ON_CLIENT + ]), found_client_op_types) + + self.assertEquals(5, len(server_event.results)) + found_server_op_types = set() + for server_result in server_event.results: + self.assertNotIn(client_result.type, found_server_op_types) + found_server_op_types.add(server_result.type) + if server_result.type == _types.OpType.RECV_MESSAGE: + self.assertEquals(REQUEST, server_result.message) + elif server_result.type == _types.OpType.RECV_CLOSE_ON_SERVER: + self.assertFalse(server_result.cancelled) + self.assertEquals(set([ + _types.OpType.SEND_INITIAL_METADATA, + _types.OpType.RECV_MESSAGE, + _types.OpType.SEND_MESSAGE, + _types.OpType.RECV_CLOSE_ON_SERVER, + _types.OpType.SEND_STATUS_FROM_SERVER + ]), found_server_op_types) + + del client_call + del server_call if __name__ == '__main__': diff --git a/src/python/src/grpc/_adapter/_server.c b/src/python/src/grpc/_adapter/_server.c deleted file mode 100644 index a6c20bf1323..00000000000 --- a/src/python/src/grpc/_adapter/_server.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "grpc/_adapter/_server.h" - -#include -#include - -#include "grpc/_adapter/_call.h" -#include "grpc/_adapter/_completion_queue.h" -#include "grpc/_adapter/_error.h" -#include "grpc/_adapter/_server_credentials.h" -#include "grpc/_adapter/_tag.h" - -static int pygrpc_server_init(Server *self, PyObject *args, PyObject *kwds) { - CompletionQueue *completion_queue; - static char *kwlist[] = {"completion_queue", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!:Server", kwlist, - &pygrpc_CompletionQueueType, - &completion_queue)) { - return -1; - } - self->c_server = grpc_server_create(NULL); - grpc_server_register_completion_queue(self->c_server, - completion_queue->c_completion_queue); - self->completion_queue = completion_queue; - Py_INCREF(completion_queue); - return 0; -} - -static void pygrpc_server_dealloc(Server *self) { - if (self->c_server != NULL) { - grpc_server_destroy(self->c_server); - } - Py_XDECREF(self->completion_queue); - self->ob_type->tp_free((PyObject *)self); -} - -static PyObject *pygrpc_server_add_http2_addr(Server *self, PyObject *args) { - const char *addr; - int port; - if (!PyArg_ParseTuple(args, "s:add_http2_addr", &addr)) { - return NULL; - } - - port = grpc_server_add_http2_port(self->c_server, addr); - if (port == 0) { - PyErr_SetString(PyExc_RuntimeError, "Couldn't add port to server!"); - return NULL; - } - - return PyInt_FromLong(port); -} - -static PyObject *pygrpc_server_add_secure_http2_addr(Server *self, - PyObject *args, - PyObject *kwargs) { - const char *addr; - PyObject *server_credentials; - static char *kwlist[] = {"addr", "server_credentials", NULL}; - int port; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO!:add_secure_http2_addr", - kwlist, &addr, &pygrpc_ServerCredentialsType, - &server_credentials)) { - return NULL; - } - port = grpc_server_add_secure_http2_port( - self->c_server, addr, - ((ServerCredentials *)server_credentials)->c_server_credentials); - if (port == 0) { - PyErr_SetString(PyExc_RuntimeError, "Couldn't add port to server!"); - return NULL; - } - return PyInt_FromLong(port); -} - -static PyObject *pygrpc_server_start(Server *self) { - grpc_server_start(self->c_server); - - Py_RETURN_NONE; -} - -static const PyObject *pygrpc_server_service(Server *self, PyObject *tag) { - grpc_call_error call_error; - const PyObject *result; - pygrpc_tag *c_tag = pygrpc_tag_new_server_rpc_call(tag); - c_tag->call->completion_queue = self->completion_queue; - c_tag->call->server = self; - Py_INCREF(c_tag->call->completion_queue); - Py_INCREF(c_tag->call->server); - call_error = grpc_server_request_call( - self->c_server, &c_tag->call->c_call, &c_tag->call->call_details, - &c_tag->call->recv_metadata, self->completion_queue->c_completion_queue, - self->completion_queue->c_completion_queue, c_tag); - - result = pygrpc_translate_call_error(call_error); - if (result != NULL) { - Py_INCREF(tag); - } - return result; -} - -static PyObject *pygrpc_server_stop(Server *self) { - grpc_server_shutdown(self->c_server); - - Py_RETURN_NONE; -} - -static PyMethodDef methods[] = { - {"add_http2_addr", (PyCFunction)pygrpc_server_add_http2_addr, METH_VARARGS, - "Add an HTTP2 address."}, - {"add_secure_http2_addr", (PyCFunction)pygrpc_server_add_secure_http2_addr, - METH_VARARGS, "Add a secure HTTP2 address."}, - {"start", (PyCFunction)pygrpc_server_start, METH_NOARGS, - "Starts the server."}, - {"service", (PyCFunction)pygrpc_server_service, METH_O, "Services a call."}, - {"stop", (PyCFunction)pygrpc_server_stop, METH_NOARGS, "Stops the server."}, - {NULL}}; - -static PyTypeObject pygrpc_ServerType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_gprc.Server", /*tp_name*/ - sizeof(Server), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)pygrpc_server_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - "Wrapping of grpc_server.", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)pygrpc_server_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ -}; - -int pygrpc_add_server(PyObject *module) { - if (PyType_Ready(&pygrpc_ServerType) < 0) { - return -1; - } - if (PyModule_AddObject(module, "Server", (PyObject *)&pygrpc_ServerType) == - -1) { - return -1; - } - return 0; -} diff --git a/src/python/src/grpc/_adapter/_server_credentials.c b/src/python/src/grpc/_adapter/_server_credentials.c deleted file mode 100644 index 06e6b94974a..00000000000 --- a/src/python/src/grpc/_adapter/_server_credentials.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "grpc/_adapter/_server_credentials.h" - -#include -#include -#include - -static int pygrpc_server_credentials_init(ServerCredentials *self, - PyObject *args, PyObject *kwds) { - char *root_certificates; - PyObject *pair_sequence; - Py_ssize_t pair_count; - grpc_ssl_pem_key_cert_pair *pairs; - int error; - PyObject *iterator; - int i; - PyObject *pair; - static char *kwlist[] = {"root_credentials", "pair_sequence", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "zO:ServerCredentials", kwlist, - &root_certificates, &pair_sequence)) { - return -1; - } - - pair_count = PySequence_Length(pair_sequence); - if (pair_count == -1) { - return -1; - } - - iterator = PyObject_GetIter(pair_sequence); - if (iterator == NULL) { - return -1; - } - pairs = gpr_malloc(pair_count * sizeof(grpc_ssl_pem_key_cert_pair)); - error = 0; - for (i = 0; i < pair_count; i++) { - pair = PyIter_Next(iterator); - if (pair == NULL) { - error = 1; - break; - } - if (!PyArg_ParseTuple(pair, "ss", &pairs[i].private_key, - &pairs[i].cert_chain)) { - error = 1; - Py_DECREF(pair); - break; - } - Py_DECREF(pair); - } - Py_DECREF(iterator); - - if (error) { - gpr_free(pairs); - return -1; - } else { - self->c_server_credentials = grpc_ssl_server_credentials_create( - root_certificates, pairs, pair_count); - gpr_free(pairs); - return 0; - } -} - -static void pygrpc_server_credentials_dealloc(ServerCredentials *self) { - if (self->c_server_credentials != NULL) { - grpc_server_credentials_release(self->c_server_credentials); - } - self->ob_type->tp_free((PyObject *)self); -} - -PyTypeObject pygrpc_ServerCredentialsType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_grpc.ServerCredencials", /*tp_name*/ - sizeof(ServerCredentials), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)pygrpc_server_credentials_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - "Wrapping of grpc_server_credentials.", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)pygrpc_server_credentials_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ -}; - -int pygrpc_add_server_credentials(PyObject *module) { - if (PyType_Ready(&pygrpc_ServerCredentialsType) < 0) { - return -1; - } - if (PyModule_AddObject(module, "ServerCredentials", - (PyObject *)&pygrpc_ServerCredentialsType) == -1) { - return -1; - } - return 0; -} diff --git a/src/python/src/grpc/_adapter/_server_credentials.h b/src/python/src/grpc/_adapter/_server_credentials.h deleted file mode 100644 index 75af9340897..00000000000 --- a/src/python/src/grpc/_adapter/_server_credentials.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef _ADAPTER__SERVER_CREDENTIALS_H_ -#define _ADAPTER__SERVER_CREDENTIALS_H_ - -#include -#include - -typedef struct { - PyObject_HEAD - grpc_server_credentials *c_server_credentials; -} ServerCredentials; - -extern PyTypeObject pygrpc_ServerCredentialsType; - -int pygrpc_add_server_credentials(PyObject *module); - -#endif /* _ADAPTER__SERVER_CREDENTIALS_H_ */ diff --git a/src/python/src/grpc/_adapter/_tag.c b/src/python/src/grpc/_adapter/_tag.c deleted file mode 100644 index 9c6ee19d793..00000000000 --- a/src/python/src/grpc/_adapter/_tag.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "grpc/_adapter/_tag.h" - -#include -#include -#include - -pygrpc_tag *pygrpc_tag_new(pygrpc_tag_type type, PyObject *user_tag, - Call *call) { - pygrpc_tag *self = (pygrpc_tag *)gpr_malloc(sizeof(pygrpc_tag)); - memset(self, 0, sizeof(pygrpc_tag)); - if (user_tag == NULL) { - self->user_tag = Py_None; - } else { - self->user_tag = user_tag; - } - Py_INCREF(self->user_tag); - self->type = type; - self->call = call; - Py_INCREF(call); - return self; -} - -pygrpc_tag *pygrpc_tag_new_server_rpc_call(PyObject *user_tag) { - return pygrpc_tag_new(PYGRPC_SERVER_RPC_NEW, user_tag, - (Call *)pygrpc_CallType.tp_alloc(&pygrpc_CallType, 0)); -} - -void pygrpc_tag_destroy(pygrpc_tag *self) { - Py_XDECREF(self->user_tag); - Py_XDECREF(self->call); - gpr_free(self); -} diff --git a/src/python/src/grpc/_adapter/_tag.h b/src/python/src/grpc/_adapter/_tag.h deleted file mode 100644 index 64812aa7e76..00000000000 --- a/src/python/src/grpc/_adapter/_tag.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef _ADAPTER__TAG_H_ -#define _ADAPTER__TAG_H_ - -#include -#include - -#include "grpc/_adapter/_call.h" -#include "grpc/_adapter/_completion_queue.h" - -/* grpc_completion_type is becoming meaningless in grpc_event; this is a partial - replacement for its descriptive functionality until Python can move its whole - C and C adapter stack to more closely resemble the core batching API. */ -typedef enum { - PYGRPC_SERVER_RPC_NEW = 0, - PYGRPC_INITIAL_METADATA = 1, - PYGRPC_READ = 2, - PYGRPC_WRITE_ACCEPTED = 3, - PYGRPC_FINISH_ACCEPTED = 4, - PYGRPC_CLIENT_METADATA_READ = 5, - PYGRPC_FINISHED_CLIENT = 6, - PYGRPC_FINISHED_SERVER = 7 -} pygrpc_tag_type; - -typedef struct { - pygrpc_tag_type type; - PyObject *user_tag; - - Call *call; -} pygrpc_tag; - -pygrpc_tag *pygrpc_tag_new(pygrpc_tag_type type, PyObject *user_tag, - Call *call); -pygrpc_tag *pygrpc_tag_new_server_rpc_call(PyObject *user_tag); -void pygrpc_tag_destroy(pygrpc_tag *self); - -#endif /* _ADAPTER__TAG_H_ */ - diff --git a/src/python/src/grpc/_adapter/_types.py b/src/python/src/grpc/_adapter/_types.py new file mode 100644 index 00000000000..5ddb1774ea0 --- /dev/null +++ b/src/python/src/grpc/_adapter/_types.py @@ -0,0 +1,368 @@ +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import abc +import collections +import enum + +# TODO(atash): decide whether or not to move these enums to the _c module to +# force build errors with upstream changes. + +class GrpcChannelArgumentKeys(enum.Enum): + """Mirrors keys used in grpc_channel_args for GRPC-specific arguments.""" + SSL_TARGET_NAME_OVERRIDE = 'grpc.ssl_target_name_override' + +@enum.unique +class CallError(enum.IntEnum): + """Mirrors grpc_call_error in the C core.""" + OK = 0 + ERROR = 1 + ERROR_NOT_ON_SERVER = 2 + ERROR_NOT_ON_CLIENT = 3 + ERROR_ALREADY_ACCEPTED = 4 + ERROR_ALREADY_INVOKED = 5 + ERROR_NOT_INVOKED = 6 + ERROR_ALREADY_FINISHED = 7 + ERROR_TOO_MANY_OPERATIONS = 8 + ERROR_INVALID_FLAGS = 9 + ERROR_INVALID_METADATA = 10 + +@enum.unique +class StatusCode(enum.IntEnum): + """Mirrors grpc_status_code in the C core.""" + OK = 0 + CANCELLED = 1 + UNKNOWN = 2 + INVALID_ARGUMENT = 3 + DEADLINE_EXCEEDED = 4 + NOT_FOUND = 5 + ALREADY_EXISTS = 6 + PERMISSION_DENIED = 7 + RESOURCE_EXHAUSTED = 8 + FAILED_PRECONDITION = 9 + ABORTED = 10 + OUT_OF_RANGE = 11 + UNIMPLEMENTED = 12 + INTERNAL = 13 + UNAVAILABLE = 14 + DATA_LOSS = 15 + UNAUTHENTICATED = 16 + +@enum.unique +class OpType(enum.IntEnum): + """Mirrors grpc_op_type in the C core.""" + SEND_INITIAL_METADATA = 0 + SEND_MESSAGE = 1 + SEND_CLOSE_FROM_CLIENT = 2 + SEND_STATUS_FROM_SERVER = 3 + RECV_INITIAL_METADATA = 4 + RECV_MESSAGE = 5 + RECV_STATUS_ON_CLIENT = 6 + RECV_CLOSE_ON_SERVER = 7 + +@enum.unique +class EventType(enum.IntEnum): + """Mirrors grpc_completion_type in the C core.""" + QUEUE_SHUTDOWN = 0 + QUEUE_TIMEOUT = 1 # if seen on the Python side, something went horridly wrong + OP_COMPLETE = 2 + +class Status(collections.namedtuple( + 'Status', [ + 'code', + 'details', + ])): + """The end status of a GRPC call. + + Attributes: + code (StatusCode): ... + details (str): ... + """ + +class CallDetails(collections.namedtuple( + 'CallDetails', [ + 'method', + 'host', + 'deadline', + ])): + """Provides information to the server about the client's call. + + Attributes: + method (str): ... + host (str): ... + deadline (float): ... + """ + +class OpArgs(collections.namedtuple( + 'OpArgs', [ + 'type', + 'initial_metadata', + 'trailing_metadata', + 'message', + 'status', + ])): + """Arguments passed into a GRPC operation. + + Attributes: + type (OpType): ... + initial_metadata (sequence of 2-sequence of str): Only valid if type == + OpType.SEND_INITIAL_METADATA, else is None. + trailing_metadata (sequence of 2-sequence of str): Only valid if type == + OpType.SEND_STATUS_FROM_SERVER, else is None. + message (bytes): Only valid if type == OpType.SEND_MESSAGE, else is None. + status (Status): Only valid if type == OpType.SEND_STATUS_FROM_SERVER, else + is None. + """ + + @staticmethod + def send_initial_metadata(initial_metadata): + return OpArgs(OpType.SEND_INITIAL_METADATA, initial_metadata, None, None, None) + + @staticmethod + def send_message(message): + return OpArgs(OpType.SEND_MESSAGE, None, None, message, None) + + @staticmethod + def send_close_from_client(): + return OpArgs(OpType.SEND_CLOSE_FROM_CLIENT, None, None, None, None) + + @staticmethod + def send_status_from_server(trailing_metadata, status_code, status_details): + return OpArgs(OpType.SEND_STATUS_FROM_SERVER, None, trailing_metadata, None, Status(status_code, status_details)) + + @staticmethod + def recv_initial_metadata(): + return OpArgs(OpType.RECV_INITIAL_METADATA, None, None, None, None); + + @staticmethod + def recv_message(): + return OpArgs(OpType.RECV_MESSAGE, None, None, None, None) + + @staticmethod + def recv_status_on_client(): + return OpArgs(OpType.RECV_STATUS_ON_CLIENT, None, None, None, None) + + @staticmethod + def recv_close_on_server(): + return OpArgs(OpType.RECV_CLOSE_ON_SERVER, None, None, None, None) + + +class OpResult(collections.namedtuple( + 'OpResult', [ + 'type', + 'initial_metadata', + 'trailing_metadata', + 'message', + 'status', + 'cancelled', + ])): + """Results received from a GRPC operation. + + Attributes: + type (OpType): ... + initial_metadata (sequence of 2-sequence of str): Only valid if type == + OpType.RECV_INITIAL_METADATA, else is None. + trailing_metadata (sequence of 2-sequence of str): Only valid if type == + OpType.RECV_STATUS_ON_CLIENT, else is None. + message (bytes): Only valid if type == OpType.RECV_MESSAGE, else is None. + status (Status): Only valid if type == OpType.RECV_STATUS_ON_CLIENT, else + is None. + cancelled (bool): Only valid if type == OpType.RECV_CLOSE_ON_SERVER, else + is None. + """ + + +class Event(collections.namedtuple( + 'Event', [ + 'type', + 'tag', + 'call', + 'call_details', + 'results', + 'success', + ])): + """An event received from a GRPC completion queue. + + Attributes: + type (EventType): ... + tag (object): ... + call (Call): The Call object associated with this event (if there is one, + else None). + call_details (CallDetails): The call details associated with the + server-side call (if there is such information, else None). + results (list of OpResult): ... + success (bool): ... + """ + + +class CompletionQueue: + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def __init__(self): + pass + + def __iter__(self): + """This class may be iterated over. + + This is the equivalent of calling next() repeatedly with an absolute + deadline of None (i.e. no deadline). + """ + return self + + @abc.abstractmethod + def next(self, deadline=float('+inf')): + """Get the next event on this completion queue. + + Args: + deadline (float): absolute deadline in seconds from the Python epoch, or + None for no deadline. + + Returns: + Event: ... + """ + pass + + @abc.abstractmethod + def shutdown(self): + """Begin the shutdown process of this completion queue. + + Note that this does not immediately destroy the completion queue. + Nevertheless, user code should not pass it around after invoking this. + """ + return None + + +class Call: + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def start_batch(self, ops, tag): + """Start a batch of operations. + + Args: + ops (sequence of OpArgs): ... + tag (object): ... + + Returns: + CallError: ... + """ + return CallError.ERROR + + @abc.abstractmethod + def cancel(self, code=None, details=None): + """Cancel the call. + + Args: + code (int): Status code to cancel with (on the server side). If + specified, so must `details`. + details (str): Status details to cancel with (on the server side). If + specified, so must `code`. + + Returns: + CallError: ... + """ + return CallError.ERROR + + +class Channel: + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def __init__(self, target, args, credentials=None): + """Initialize a Channel. + + Args: + target (str): ... + args (sequence of 2-sequence of str, (str|integer)): ... + credentials (ClientCredentials): If None, create an insecure channel, + else create a secure channel using the client credentials. + """ + + @abc.abstractmethod + def create_call(self, completion_queue, method, host, deadline=float('+inf')): + """Create a call from this channel. + + Args: + completion_queue (CompletionQueue): ... + method (str): ... + host (str): ... + deadline (float): absolute deadline in seconds from the Python epoch, or + None for no deadline. + + Returns: + Call: call object associated with this Channel and passed parameters. + """ + return None + + +class Server: + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def __init__(self, completion_queue, args): + """Initialize a server. + + Args: + completion_queue (CompletionQueue): ... + args (sequence of 2-sequence of str, (str|integer)): ... + """ + + @abc.abstractmethod + def add_http2_port(self, address, credentials=None): + """Adds an HTTP/2 address+port to the server. + + Args: + address (str): ... + credentials (ServerCredentials): If None, create an insecure port, else + create a secure port using the server credentials. + """ + + @abc.abstractmethod + def start(self): + """Starts the server.""" + + @abc.abstractmethod + def shutdown(self, tag=None): + """Shuts down the server. Does not immediately destroy the server. + + Args: + tag (object): if not None, have the server place an event on its + completion queue notifying it when this server has completely shut down. + """ + + @abc.abstractmethod + def request_call(self, completion_queue, tag): + """Requests a call from the server on the server's completion queue. + + Args: + completion_queue (CompletionQueue): Completion queue for the call. May be + the same as the server's completion queue. + tag (object) ... + """ diff --git a/src/python/src/grpc/_adapter/fore.py b/src/python/src/grpc/_adapter/fore.py index 69e145e3f61..7d88bda2631 100644 --- a/src/python/src/grpc/_adapter/fore.py +++ b/src/python/src/grpc/_adapter/fore.py @@ -35,7 +35,7 @@ import threading import time from grpc._adapter import _common -from grpc._adapter import _low +from grpc._adapter import _intermediary_low as _low from grpc.framework.base import interfaces as base_interfaces from grpc.framework.base import null from grpc.framework.foundation import activated @@ -204,7 +204,7 @@ class ForeLink(base_interfaces.ForeLink, activated.Activated): call, sequence_number, base_interfaces.FrontToBackTicket.Kind.CANCELLATION, None, None, None, None, None) - elif code is _low.Code.EXPIRED: + elif code is _low.Code.DEADLINE_EXCEEDED: ticket = base_interfaces.FrontToBackTicket( call, sequence_number, base_interfaces.FrontToBackTicket.Kind.EXPIRATION, None, None, None, diff --git a/src/python/src/grpc/_adapter/rear.py b/src/python/src/grpc/_adapter/rear.py index b3b0b4ed329..fd6f45f7a79 100644 --- a/src/python/src/grpc/_adapter/rear.py +++ b/src/python/src/grpc/_adapter/rear.py @@ -35,7 +35,7 @@ import threading import time from grpc._adapter import _common -from grpc._adapter import _low +from grpc._adapter import _intermediary_low as _low from grpc.framework.base import interfaces as base_interfaces from grpc.framework.base import null from grpc.framework.foundation import activated @@ -195,7 +195,7 @@ class RearLink(base_interfaces.RearLink, activated.Activated): kind = base_interfaces.BackToFrontTicket.Kind.COMPLETION elif event.status.code is _low.Code.CANCELLED: kind = base_interfaces.BackToFrontTicket.Kind.CANCELLATION - elif event.status.code is _low.Code.EXPIRED: + elif event.status.code is _low.Code.DEADLINE_EXCEEDED: kind = base_interfaces.BackToFrontTicket.Kind.EXPIRATION else: kind = base_interfaces.BackToFrontTicket.Kind.TRANSMISSION_FAILURE diff --git a/src/python/src/setup.py b/src/python/src/setup.py index d0f4791a1e4..dc655a70f91 100644 --- a/src/python/src/setup.py +++ b/src/python/src/setup.py @@ -34,15 +34,15 @@ import setuptools import sys _EXTENSION_SOURCES = ( - 'grpc/_adapter/_c.c', - 'grpc/_adapter/_call.c', - 'grpc/_adapter/_channel.c', - 'grpc/_adapter/_completion_queue.c', - 'grpc/_adapter/_error.c', - 'grpc/_adapter/_server.c', - 'grpc/_adapter/_client_credentials.c', - 'grpc/_adapter/_server_credentials.c', - 'grpc/_adapter/_tag.c' + 'grpc/_adapter/_c/module.c', + 'grpc/_adapter/_c/types.c', + 'grpc/_adapter/_c/utility.c', + 'grpc/_adapter/_c/types/client_credentials.c', + 'grpc/_adapter/_c/types/server_credentials.c', + 'grpc/_adapter/_c/types/completion_queue.c', + 'grpc/_adapter/_c/types/call.c', + 'grpc/_adapter/_c/types/channel.c', + 'grpc/_adapter/_c/types/server.c', ) _EXTENSION_INCLUDE_DIRECTORIES = ( diff --git a/tools/run_tests/python_tests.json b/tools/run_tests/python_tests.json index dff053784db..6c969d765f9 100755 --- a/tools/run_tests/python_tests.json +++ b/tools/run_tests/python_tests.json @@ -1,27 +1,27 @@ [ { - "file": "test/compiler/python_plugin_test.py" + "module": "grpc._adapter._c_test" }, { - "module": "grpc._adapter._blocking_invocation_inline_service_test" + "module": "grpc._adapter._low_test" }, { - "module": "grpc._adapter._c_test" + "module": "grpc._adapter._intermediary_low_test" }, { - "module": "grpc._adapter._event_invocation_synchronous_event_service_test" + "module": "grpc._adapter._links_test" }, { - "module": "grpc._adapter._future_invocation_asynchronous_event_service_test" + "module": "grpc._adapter._lonely_rear_link_test" }, { - "module": "grpc._adapter._links_test" + "module": "grpc._adapter._blocking_invocation_inline_service_test" }, { - "module": "grpc._adapter._lonely_rear_link_test" + "module": "grpc._adapter._event_invocation_synchronous_event_service_test" }, { - "module": "grpc._adapter._low_test" + "module": "grpc._adapter._future_invocation_asynchronous_event_service_test" }, { "module": "grpc.early_adopter.implementations_test" @@ -49,5 +49,8 @@ }, { "module": "interop._secure_interop_test" + }, + { + "file": "test/compiler/python_plugin_test.py" } ] From 9300c4b9c02bd2de81a7fc4fc1af42f820f2eb86 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 29 May 2015 14:51:11 -0700 Subject: [PATCH 06/52] Fix the display of total slowdown --- test/core/util/test_config.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/core/util/test_config.c b/test/core/util/test_config.c index be69fcf6750..20ab67ec15d 100644 --- a/test/core/util/test_config.c +++ b/test/core/util/test_config.c @@ -50,8 +50,9 @@ static int seed(void) { return _getpid(); } void grpc_test_init(int argc, char **argv) { gpr_log(GPR_DEBUG, "test slowdown: machine=%f build=%f total=%f", - GRPC_TEST_SLOWDOWN_MACHINE_FACTOR, GRPC_TEST_SLOWDOWN_BUILD_FACTOR, - GRPC_TEST_SLOWDOWN_FACTOR); + (double)GRPC_TEST_SLOWDOWN_MACHINE_FACTOR, + (double)GRPC_TEST_SLOWDOWN_BUILD_FACTOR, + (double)GRPC_TEST_SLOWDOWN_FACTOR); /* seed rng with pid, so we don't end up with the same random numbers as a concurrently running test binary */ srand(seed()); From 28848229b59127017534cc11a93ab9bce81d8123 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Fri, 29 May 2015 20:04:38 -0700 Subject: [PATCH 07/52] Move RemoteTestClient files to /objective-c The tests are going to use it too --- .../RemoteTestClient/Empty.pbobjc.h | 0 .../RemoteTestClient/Empty.pbobjc.m | 0 .../RemoteTestClient/Messages.pbobjc.h | 0 .../RemoteTestClient/Messages.pbobjc.m | 0 .../RemoteTestClient/RemoteTest.podspec | 0 .../Sample => generated_libraries}/RemoteTestClient/Test.pbobjc.h | 0 .../Sample => generated_libraries}/RemoteTestClient/Test.pbobjc.m | 0 .../Sample => generated_libraries}/RemoteTestClient/Test.pbrpc.h | 0 .../Sample => generated_libraries}/RemoteTestClient/Test.pbrpc.m | 0 .../Sample => generated_libraries}/RemoteTestClient/empty.proto | 0 .../RemoteTestClient/messages.proto | 0 .../Sample => generated_libraries}/RemoteTestClient/test.proto | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename src/objective-c/{examples/Sample => generated_libraries}/RemoteTestClient/Empty.pbobjc.h (100%) rename src/objective-c/{examples/Sample => generated_libraries}/RemoteTestClient/Empty.pbobjc.m (100%) rename src/objective-c/{examples/Sample => generated_libraries}/RemoteTestClient/Messages.pbobjc.h (100%) rename src/objective-c/{examples/Sample => generated_libraries}/RemoteTestClient/Messages.pbobjc.m (100%) rename src/objective-c/{examples/Sample => generated_libraries}/RemoteTestClient/RemoteTest.podspec (100%) rename src/objective-c/{examples/Sample => generated_libraries}/RemoteTestClient/Test.pbobjc.h (100%) rename src/objective-c/{examples/Sample => generated_libraries}/RemoteTestClient/Test.pbobjc.m (100%) rename src/objective-c/{examples/Sample => generated_libraries}/RemoteTestClient/Test.pbrpc.h (100%) rename src/objective-c/{examples/Sample => generated_libraries}/RemoteTestClient/Test.pbrpc.m (100%) rename src/objective-c/{examples/Sample => generated_libraries}/RemoteTestClient/empty.proto (100%) rename src/objective-c/{examples/Sample => generated_libraries}/RemoteTestClient/messages.proto (100%) rename src/objective-c/{examples/Sample => generated_libraries}/RemoteTestClient/test.proto (100%) diff --git a/src/objective-c/examples/Sample/RemoteTestClient/Empty.pbobjc.h b/src/objective-c/generated_libraries/RemoteTestClient/Empty.pbobjc.h similarity index 100% rename from src/objective-c/examples/Sample/RemoteTestClient/Empty.pbobjc.h rename to src/objective-c/generated_libraries/RemoteTestClient/Empty.pbobjc.h diff --git a/src/objective-c/examples/Sample/RemoteTestClient/Empty.pbobjc.m b/src/objective-c/generated_libraries/RemoteTestClient/Empty.pbobjc.m similarity index 100% rename from src/objective-c/examples/Sample/RemoteTestClient/Empty.pbobjc.m rename to src/objective-c/generated_libraries/RemoteTestClient/Empty.pbobjc.m diff --git a/src/objective-c/examples/Sample/RemoteTestClient/Messages.pbobjc.h b/src/objective-c/generated_libraries/RemoteTestClient/Messages.pbobjc.h similarity index 100% rename from src/objective-c/examples/Sample/RemoteTestClient/Messages.pbobjc.h rename to src/objective-c/generated_libraries/RemoteTestClient/Messages.pbobjc.h diff --git a/src/objective-c/examples/Sample/RemoteTestClient/Messages.pbobjc.m b/src/objective-c/generated_libraries/RemoteTestClient/Messages.pbobjc.m similarity index 100% rename from src/objective-c/examples/Sample/RemoteTestClient/Messages.pbobjc.m rename to src/objective-c/generated_libraries/RemoteTestClient/Messages.pbobjc.m diff --git a/src/objective-c/examples/Sample/RemoteTestClient/RemoteTest.podspec b/src/objective-c/generated_libraries/RemoteTestClient/RemoteTest.podspec similarity index 100% rename from src/objective-c/examples/Sample/RemoteTestClient/RemoteTest.podspec rename to src/objective-c/generated_libraries/RemoteTestClient/RemoteTest.podspec diff --git a/src/objective-c/examples/Sample/RemoteTestClient/Test.pbobjc.h b/src/objective-c/generated_libraries/RemoteTestClient/Test.pbobjc.h similarity index 100% rename from src/objective-c/examples/Sample/RemoteTestClient/Test.pbobjc.h rename to src/objective-c/generated_libraries/RemoteTestClient/Test.pbobjc.h diff --git a/src/objective-c/examples/Sample/RemoteTestClient/Test.pbobjc.m b/src/objective-c/generated_libraries/RemoteTestClient/Test.pbobjc.m similarity index 100% rename from src/objective-c/examples/Sample/RemoteTestClient/Test.pbobjc.m rename to src/objective-c/generated_libraries/RemoteTestClient/Test.pbobjc.m diff --git a/src/objective-c/examples/Sample/RemoteTestClient/Test.pbrpc.h b/src/objective-c/generated_libraries/RemoteTestClient/Test.pbrpc.h similarity index 100% rename from src/objective-c/examples/Sample/RemoteTestClient/Test.pbrpc.h rename to src/objective-c/generated_libraries/RemoteTestClient/Test.pbrpc.h diff --git a/src/objective-c/examples/Sample/RemoteTestClient/Test.pbrpc.m b/src/objective-c/generated_libraries/RemoteTestClient/Test.pbrpc.m similarity index 100% rename from src/objective-c/examples/Sample/RemoteTestClient/Test.pbrpc.m rename to src/objective-c/generated_libraries/RemoteTestClient/Test.pbrpc.m diff --git a/src/objective-c/examples/Sample/RemoteTestClient/empty.proto b/src/objective-c/generated_libraries/RemoteTestClient/empty.proto similarity index 100% rename from src/objective-c/examples/Sample/RemoteTestClient/empty.proto rename to src/objective-c/generated_libraries/RemoteTestClient/empty.proto diff --git a/src/objective-c/examples/Sample/RemoteTestClient/messages.proto b/src/objective-c/generated_libraries/RemoteTestClient/messages.proto similarity index 100% rename from src/objective-c/examples/Sample/RemoteTestClient/messages.proto rename to src/objective-c/generated_libraries/RemoteTestClient/messages.proto diff --git a/src/objective-c/examples/Sample/RemoteTestClient/test.proto b/src/objective-c/generated_libraries/RemoteTestClient/test.proto similarity index 100% rename from src/objective-c/examples/Sample/RemoteTestClient/test.proto rename to src/objective-c/generated_libraries/RemoteTestClient/test.proto From 15c8e1b60c96b859c564e393bd149258e02e0699 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Fri, 29 May 2015 20:04:57 -0700 Subject: [PATCH 08/52] Point Podfile of sample app to new RemoteTestsClient location --- src/objective-c/examples/Sample/Podfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/examples/Sample/Podfile b/src/objective-c/examples/Sample/Podfile index e8b78647ac0..0d077387c19 100644 --- a/src/objective-c/examples/Sample/Podfile +++ b/src/objective-c/examples/Sample/Podfile @@ -4,7 +4,7 @@ platform :ios, '8.0' pod 'gRPC', :path => "../../../.." pod 'Protobuf', :git => 'https://github.com/google/protobuf.git' pod 'Route_guide', :path => "RouteGuideClient" -pod 'RemoteTest', :path => "RemoteTestClient" +pod 'RemoteTest', :path => "../../generated_libraries/RemoteTestClient" link_with 'Sample', 'SampleTests' From dc42ee624db264a6d76c3a890d0ddcdc86d887d7 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Sat, 30 May 2015 11:00:26 -0700 Subject: [PATCH 09/52] Add RemoteTestClient to tests' Podfile --- src/objective-c/tests/Podfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile index 6df063a3801..d8fea6edb15 100644 --- a/src/objective-c/tests/Podfile +++ b/src/objective-c/tests/Podfile @@ -1,7 +1,9 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' -pod 'gRPC/RxLibrary', :path => "../../.." +pod 'gRPC', :path => "../../.." +pod 'Protobuf', :git => 'https://github.com/google/protobuf.git' +pod 'RemoteTest', :path => "../generated_libraries/RemoteTestClient" link_with 'AllTests' From 7307684b2ba07e25e7858080c667a98f5b1171ee Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Sat, 30 May 2015 12:04:43 -0700 Subject: [PATCH 10/52] Add RemoteProtoTests as InteropTests to tests project --- src/objective-c/tests/InteropTests.m | 305 ++++++++++++++++++ .../tests/Tests.xcodeproj/project.pbxproj | 4 + 2 files changed, 309 insertions(+) create mode 100644 src/objective-c/tests/InteropTests.m diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m new file mode 100644 index 00000000000..0a512c17dcb --- /dev/null +++ b/src/objective-c/tests/InteropTests.m @@ -0,0 +1,305 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#import +#import + +#import +#import +#import +#import +#import +#import +#import + +// Convenience constructors for the generated proto messages: + +@interface RMTStreamingOutputCallRequest (Constructors) ++ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize + requestedResponseSize:(NSNumber *)responseSize; +@end + +@implementation RMTStreamingOutputCallRequest (Constructors) ++ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize + requestedResponseSize:(NSNumber *)responseSize { + RMTStreamingOutputCallRequest *request = [self message]; + RMTResponseParameters *parameters = [RMTResponseParameters message]; + parameters.size = responseSize.integerValue; + [request.responseParametersArray addObject:parameters]; + request.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue]; + return request; +} +@end + +@interface RMTStreamingOutputCallResponse (Constructors) ++ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize; +@end + +@implementation RMTStreamingOutputCallResponse (Constructors) ++ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize { + RMTStreamingOutputCallResponse * response = [self message]; + response.payload.type = RMTPayloadType_Compressable; + response.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue]; + return response; +} +@end + +@interface InteropTests : XCTestCase +@end + +@implementation InteropTests { + RMTTestService *_service; +} + +- (void)setUp { + _service = [[RMTTestService alloc] initWithHost:@"grpc-test.sandbox.google.com"]; +} + +// Tests as described here: https://github.com/grpc/grpc/blob/master/doc/interop-test-descriptions.md + +- (void)testEmptyUnaryRPC { + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyUnary"]; + + RMTEmpty *request = [RMTEmpty message]; + + [_service emptyCallWithRequest:request handler:^(RMTEmpty *response, NSError *error) { + XCTAssertNil(error, @"Finished with unexpected error: %@", error); + + id expectedResponse = [RMTEmpty message]; + XCTAssertEqualObjects(response, expectedResponse); + + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:2 handler:nil]; +} + +- (void)testLargeUnaryRPC { + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"]; + + RMTSimpleRequest *request = [RMTSimpleRequest message]; + request.responseType = RMTPayloadType_Compressable; + request.responseSize = 314159; + request.payload.body = [NSMutableData dataWithLength:271828]; + + [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) { + XCTAssertNil(error, @"Finished with unexpected error: %@", error); + + RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message]; + expectedResponse.payload.type = RMTPayloadType_Compressable; + expectedResponse.payload.body = [NSMutableData dataWithLength:314159]; + XCTAssertEqualObjects(response, expectedResponse); + + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:4 handler:nil]; +} + +- (void)testClientStreamingRPC { + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ClientStreaming"]; + + RMTStreamingInputCallRequest *request1 = [RMTStreamingInputCallRequest message]; + request1.payload.body = [NSMutableData dataWithLength:27182]; + + RMTStreamingInputCallRequest *request2 = [RMTStreamingInputCallRequest message]; + request2.payload.body = [NSMutableData dataWithLength:8]; + + RMTStreamingInputCallRequest *request3 = [RMTStreamingInputCallRequest message]; + request3.payload.body = [NSMutableData dataWithLength:1828]; + + RMTStreamingInputCallRequest *request4 = [RMTStreamingInputCallRequest message]; + request4.payload.body = [NSMutableData dataWithLength:45904]; + + id writer = [GRXWriter writerWithContainer:@[request1, request2, request3, request4]]; + + [_service streamingInputCallWithRequestsWriter:writer + handler:^(RMTStreamingInputCallResponse *response, + NSError *error) { + XCTAssertNil(error, @"Finished with unexpected error: %@", error); + + RMTStreamingInputCallResponse *expectedResponse = [RMTStreamingInputCallResponse message]; + expectedResponse.aggregatedPayloadSize = 74922; + XCTAssertEqualObjects(response, expectedResponse); + + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:4 handler:nil]; +} + +- (void)testServerStreamingRPC { + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ServerStreaming"]; + + NSArray *expectedSizes = @[@31415, @9, @2653, @58979]; + + RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message]; + for (NSNumber *size in expectedSizes) { + RMTResponseParameters *parameters = [RMTResponseParameters message]; + parameters.size = [size integerValue]; + [request.responseParametersArray addObject:parameters]; + } + + __block int index = 0; + [_service streamingOutputCallWithRequest:request + handler:^(BOOL done, + RMTStreamingOutputCallResponse *response, + NSError *error){ + XCTAssertNil(error, @"Finished with unexpected error: %@", error); + XCTAssertTrue(done || response, @"Event handler called without an event."); + + if (response) { + XCTAssertLessThan(index, 4, @"More than 4 responses received."); + id expected = [RMTStreamingOutputCallResponse messageWithPayloadSize:expectedSizes[index]]; + XCTAssertEqualObjects(response, expected); + index += 1; + } + + if (done) { + XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index); + [expectation fulfill]; + } + }]; + + [self waitForExpectationsWithTimeout:4 handler:nil]; +} + +- (void)testPingPongRPC { + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"PingPong"]; + + NSArray *requests = @[@27182, @8, @1828, @45904]; + NSArray *responses = @[@31415, @9, @2653, @58979]; + + GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init]; + + __block int index = 0; + + id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] + requestedResponseSize:responses[index]]; + [requestsBuffer writeValue:request]; + + [_service fullDuplexCallWithRequestsWriter:requestsBuffer + handler:^(BOOL done, + RMTStreamingOutputCallResponse *response, + NSError *error) { + XCTAssertNil(error, @"Finished with unexpected error: %@", error); + XCTAssertTrue(done || response, @"Event handler called without an event."); + + if (response) { + XCTAssertLessThan(index, 4, @"More than 4 responses received."); + id expected = [RMTStreamingOutputCallResponse messageWithPayloadSize:responses[index]]; + XCTAssertEqualObjects(response, expected); + index += 1; + if (index < 4) { + id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] + requestedResponseSize:responses[index]]; + [requestsBuffer writeValue:request]; + } else { + [requestsBuffer writesFinishedWithError:nil]; + } + } + + if (done) { + XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index); + [expectation fulfill]; + } + }]; + [self waitForExpectationsWithTimeout:2 handler:nil]; +} + +- (void)testEmptyStreamRPC { + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyStream"]; + [_service fullDuplexCallWithRequestsWriter:[GRXWriter emptyWriter] + handler:^(BOOL done, + RMTStreamingOutputCallResponse *response, + NSError *error) { + XCTAssertNil(error, @"Finished with unexpected error: %@", error); + XCTAssert(done, @"Unexpected response: %@", response); + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:2 handler:nil]; +} + +- (void)testCancelAfterBeginRPC { + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterBegin"]; + + // A buffered pipe to which we never write any value acts as a writer that just hangs. + GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init]; + + ProtoRPC *call = [_service RPCToStreamingInputCallWithRequestsWriter:requestsBuffer + handler:^(RMTStreamingInputCallResponse *response, + NSError *error) { + XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); + [expectation fulfill]; + }]; + [call start]; + [call cancel]; + [self waitForExpectationsWithTimeout:1 handler:nil]; +} + +- (void)testCancelAfterFirstResponseRPC { + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterFirstResponse"]; + + // A buffered pipe to which we write a single value but never close + GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init]; + + __block BOOL receivedResponse = NO; + + id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782 + requestedResponseSize:@31415]; + + [requestsBuffer writeValue:request]; + + __block ProtoRPC *call = [_service RPCToFullDuplexCallWithRequestsWriter:requestsBuffer + handler:^(BOOL done, + RMTStreamingOutputCallResponse *response, + NSError *error) { + if (receivedResponse) { + XCTAssert(done, @"Unexpected extra response %@", response); + XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); + [expectation fulfill]; + } else { + XCTAssertNil(error, @"Finished with unexpected error: %@", error); + XCTAssertFalse(done, @"Finished without response"); + XCTAssertNotNil(response); + receivedResponse = YES; + [call cancel]; + } + }]; + [call start]; + [self waitForExpectationsWithTimeout:4 handler:nil]; +} + +@end diff --git a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj index 80059b7cbe8..3a98fec11a3 100644 --- a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj +++ b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 63423F4A1B150A5F006CF63C /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; 63423F511B151B77006CF63C /* RxLibraryUnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63423F501B151B77006CF63C /* RxLibraryUnitTests.m */; }; 635697CD1B14FC11007A7283 /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 635697CC1B14FC11007A7283 /* Tests.m */; }; + 635ED2EC1B1A3BC400FDE5C3 /* InteropTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */; }; 7D8A186224D39101F90230F6 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 35F2B6BF3BAE8F0DC4AFD76E /* libPods.a */; }; /* End PBXBuildFile section */ @@ -43,6 +44,7 @@ 635697C71B14FC11007A7283 /* libTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTests.a; sourceTree = BUILT_PRODUCTS_DIR; }; 635697CC1B14FC11007A7283 /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = ""; }; 635697D81B14FC11007A7283 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InteropTests.m; sourceTree = ""; }; FF7B5489BCFE40111D768DD0 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -105,6 +107,7 @@ 635697C91B14FC11007A7283 /* Tests */ = { isa = PBXGroup; children = ( + 635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */, 63423F501B151B77006CF63C /* RxLibraryUnitTests.m */, 635697CC1B14FC11007A7283 /* Tests.m */, 635697D71B14FC11007A7283 /* Supporting Files */, @@ -244,6 +247,7 @@ buildActionMask = 2147483647; files = ( 63423F511B151B77006CF63C /* RxLibraryUnitTests.m in Sources */, + 635ED2EC1B1A3BC400FDE5C3 /* InteropTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From 1641cc93b612a880fd380c98f9dca0e5fa33cee3 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Sat, 30 May 2015 19:05:12 -0700 Subject: [PATCH 11/52] Delete RemoteProtoTests from sample app --- .../Sample/Sample.xcodeproj/project.pbxproj | 4 - .../Sample/SampleTests/RemoteProtoTests.m | 305 ------------------ 2 files changed, 309 deletions(-) delete mode 100644 src/objective-c/examples/Sample/SampleTests/RemoteProtoTests.m diff --git a/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj b/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj index 17c2255b5a0..877d65a7011 100644 --- a/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj +++ b/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj @@ -8,7 +8,6 @@ /* Begin PBXBuildFile section */ 60BBBBB15823BBF7639D7AA9 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DC7B7C4C0410F43B9621631 /* libPods.a */; }; - 6340F0491AE66E3300FB6A3D /* RemoteProtoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6340F0481AE66E3300FB6A3D /* RemoteProtoTests.m */; }; 6356D1DE1AC11FE00075FBBC /* RemoteTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6356D1DD1AC11FE00075FBBC /* RemoteTests.m */; }; 6369A2701A9322E20015FC5C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A26F1A9322E20015FC5C /* main.m */; }; 6369A2731A9322E20015FC5C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2721A9322E20015FC5C /* AppDelegate.m */; }; @@ -32,7 +31,6 @@ /* Begin PBXFileReference section */ 2DC7B7C4C0410F43B9621631 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 6340F0481AE66E3300FB6A3D /* RemoteProtoTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RemoteProtoTests.m; sourceTree = ""; }; 6356D1DD1AC11FE00075FBBC /* RemoteTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RemoteTests.m; sourceTree = ""; }; 6369A26A1A9322E20015FC5C /* Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6369A26E1A9322E20015FC5C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -118,7 +116,6 @@ 6369A2861A9322E20015FC5C /* SampleTests */ = { isa = PBXGroup; children = ( - 6340F0481AE66E3300FB6A3D /* RemoteProtoTests.m */, 6369A2891A9322E20015FC5C /* SampleTests.m */, 6369A2871A9322E20015FC5C /* Supporting Files */, 6356D1DD1AC11FE00075FBBC /* RemoteTests.m */, @@ -329,7 +326,6 @@ buildActionMask = 2147483647; files = ( 6369A28A1A9322E20015FC5C /* SampleTests.m in Sources */, - 6340F0491AE66E3300FB6A3D /* RemoteProtoTests.m in Sources */, 6356D1DE1AC11FE00075FBBC /* RemoteTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/src/objective-c/examples/Sample/SampleTests/RemoteProtoTests.m b/src/objective-c/examples/Sample/SampleTests/RemoteProtoTests.m deleted file mode 100644 index 8e0e11d23da..00000000000 --- a/src/objective-c/examples/Sample/SampleTests/RemoteProtoTests.m +++ /dev/null @@ -1,305 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include - -#import -#import - -#import -#import -#import -#import -#import -#import -#import - -// Convenience constructors for the generated proto messages: - -@interface RMTStreamingOutputCallRequest (Constructors) -+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize - requestedResponseSize:(NSNumber *)responseSize; -@end - -@implementation RMTStreamingOutputCallRequest (Constructors) -+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize - requestedResponseSize:(NSNumber *)responseSize { - RMTStreamingOutputCallRequest *request = [self message]; - RMTResponseParameters *parameters = [RMTResponseParameters message]; - parameters.size = responseSize.integerValue; - [request.responseParametersArray addObject:parameters]; - request.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue]; - return request; -} -@end - -@interface RMTStreamingOutputCallResponse (Constructors) -+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize; -@end - -@implementation RMTStreamingOutputCallResponse (Constructors) -+ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize { - RMTStreamingOutputCallResponse * response = [self message]; - response.payload.type = RMTPayloadType_Compressable; - response.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue]; - return response; -} -@end - -@interface RemoteProtoTests : XCTestCase -@end - -@implementation RemoteProtoTests { - RMTTestService *_service; -} - -- (void)setUp { - _service = [[RMTTestService alloc] initWithHost:@"grpc-test.sandbox.google.com"]; -} - -// Tests as described here: https://github.com/grpc/grpc/blob/master/doc/interop-test-descriptions.md - -- (void)testEmptyUnaryRPC { - __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyUnary"]; - - RMTEmpty *request = [RMTEmpty message]; - - [_service emptyCallWithRequest:request handler:^(RMTEmpty *response, NSError *error) { - XCTAssertNil(error, @"Finished with unexpected error: %@", error); - - id expectedResponse = [RMTEmpty message]; - XCTAssertEqualObjects(response, expectedResponse); - - [expectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:2 handler:nil]; -} - -- (void)testLargeUnaryRPC { - __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"]; - - RMTSimpleRequest *request = [RMTSimpleRequest message]; - request.responseType = RMTPayloadType_Compressable; - request.responseSize = 314159; - request.payload.body = [NSMutableData dataWithLength:271828]; - - [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) { - XCTAssertNil(error, @"Finished with unexpected error: %@", error); - - RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message]; - expectedResponse.payload.type = RMTPayloadType_Compressable; - expectedResponse.payload.body = [NSMutableData dataWithLength:314159]; - XCTAssertEqualObjects(response, expectedResponse); - - [expectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:4 handler:nil]; -} - -- (void)testClientStreamingRPC { - __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ClientStreaming"]; - - RMTStreamingInputCallRequest *request1 = [RMTStreamingInputCallRequest message]; - request1.payload.body = [NSMutableData dataWithLength:27182]; - - RMTStreamingInputCallRequest *request2 = [RMTStreamingInputCallRequest message]; - request2.payload.body = [NSMutableData dataWithLength:8]; - - RMTStreamingInputCallRequest *request3 = [RMTStreamingInputCallRequest message]; - request3.payload.body = [NSMutableData dataWithLength:1828]; - - RMTStreamingInputCallRequest *request4 = [RMTStreamingInputCallRequest message]; - request4.payload.body = [NSMutableData dataWithLength:45904]; - - id writer = [GRXWriter writerWithContainer:@[request1, request2, request3, request4]]; - - [_service streamingInputCallWithRequestsWriter:writer - handler:^(RMTStreamingInputCallResponse *response, - NSError *error) { - XCTAssertNil(error, @"Finished with unexpected error: %@", error); - - RMTStreamingInputCallResponse *expectedResponse = [RMTStreamingInputCallResponse message]; - expectedResponse.aggregatedPayloadSize = 74922; - XCTAssertEqualObjects(response, expectedResponse); - - [expectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:4 handler:nil]; -} - -- (void)testServerStreamingRPC { - __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ServerStreaming"]; - - NSArray *expectedSizes = @[@31415, @9, @2653, @58979]; - - RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message]; - for (NSNumber *size in expectedSizes) { - RMTResponseParameters *parameters = [RMTResponseParameters message]; - parameters.size = [size integerValue]; - [request.responseParametersArray addObject:parameters]; - } - - __block int index = 0; - [_service streamingOutputCallWithRequest:request - handler:^(BOOL done, - RMTStreamingOutputCallResponse *response, - NSError *error){ - XCTAssertNil(error, @"Finished with unexpected error: %@", error); - XCTAssertTrue(done || response, @"Event handler called without an event."); - - if (response) { - XCTAssertLessThan(index, 4, @"More than 4 responses received."); - id expected = [RMTStreamingOutputCallResponse messageWithPayloadSize:expectedSizes[index]]; - XCTAssertEqualObjects(response, expected); - index += 1; - } - - if (done) { - XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index); - [expectation fulfill]; - } - }]; - - [self waitForExpectationsWithTimeout:4 handler:nil]; -} - -- (void)testPingPongRPC { - __weak XCTestExpectation *expectation = [self expectationWithDescription:@"PingPong"]; - - NSArray *requests = @[@27182, @8, @1828, @45904]; - NSArray *responses = @[@31415, @9, @2653, @58979]; - - GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init]; - - __block int index = 0; - - id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] - requestedResponseSize:responses[index]]; - [requestsBuffer writeValue:request]; - - [_service fullDuplexCallWithRequestsWriter:requestsBuffer - handler:^(BOOL done, - RMTStreamingOutputCallResponse *response, - NSError *error) { - XCTAssertNil(error, @"Finished with unexpected error: %@", error); - XCTAssertTrue(done || response, @"Event handler called without an event."); - - if (response) { - XCTAssertLessThan(index, 4, @"More than 4 responses received."); - id expected = [RMTStreamingOutputCallResponse messageWithPayloadSize:responses[index]]; - XCTAssertEqualObjects(response, expected); - index += 1; - if (index < 4) { - id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] - requestedResponseSize:responses[index]]; - [requestsBuffer writeValue:request]; - } else { - [requestsBuffer writesFinishedWithError:nil]; - } - } - - if (done) { - XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index); - [expectation fulfill]; - } - }]; - [self waitForExpectationsWithTimeout:2 handler:nil]; -} - -- (void)testEmptyStreamRPC { - __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyStream"]; - [_service fullDuplexCallWithRequestsWriter:[GRXWriter emptyWriter] - handler:^(BOOL done, - RMTStreamingOutputCallResponse *response, - NSError *error) { - XCTAssertNil(error, @"Finished with unexpected error: %@", error); - XCTAssert(done, @"Unexpected response: %@", response); - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:2 handler:nil]; -} - -- (void)testCancelAfterBeginRPC { - __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterBegin"]; - - // A buffered pipe to which we never write any value acts as a writer that just hangs. - GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init]; - - ProtoRPC *call = [_service RPCToStreamingInputCallWithRequestsWriter:requestsBuffer - handler:^(RMTStreamingInputCallResponse *response, - NSError *error) { - XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); - [expectation fulfill]; - }]; - [call start]; - [call cancel]; - [self waitForExpectationsWithTimeout:1 handler:nil]; -} - -- (void)testCancelAfterFirstResponseRPC { - __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterFirstResponse"]; - - // A buffered pipe to which we write a single value but never close - GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init]; - - __block BOOL receivedResponse = NO; - - id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782 - requestedResponseSize:@31415]; - - [requestsBuffer writeValue:request]; - - __block ProtoRPC *call = [_service RPCToFullDuplexCallWithRequestsWriter:requestsBuffer - handler:^(BOOL done, - RMTStreamingOutputCallResponse *response, - NSError *error) { - if (receivedResponse) { - XCTAssert(done, @"Unexpected extra response %@", response); - XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); - [expectation fulfill]; - } else { - XCTAssertNil(error, @"Finished with unexpected error: %@", error); - XCTAssertFalse(done, @"Finished without response"); - XCTAssertNotNil(response); - receivedResponse = YES; - [call cancel]; - } - }]; - [call start]; - [self waitForExpectationsWithTimeout:4 handler:nil]; -} - -@end From 5f228f5001c7c1f85c0d1965640bd6258d7b9188 Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Tue, 26 May 2015 19:58:50 -0700 Subject: [PATCH 12/52] Adapted the following to the new iomgr's cb API: alarm_test, tcp_posix, fd_posix, pollset_posix, credentials, call, channel, server, child_channel --- src/core/channel/child_channel.c | 13 ++++- src/core/iomgr/fd_posix.c | 29 +++++++--- src/core/iomgr/fd_posix.h | 10 ++-- src/core/iomgr/iomgr.c | 92 +++++++++++++++++++------------- src/core/iomgr/iomgr.h | 13 ++++- src/core/iomgr/iomgr_internal.h | 4 +- src/core/iomgr/pollset_posix.c | 8 ++- src/core/iomgr/socket_windows.c | 11 ++-- src/core/iomgr/socket_windows.h | 2 + src/core/iomgr/tcp_posix.c | 8 ++- src/core/security/credentials.c | 4 +- src/core/surface/call.c | 6 ++- src/core/surface/channel.c | 6 ++- src/core/surface/server.c | 25 ++++++--- test/core/iomgr/alarm_test.c | 11 +++- 15 files changed, 170 insertions(+), 72 deletions(-) diff --git a/src/core/channel/child_channel.c b/src/core/channel/child_channel.c index a2f3c54290a..5679a8c81aa 100644 --- a/src/core/channel/child_channel.c +++ b/src/core/channel/child_channel.c @@ -58,6 +58,9 @@ typedef struct { gpr_uint8 sending_farewell; /* have we sent farewell (goaway + disconnect) */ gpr_uint8 sent_farewell; + + grpc_iomgr_closure finally_destroy_channel_iocb; + grpc_iomgr_closure send_farewells_iocb; } lb_channel_data; typedef struct { grpc_child_channel *channel; } lb_call_data; @@ -213,12 +216,18 @@ static void maybe_destroy_channel(grpc_child_channel *channel) { lb_channel_data *chand = LINK_BACK_ELEM_FROM_CHANNEL(channel)->channel_data; if (chand->destroyed && chand->disconnected && chand->active_calls == 0 && !chand->sending_farewell && !chand->calling_back) { - grpc_iomgr_add_callback(finally_destroy_channel, channel); + chand->finally_destroy_channel_iocb.cb = finally_destroy_channel; + chand->finally_destroy_channel_iocb.cb_arg = channel; + chand->finally_destroy_channel_iocb.is_ext_managed = 1; /* GPR_TRUE */ + grpc_iomgr_add_callback(&chand->finally_destroy_channel_iocb); } else if (chand->destroyed && !chand->disconnected && chand->active_calls == 0 && !chand->sending_farewell && !chand->sent_farewell) { chand->sending_farewell = 1; - grpc_iomgr_add_callback(send_farewells, channel); + chand->send_farewells_iocb.cb = send_farewells; + chand->send_farewells_iocb.cb_arg = channel; + chand->send_farewells_iocb.is_ext_managed = 1; /* GPR_TRUE */ + grpc_iomgr_add_callback(&chand->send_farewells_iocb); } } diff --git a/src/core/iomgr/fd_posix.c b/src/core/iomgr/fd_posix.c index b697fcc64a2..3509d021eec 100644 --- a/src/core/iomgr/fd_posix.c +++ b/src/core/iomgr/fd_posix.c @@ -91,6 +91,7 @@ static grpc_fd *alloc_fd(int fd) { gpr_mu_init(&r->set_state_mu); gpr_mu_init(&r->watcher_mu); } + gpr_atm_rel_store(&r->refst, 1); gpr_atm_rel_store(&r->readst, NOT_READY); gpr_atm_rel_store(&r->writest, NOT_READY); @@ -117,7 +118,10 @@ static void unref_by(grpc_fd *fd, int n) { gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n); if (old == n) { close(fd->fd); - grpc_iomgr_add_callback(fd->on_done, fd->on_done_user_data); + fd->on_done_iocb.cb = fd->on_done; + fd->on_done_iocb.cb_arg = fd->on_done_user_data; + fd->on_done_iocb.is_ext_managed = 1; + grpc_iomgr_add_callback(&fd->on_done_iocb); freelist_fd(fd); grpc_iomgr_unref(); } else { @@ -196,20 +200,25 @@ void grpc_fd_ref(grpc_fd *fd) { ref_by(fd, 2); } void grpc_fd_unref(grpc_fd *fd) { unref_by(fd, 2); } static void make_callback(grpc_iomgr_cb_func cb, void *arg, int success, - int allow_synchronous_callback) { + int allow_synchronous_callback, + grpc_iomgr_closure *iocb) { if (allow_synchronous_callback) { cb(arg, success); } else { - grpc_iomgr_add_delayed_callback(cb, arg, success); + /* !iocb: allocate -> managed by iomgr + * iocb: "iocb" holds an instance managed by fd_posix */ + iocb = grpc_iomgr_cb_create(cb, arg, !iocb /* is_ext_managed */); + grpc_iomgr_add_delayed_callback(iocb, success); } } static void make_callbacks(grpc_iomgr_closure *callbacks, size_t n, int success, - int allow_synchronous_callback) { + int allow_synchronous_callback, + grpc_iomgr_closure *iocbs) { size_t i; for (i = 0; i < n; i++) { make_callback(callbacks[i].cb, callbacks[i].cb_arg, success, - allow_synchronous_callback); + allow_synchronous_callback, iocbs + i); } } @@ -238,7 +247,7 @@ static void notify_on(grpc_fd *fd, gpr_atm *st, grpc_iomgr_closure *closure, gpr_atm_rel_store(st, NOT_READY); make_callback(closure->cb, closure->cb_arg, !gpr_atm_acq_load(&fd->shutdown), - allow_synchronous_callback); + allow_synchronous_callback, NULL); return; default: /* WAITING */ /* upcallptr was set to a different closure. This is an error! */ @@ -284,11 +293,14 @@ static void set_ready(grpc_fd *fd, gpr_atm *st, int success; grpc_iomgr_closure cb; size_t ncb = 0; + grpc_iomgr_closure *ready_iocb; gpr_mu_lock(&fd->set_state_mu); set_ready_locked(st, &cb, &ncb); gpr_mu_unlock(&fd->set_state_mu); success = !gpr_atm_acq_load(&fd->shutdown); - make_callbacks(&cb, ncb, success, allow_synchronous_callback); + assert(ncb <= 1); + ready_iocb = grpc_iomgr_cb_create(cb.cb, cb.cb_arg, 0); + make_callbacks(&cb, ncb, success, allow_synchronous_callback, ready_iocb); } void grpc_fd_shutdown(grpc_fd *fd) { @@ -300,7 +312,8 @@ void grpc_fd_shutdown(grpc_fd *fd) { set_ready_locked(&fd->readst, cb, &ncb); set_ready_locked(&fd->writest, cb, &ncb); gpr_mu_unlock(&fd->set_state_mu); - make_callbacks(cb, ncb, 0, 0); + assert(ncb <= 2); + make_callbacks(cb, ncb, 0, 0, fd->shutdown_iocbs); } void grpc_fd_notify_on_read(grpc_fd *fd, grpc_iomgr_closure *closure) { diff --git a/src/core/iomgr/fd_posix.h b/src/core/iomgr/fd_posix.h index cfc533b7f56..59bd01ce0f2 100644 --- a/src/core/iomgr/fd_posix.h +++ b/src/core/iomgr/fd_posix.h @@ -40,11 +40,6 @@ #include #include -typedef struct { - grpc_iomgr_cb_func cb; - void *cb_arg; -} grpc_iomgr_closure; - typedef struct grpc_fd grpc_fd; typedef struct grpc_fd_watcher { @@ -99,6 +94,11 @@ struct grpc_fd { grpc_iomgr_cb_func on_done; void *on_done_user_data; struct grpc_fd *freelist_next; + + grpc_iomgr_closure on_done_iocb; + /*grpc_iomgr_closure *ready_iocb; XXX: the only one we need to allocate on + * the spot*/ + grpc_iomgr_closure shutdown_iocbs[2]; }; /* Create a wrapped file descriptor. diff --git a/src/core/iomgr/iomgr.c b/src/core/iomgr/iomgr.c index d22542fc91d..e74c32b219c 100644 --- a/src/core/iomgr/iomgr.c +++ b/src/core/iomgr/iomgr.c @@ -33,6 +33,7 @@ #include "src/core/iomgr/iomgr.h" +#include #include #include "src/core/iomgr/iomgr_internal.h" @@ -42,17 +43,10 @@ #include #include -typedef struct delayed_callback { - grpc_iomgr_cb_func cb; - void *cb_arg; - int success; - struct delayed_callback *next; -} delayed_callback; - static gpr_mu g_mu; static gpr_cv g_rcv; -static delayed_callback *g_cbs_head = NULL; -static delayed_callback *g_cbs_tail = NULL; +static grpc_iomgr_closure *g_cbs_head = NULL; +static grpc_iomgr_closure *g_cbs_tail = NULL; static int g_shutdown; static int g_refs; static gpr_event g_background_callback_executor_done; @@ -66,12 +60,18 @@ static void background_callback_executor(void *ignored) { gpr_timespec short_deadline = gpr_time_add(gpr_now(), gpr_time_from_millis(100)); if (g_cbs_head) { - delayed_callback *cb = g_cbs_head; - g_cbs_head = cb->next; + grpc_iomgr_closure *iocb = g_cbs_head; + int is_cb_ext_managed; + g_cbs_head = iocb->next; if (!g_cbs_head) g_cbs_tail = NULL; gpr_mu_unlock(&g_mu); - cb->cb(cb->cb_arg, cb->success); - gpr_free(cb); + /* capture the managed state, as the callback may deallocate itself */ + is_cb_ext_managed = iocb->is_ext_managed; + assert(iocb->success >= 0); + iocb->cb(iocb->cb_arg, iocb->success); + if (!is_cb_ext_managed) { + gpr_free(iocb); + } gpr_mu_lock(&g_mu); } else if (grpc_alarm_check(&g_mu, gpr_now(), &deadline)) { } else { @@ -103,7 +103,7 @@ void grpc_iomgr_init(void) { } void grpc_iomgr_shutdown(void) { - delayed_callback *cb; + grpc_iomgr_closure *iocb; gpr_timespec shutdown_deadline = gpr_time_add(gpr_now(), gpr_time_from_seconds(10)); @@ -114,13 +114,18 @@ void grpc_iomgr_shutdown(void) { gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed%s", g_refs, g_cbs_head ? " and executing final callbacks" : ""); while (g_cbs_head) { - cb = g_cbs_head; - g_cbs_head = cb->next; + int is_cb_ext_managed; + iocb = g_cbs_head; + g_cbs_head = iocb->next; if (!g_cbs_head) g_cbs_tail = NULL; gpr_mu_unlock(&g_mu); - cb->cb(cb->cb_arg, 0); - gpr_free(cb); + /* capture the managed state, as the callback may deallocate itself */ + is_cb_ext_managed = iocb->is_ext_managed; + iocb->cb(iocb->cb_arg, 0); + if (!is_cb_ext_managed) { + gpr_free(iocb); + } gpr_mu_lock(&g_mu); } if (g_refs) { @@ -167,42 +172,52 @@ void grpc_iomgr_unref(void) { gpr_mu_unlock(&g_mu); } -void grpc_iomgr_add_delayed_callback(grpc_iomgr_cb_func cb, void *cb_arg, - int success) { - delayed_callback *dcb = gpr_malloc(sizeof(delayed_callback)); - dcb->cb = cb; - dcb->cb_arg = cb_arg; - dcb->success = success; +grpc_iomgr_closure *grpc_iomgr_cb_create(grpc_iomgr_cb_func cb, void *cb_arg, + int is_ext_managed) { + grpc_iomgr_closure *iocb = gpr_malloc(sizeof(grpc_iomgr_closure)); + iocb->cb = cb; + iocb->cb_arg = cb_arg; + iocb->is_ext_managed = is_ext_managed; + iocb->success = -1; /* uninitialized */ + iocb->next = NULL; + return iocb; +} + +void grpc_iomgr_add_delayed_callback(grpc_iomgr_closure *iocb, int success) { + iocb->success = success; gpr_mu_lock(&g_mu); - dcb->next = NULL; + iocb->next = NULL; if (!g_cbs_tail) { - g_cbs_head = g_cbs_tail = dcb; + g_cbs_head = g_cbs_tail = iocb; } else { - g_cbs_tail->next = dcb; - g_cbs_tail = dcb; + g_cbs_tail->next = iocb; + g_cbs_tail = iocb; } gpr_mu_unlock(&g_mu); } -void grpc_iomgr_add_callback(grpc_iomgr_cb_func cb, void *cb_arg) { - grpc_iomgr_add_delayed_callback(cb, cb_arg, 1); + +void grpc_iomgr_add_callback(grpc_iomgr_closure *iocb) { + grpc_iomgr_add_delayed_callback(iocb, 1); } + int grpc_maybe_call_delayed_callbacks(gpr_mu *drop_mu, int success) { int n = 0; gpr_mu *retake_mu = NULL; - delayed_callback *cb; + grpc_iomgr_closure *iocb; for (;;) { + int is_cb_ext_managed; /* check for new work */ if (!gpr_mu_trylock(&g_mu)) { break; } - cb = g_cbs_head; - if (!cb) { + iocb = g_cbs_head; + if (!iocb) { gpr_mu_unlock(&g_mu); break; } - g_cbs_head = cb->next; + g_cbs_head = iocb->next; if (!g_cbs_head) g_cbs_tail = NULL; gpr_mu_unlock(&g_mu); /* if we have a mutex to drop, do so before executing work */ @@ -211,8 +226,13 @@ int grpc_maybe_call_delayed_callbacks(gpr_mu *drop_mu, int success) { retake_mu = drop_mu; drop_mu = NULL; } - cb->cb(cb->cb_arg, success && cb->success); - gpr_free(cb); + /* capture the managed state, as the callback may deallocate itself */ + is_cb_ext_managed = iocb->is_ext_managed; + assert(iocb->success >= 0); + iocb->cb(iocb->cb_arg, success && iocb->success); + if (!is_cb_ext_managed) { + gpr_free(iocb); + } n++; } if (retake_mu) { diff --git a/src/core/iomgr/iomgr.h b/src/core/iomgr/iomgr.h index 1f5d23fdda4..86bb5f35839 100644 --- a/src/core/iomgr/iomgr.h +++ b/src/core/iomgr/iomgr.h @@ -37,11 +37,22 @@ /* gRPC Callback definition */ typedef void (*grpc_iomgr_cb_func)(void *arg, int success); +typedef struct grpc_iomgr_closure { + grpc_iomgr_cb_func cb; + void *cb_arg; + int success; + int is_ext_managed; /** is memory being managed externally? */ + struct grpc_iomgr_closure *next; /** Do not touch */ +} grpc_iomgr_closure; + +grpc_iomgr_closure *grpc_iomgr_cb_create(grpc_iomgr_cb_func cb, void *cb_arg, + int is_ext_managed); + void grpc_iomgr_init(void); void grpc_iomgr_shutdown(void); /* This function is called from within a callback or from anywhere else and causes the invocation of a callback at some point in the future */ -void grpc_iomgr_add_callback(grpc_iomgr_cb_func cb, void *cb_arg); +void grpc_iomgr_add_callback(grpc_iomgr_closure *iocb); #endif /* GRPC_INTERNAL_CORE_IOMGR_IOMGR_H */ diff --git a/src/core/iomgr/iomgr_internal.h b/src/core/iomgr/iomgr_internal.h index 07923258b9b..25a731d58c3 100644 --- a/src/core/iomgr/iomgr_internal.h +++ b/src/core/iomgr/iomgr_internal.h @@ -35,12 +35,10 @@ #define GRPC_INTERNAL_CORE_IOMGR_IOMGR_INTERNAL_H #include "src/core/iomgr/iomgr.h" -#include "src/core/iomgr/iomgr_internal.h" #include int grpc_maybe_call_delayed_callbacks(gpr_mu *drop_mu, int success); -void grpc_iomgr_add_delayed_callback(grpc_iomgr_cb_func cb, void *cb_arg, - int success); +void grpc_iomgr_add_delayed_callback(grpc_iomgr_closure *iocb, int success); void grpc_iomgr_ref(void); void grpc_iomgr_unref(void); diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c index 826c792990e..7a2ba4be060 100644 --- a/src/core/iomgr/pollset_posix.c +++ b/src/core/iomgr/pollset_posix.c @@ -257,6 +257,7 @@ typedef struct grpc_unary_promote_args { const grpc_pollset_vtable *original_vtable; grpc_pollset *pollset; grpc_fd *fd; + grpc_iomgr_closure promotion_iocb; } grpc_unary_promote_args; static void unary_poll_do_promote(void *args, int success) { @@ -279,7 +280,7 @@ static void unary_poll_do_promote(void *args, int success) { /* First we need to ensure that nobody is polling concurrently */ while (pollset->counter != 0) { grpc_pollset_kick(pollset); - grpc_iomgr_add_callback(unary_poll_do_promote, up_args); + grpc_iomgr_add_callback(&up_args->promotion_iocb); gpr_mu_unlock(&pollset->mu); return; } @@ -363,7 +364,10 @@ static void unary_poll_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) { up_args->pollset = pollset; up_args->fd = fd; up_args->original_vtable = pollset->vtable; - grpc_iomgr_add_callback(unary_poll_do_promote, up_args); + up_args->promotion_iocb.cb = unary_poll_do_promote; + up_args->promotion_iocb.cb_arg = up_args; + up_args->promotion_iocb.is_ext_managed = 1; + grpc_iomgr_add_callback(&up_args->promotion_iocb); grpc_pollset_kick(pollset); } diff --git a/src/core/iomgr/socket_windows.c b/src/core/iomgr/socket_windows.c index ee5150a6967..92fcf7de2ab 100644 --- a/src/core/iomgr/socket_windows.c +++ b/src/core/iomgr/socket_windows.c @@ -62,15 +62,18 @@ grpc_winsocket *grpc_winsocket_create(SOCKET socket) { int grpc_winsocket_shutdown(grpc_winsocket *socket) { int callbacks_set = 0; gpr_mu_lock(&socket->state_mu); + socket->shutdown_iocb.is_ext_managed = 1; /* GPR_TRUE */ if (socket->read_info.cb) { callbacks_set++; - grpc_iomgr_add_delayed_callback(socket->read_info.cb, - socket->read_info.opaque, 0); + socket->shutdown_iocb.cb = socket->read_info.cb; + socket->shutdown_iocb.cb_arg = socket->read_info.opaque; + grpc_iomgr_add_delayed_callback(socket->shutdown_iocb, 0); } if (socket->write_info.cb) { callbacks_set++; - grpc_iomgr_add_delayed_callback(socket->write_info.cb, - socket->write_info.opaque, 0); + socket->shutdown_iocb.cb = socket->write_info.cb; + socket->shutdown_iocb.cb_arg = socket->write_info.opaque; + grpc_iomgr_add_delayed_callback(socket->shutdown_iocb, 0); } gpr_mu_unlock(&socket->state_mu); return callbacks_set; diff --git a/src/core/iomgr/socket_windows.h b/src/core/iomgr/socket_windows.h index b27eb14219c..8fd8ae97b6d 100644 --- a/src/core/iomgr/socket_windows.h +++ b/src/core/iomgr/socket_windows.h @@ -93,6 +93,8 @@ typedef struct grpc_winsocket { there is a pending operation that the IO Completion Port will have to wait for. The socket will be collected at that time. */ int orphan; + + grpc_iomgr_closure shutdown_iocb; } grpc_winsocket; /* Create a wrapped windows handle. This takes ownership of it, meaning that diff --git a/src/core/iomgr/tcp_posix.c b/src/core/iomgr/tcp_posix.c index cd6b2ecae6f..e2cda527339 100644 --- a/src/core/iomgr/tcp_posix.c +++ b/src/core/iomgr/tcp_posix.c @@ -280,6 +280,8 @@ typedef struct { grpc_iomgr_closure read_closure; grpc_iomgr_closure write_closure; + + grpc_iomgr_closure handle_read_iocb; } grpc_tcp; static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success); @@ -443,7 +445,8 @@ static void grpc_tcp_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, tcp->finished_edge = 0; grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure); } else { - grpc_iomgr_add_callback(grpc_tcp_handle_read, tcp); + tcp->handle_read_iocb.cb_arg = tcp; + grpc_iomgr_add_callback(&tcp->handle_read_iocb); } } @@ -592,6 +595,9 @@ grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size) { tcp->read_closure.cb_arg = tcp; tcp->write_closure.cb = grpc_tcp_handle_write; tcp->write_closure.cb_arg = tcp; + + tcp->handle_read_iocb.cb = grpc_tcp_handle_read; + tcp->handle_read_iocb.is_ext_managed = 1; return &tcp->base; } diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c index ae22bf47a0f..e9229f06942 100644 --- a/src/core/security/credentials.c +++ b/src/core/security/credentials.c @@ -832,8 +832,10 @@ static void fake_oauth2_get_request_metadata(grpc_credentials *creds, if (c->is_async) { grpc_iomgr_add_callback( + grpc_iomgr_cb_create( on_simulated_token_fetch_done, - grpc_credentials_metadata_request_create(creds, cb, user_data)); + grpc_credentials_metadata_request_create(creds, cb, user_data), + 0 /*GPR_FALSE*/)); } else { cb(user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK); } diff --git a/src/core/surface/call.c b/src/core/surface/call.c index e3995a407b8..99e14e3e158 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -226,6 +226,7 @@ struct grpc_call { gpr_slice_buffer incoming_message; gpr_uint32 incoming_message_length; + grpc_iomgr_closure destroy_iocb; }; #define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1)) @@ -367,7 +368,10 @@ void grpc_call_internal_unref(grpc_call *c, int allow_immediate_deletion) { if (allow_immediate_deletion) { destroy_call(c, 1); } else { - grpc_iomgr_add_callback(destroy_call, c); + c->destroy_iocb.cb = destroy_call; + c->destroy_iocb.cb_arg = c; + c->destroy_iocb.is_ext_managed = 1; /* GPR_TRUE */ + grpc_iomgr_add_callback(&c->destroy_iocb); } } } diff --git a/src/core/surface/channel.c b/src/core/surface/channel.c index be9da2b7f95..8e593b8073d 100644 --- a/src/core/surface/channel.c +++ b/src/core/surface/channel.c @@ -61,6 +61,7 @@ struct grpc_channel { gpr_mu registered_call_mu; registered_call *registered_calls; + grpc_iomgr_closure destroy_iocb; }; #define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c) + 1)) @@ -193,7 +194,10 @@ static void destroy_channel(void *p, int ok) { void grpc_channel_internal_unref(grpc_channel *channel) { if (gpr_unref(&channel->refs)) { - grpc_iomgr_add_callback(destroy_channel, channel); + channel->destroy_iocb.cb = destroy_channel; + channel->destroy_iocb.cb_arg = channel; + channel->destroy_iocb.is_ext_managed = 1; + grpc_iomgr_add_callback(&channel->destroy_iocb); } } diff --git a/src/core/surface/server.c b/src/core/surface/server.c index 60606c75e4d..a10b9214563 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -122,6 +122,8 @@ struct channel_data { channel_registered_method *registered_methods; gpr_uint32 registered_method_slots; gpr_uint32 registered_method_max_probes; + grpc_iomgr_closure finish_shutdown_channel_iocb; + grpc_iomgr_closure finish_destroy_channel_iocb; }; struct grpc_server { @@ -304,7 +306,10 @@ static void destroy_channel(channel_data *chand) { GPR_ASSERT(chand->server != NULL); orphan_channel(chand); server_ref(chand->server); - grpc_iomgr_add_callback(finish_destroy_channel, chand); + chand->finish_destroy_channel_iocb.cb = finish_destroy_channel; + chand->finish_destroy_channel_iocb.cb_arg = chand; + chand->finish_destroy_channel_iocb.is_ext_managed = 1; + grpc_iomgr_add_callback(&chand->finish_destroy_channel_iocb); } static void finish_start_new_rpc_and_unlock(grpc_server *server, @@ -416,7 +421,8 @@ static void server_on_recv(void *ptr, int success) { gpr_mu_lock(&chand->server->mu); if (calld->state == NOT_STARTED) { calld->state = ZOMBIED; - grpc_iomgr_add_callback(kill_zombie, elem); + grpc_iomgr_add_callback( + grpc_iomgr_cb_create(kill_zombie, elem, 0 /* GPR_FALSE */)); } gpr_mu_unlock(&chand->server->mu); break; @@ -424,11 +430,13 @@ static void server_on_recv(void *ptr, int success) { gpr_mu_lock(&chand->server->mu); if (calld->state == NOT_STARTED) { calld->state = ZOMBIED; - grpc_iomgr_add_callback(kill_zombie, elem); + grpc_iomgr_add_callback( + grpc_iomgr_cb_create(kill_zombie, elem, 0 /* GPR_FALSE */)); } else if (calld->state == PENDING) { call_list_remove(calld, PENDING_START); calld->state = ZOMBIED; - grpc_iomgr_add_callback(kill_zombie, elem); + grpc_iomgr_add_callback( + grpc_iomgr_cb_create(kill_zombie, elem, 0 /* GPR_FALSE */)); } gpr_mu_unlock(&chand->server->mu); break; @@ -502,7 +510,10 @@ static void finish_shutdown_channel(void *cd, int success) { static void shutdown_channel(channel_data *chand) { grpc_channel_internal_ref(chand->channel); - grpc_iomgr_add_callback(finish_shutdown_channel, chand); + chand->finish_shutdown_channel_iocb.cb = finish_shutdown_channel; + chand->finish_shutdown_channel_iocb.cb_arg = chand; + chand->finish_shutdown_channel_iocb.is_ext_managed = 1; + grpc_iomgr_add_callback(&chand->finish_shutdown_channel_iocb); } static void init_call_elem(grpc_call_element *elem, @@ -943,8 +954,10 @@ void grpc_server_destroy(grpc_server *server) { gpr_log(GPR_DEBUG, "server destroys call %p", calld->call); calld->state = ZOMBIED; grpc_iomgr_add_callback( + grpc_iomgr_cb_create( kill_zombie, - grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0)); + grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0), + 0)); /* XXX */ } for (c = server->root_channel_data.next; c != &server->root_channel_data; diff --git a/test/core/iomgr/alarm_test.c b/test/core/iomgr/alarm_test.c index e677ba30dde..e416c794251 100644 --- a/test/core/iomgr/alarm_test.c +++ b/test/core/iomgr/alarm_test.c @@ -55,6 +55,7 @@ void no_op_cb(void *arg, int success) {} typedef struct { gpr_cv cv; gpr_mu mu; + grpc_iomgr_closure *iocb; int counter; int done_success_ctr; int done_cancel_ctr; @@ -81,7 +82,10 @@ static void alarm_cb(void *arg /* alarm_arg */, int success) { a->success = success; gpr_cv_signal(&a->cv); gpr_mu_unlock(&a->mu); - grpc_iomgr_add_callback(followup_cb, &a->fcb_arg); + a->iocb->cb = followup_cb; + a->iocb->cb_arg = &a->fcb_arg; + a->iocb->is_ext_managed = 1; + grpc_iomgr_add_callback(a->iocb); } /* Test grpc_alarm add and cancel. */ @@ -107,6 +111,7 @@ static void test_grpc_alarm(void) { arg.done = 0; gpr_mu_init(&arg.mu); gpr_cv_init(&arg.cv); + arg.iocb = gpr_malloc(sizeof(grpc_iomgr_closure)); gpr_event_init(&arg.fcb_arg); grpc_alarm_init(&alarm, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100), alarm_cb, &arg, @@ -148,6 +153,7 @@ static void test_grpc_alarm(void) { } gpr_cv_destroy(&arg.cv); gpr_mu_destroy(&arg.mu); + gpr_free(arg.iocb); arg2.counter = 0; arg2.success = SUCCESS_NOT_SET; @@ -156,6 +162,8 @@ static void test_grpc_alarm(void) { arg2.done = 0; gpr_mu_init(&arg2.mu); gpr_cv_init(&arg2.cv); + arg2.iocb = gpr_malloc(sizeof(grpc_iomgr_closure)); + gpr_event_init(&arg2.fcb_arg); grpc_alarm_init(&alarm_to_cancel, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100), @@ -206,6 +214,7 @@ static void test_grpc_alarm(void) { } gpr_cv_destroy(&arg2.cv); gpr_mu_destroy(&arg2.mu); + gpr_free(arg2.iocb); grpc_iomgr_shutdown(); } From a30020f00996735ce8890dca534a31b8e97b5889 Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Wed, 27 May 2015 19:21:01 -0700 Subject: [PATCH 13/52] Comments addressed. --- src/core/channel/child_channel.c | 2 - src/core/iomgr/fd_posix.c | 51 +++++++-------- src/core/iomgr/fd_posix.h | 2 - src/core/iomgr/iomgr.c | 104 ++++++++++++++++--------------- src/core/iomgr/iomgr.h | 11 ++-- src/core/iomgr/pollset_posix.c | 1 - src/core/iomgr/socket_windows.c | 9 ++- src/core/iomgr/tcp_posix.c | 1 - src/core/security/credentials.c | 11 ++-- src/core/surface/call.c | 1 - src/core/surface/channel.c | 1 - src/core/surface/server.c | 34 ++++++---- test/core/iomgr/alarm_test.c | 16 +++-- 13 files changed, 123 insertions(+), 121 deletions(-) diff --git a/src/core/channel/child_channel.c b/src/core/channel/child_channel.c index 5679a8c81aa..213a4b881d3 100644 --- a/src/core/channel/child_channel.c +++ b/src/core/channel/child_channel.c @@ -218,7 +218,6 @@ static void maybe_destroy_channel(grpc_child_channel *channel) { !chand->sending_farewell && !chand->calling_back) { chand->finally_destroy_channel_iocb.cb = finally_destroy_channel; chand->finally_destroy_channel_iocb.cb_arg = channel; - chand->finally_destroy_channel_iocb.is_ext_managed = 1; /* GPR_TRUE */ grpc_iomgr_add_callback(&chand->finally_destroy_channel_iocb); } else if (chand->destroyed && !chand->disconnected && chand->active_calls == 0 && !chand->sending_farewell && @@ -226,7 +225,6 @@ static void maybe_destroy_channel(grpc_child_channel *channel) { chand->sending_farewell = 1; chand->send_farewells_iocb.cb = send_farewells; chand->send_farewells_iocb.cb_arg = channel; - chand->send_farewells_iocb.is_ext_managed = 1; /* GPR_TRUE */ grpc_iomgr_add_callback(&chand->send_farewells_iocb); } } diff --git a/src/core/iomgr/fd_posix.c b/src/core/iomgr/fd_posix.c index 3509d021eec..672b321b951 100644 --- a/src/core/iomgr/fd_posix.c +++ b/src/core/iomgr/fd_posix.c @@ -118,9 +118,8 @@ static void unref_by(grpc_fd *fd, int n) { gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n); if (old == n) { close(fd->fd); - fd->on_done_iocb.cb = fd->on_done; - fd->on_done_iocb.cb_arg = fd->on_done_user_data; - fd->on_done_iocb.is_ext_managed = 1; + grpc_iomgr_closure_init(&fd->on_done_iocb, fd->on_done, + fd->on_done_user_data); grpc_iomgr_add_callback(&fd->on_done_iocb); freelist_fd(fd); grpc_iomgr_unref(); @@ -199,26 +198,20 @@ void grpc_fd_ref(grpc_fd *fd) { ref_by(fd, 2); } void grpc_fd_unref(grpc_fd *fd) { unref_by(fd, 2); } -static void make_callback(grpc_iomgr_cb_func cb, void *arg, int success, - int allow_synchronous_callback, - grpc_iomgr_closure *iocb) { +static void process_callback(grpc_iomgr_closure *closure, int success, + int allow_synchronous_callback) { if (allow_synchronous_callback) { - cb(arg, success); + closure->cb(closure->cb_arg, success); } else { - /* !iocb: allocate -> managed by iomgr - * iocb: "iocb" holds an instance managed by fd_posix */ - iocb = grpc_iomgr_cb_create(cb, arg, !iocb /* is_ext_managed */); - grpc_iomgr_add_delayed_callback(iocb, success); + grpc_iomgr_add_delayed_callback(closure, success); } } -static void make_callbacks(grpc_iomgr_closure *callbacks, size_t n, int success, - int allow_synchronous_callback, - grpc_iomgr_closure *iocbs) { +static void process_callbacks(grpc_iomgr_closure *callbacks, size_t n, + int success, int allow_synchronous_callback) { size_t i; for (i = 0; i < n; i++) { - make_callback(callbacks[i].cb, callbacks[i].cb_arg, success, - allow_synchronous_callback, iocbs + i); + process_callback(callbacks + i, success, allow_synchronous_callback); } } @@ -245,9 +238,9 @@ static void notify_on(grpc_fd *fd, gpr_atm *st, grpc_iomgr_closure *closure, case READY: assert(gpr_atm_no_barrier_load(st) == READY); gpr_atm_rel_store(st, NOT_READY); - make_callback(closure->cb, closure->cb_arg, - !gpr_atm_acq_load(&fd->shutdown), - allow_synchronous_callback, NULL); + closure->success = -1; + process_callback(closure, !gpr_atm_acq_load(&fd->shutdown), + allow_synchronous_callback); return; default: /* WAITING */ /* upcallptr was set to a different closure. This is an error! */ @@ -291,29 +284,31 @@ static void set_ready(grpc_fd *fd, gpr_atm *st, /* only one set_ready can be active at once (but there may be a racing notify_on) */ int success; - grpc_iomgr_closure cb; + grpc_iomgr_closure closure; size_t ncb = 0; - grpc_iomgr_closure *ready_iocb; + gpr_mu_lock(&fd->set_state_mu); - set_ready_locked(st, &cb, &ncb); + set_ready_locked(st, &closure, &ncb); gpr_mu_unlock(&fd->set_state_mu); success = !gpr_atm_acq_load(&fd->shutdown); assert(ncb <= 1); - ready_iocb = grpc_iomgr_cb_create(cb.cb, cb.cb_arg, 0); - make_callbacks(&cb, ncb, success, allow_synchronous_callback, ready_iocb); + if (ncb > 0) { + grpc_iomgr_closure *managed_cb = gpr_malloc(sizeof(grpc_iomgr_closure)); + grpc_iomgr_managed_closure_init(managed_cb, closure.cb, closure.cb_arg); + process_callbacks(managed_cb, ncb, success, allow_synchronous_callback); + } } void grpc_fd_shutdown(grpc_fd *fd) { - grpc_iomgr_closure cb[2]; size_t ncb = 0; gpr_mu_lock(&fd->set_state_mu); GPR_ASSERT(!gpr_atm_no_barrier_load(&fd->shutdown)); gpr_atm_rel_store(&fd->shutdown, 1); - set_ready_locked(&fd->readst, cb, &ncb); - set_ready_locked(&fd->writest, cb, &ncb); + set_ready_locked(&fd->readst, fd->shutdown_iocbs, &ncb); + set_ready_locked(&fd->writest, fd->shutdown_iocbs, &ncb); gpr_mu_unlock(&fd->set_state_mu); assert(ncb <= 2); - make_callbacks(cb, ncb, 0, 0, fd->shutdown_iocbs); + process_callbacks(fd->shutdown_iocbs, ncb, 0, 0); } void grpc_fd_notify_on_read(grpc_fd *fd, grpc_iomgr_closure *closure) { diff --git a/src/core/iomgr/fd_posix.h b/src/core/iomgr/fd_posix.h index 59bd01ce0f2..2d9c3245e34 100644 --- a/src/core/iomgr/fd_posix.h +++ b/src/core/iomgr/fd_posix.h @@ -96,8 +96,6 @@ struct grpc_fd { struct grpc_fd *freelist_next; grpc_iomgr_closure on_done_iocb; - /*grpc_iomgr_closure *ready_iocb; XXX: the only one we need to allocate on - * the spot*/ grpc_iomgr_closure shutdown_iocbs[2]; }; diff --git a/src/core/iomgr/iomgr.c b/src/core/iomgr/iomgr.c index e74c32b219c..1d6fa9053eb 100644 --- a/src/core/iomgr/iomgr.c +++ b/src/core/iomgr/iomgr.c @@ -60,18 +60,12 @@ static void background_callback_executor(void *ignored) { gpr_timespec short_deadline = gpr_time_add(gpr_now(), gpr_time_from_millis(100)); if (g_cbs_head) { - grpc_iomgr_closure *iocb = g_cbs_head; - int is_cb_ext_managed; - g_cbs_head = iocb->next; + grpc_iomgr_closure *closure = g_cbs_head; + g_cbs_head = closure->next; if (!g_cbs_head) g_cbs_tail = NULL; gpr_mu_unlock(&g_mu); - /* capture the managed state, as the callback may deallocate itself */ - is_cb_ext_managed = iocb->is_ext_managed; - assert(iocb->success >= 0); - iocb->cb(iocb->cb_arg, iocb->success); - if (!is_cb_ext_managed) { - gpr_free(iocb); - } + assert(closure->success >= 0); + closure->cb(closure->cb_arg, closure->success); gpr_mu_lock(&g_mu); } else if (grpc_alarm_check(&g_mu, gpr_now(), &deadline)) { } else { @@ -103,7 +97,7 @@ void grpc_iomgr_init(void) { } void grpc_iomgr_shutdown(void) { - grpc_iomgr_closure *iocb; + grpc_iomgr_closure *closure; gpr_timespec shutdown_deadline = gpr_time_add(gpr_now(), gpr_time_from_seconds(10)); @@ -114,18 +108,12 @@ void grpc_iomgr_shutdown(void) { gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed%s", g_refs, g_cbs_head ? " and executing final callbacks" : ""); while (g_cbs_head) { - int is_cb_ext_managed; - iocb = g_cbs_head; - g_cbs_head = iocb->next; + closure = g_cbs_head; + g_cbs_head = closure->next; if (!g_cbs_head) g_cbs_tail = NULL; gpr_mu_unlock(&g_mu); - /* capture the managed state, as the callback may deallocate itself */ - is_cb_ext_managed = iocb->is_ext_managed; - iocb->cb(iocb->cb_arg, 0); - if (!is_cb_ext_managed) { - gpr_free(iocb); - } + closure->cb(closure->cb_arg, 0); gpr_mu_lock(&g_mu); } if (g_refs) { @@ -172,52 +160,75 @@ void grpc_iomgr_unref(void) { gpr_mu_unlock(&g_mu); } -grpc_iomgr_closure *grpc_iomgr_cb_create(grpc_iomgr_cb_func cb, void *cb_arg, - int is_ext_managed) { - grpc_iomgr_closure *iocb = gpr_malloc(sizeof(grpc_iomgr_closure)); - iocb->cb = cb; - iocb->cb_arg = cb_arg; - iocb->is_ext_managed = is_ext_managed; - iocb->success = -1; /* uninitialized */ - iocb->next = NULL; - return iocb; + +void grpc_iomgr_closure_init(grpc_iomgr_closure *closure, grpc_iomgr_cb_func cb, + void *cb_arg) { + closure->cb = cb; + closure->cb_arg = cb_arg; + closure->success = -1; /* uninitialized */ + closure->next = NULL; +} + +typedef struct { + grpc_iomgr_closure managed; + grpc_iomgr_closure *manager; +} managed_closure_arg; + +static void closure_manager_func(void *arg, int success) { + managed_closure_arg *mc_arg = (managed_closure_arg*) arg; + + mc_arg->managed.cb(mc_arg->managed.cb_arg, success); + gpr_free(mc_arg->manager); + gpr_free(mc_arg); } -void grpc_iomgr_add_delayed_callback(grpc_iomgr_closure *iocb, int success) { - iocb->success = success; +void grpc_iomgr_managed_closure_init(grpc_iomgr_closure *manager, + grpc_iomgr_cb_func managed_cb, + void *managed_cb_arg) { + managed_closure_arg *managed_arg = gpr_malloc(sizeof(managed_closure_arg)); + + managed_arg->managed.cb = managed_cb; + managed_arg->managed.cb_arg = managed_cb_arg; + managed_arg->manager= manager; + + grpc_iomgr_closure_init(manager, closure_manager_func, managed_arg); +} + + +void grpc_iomgr_add_delayed_callback(grpc_iomgr_closure *closure, int success) { + closure->success = success; gpr_mu_lock(&g_mu); - iocb->next = NULL; + closure->next = NULL; if (!g_cbs_tail) { - g_cbs_head = g_cbs_tail = iocb; + g_cbs_head = g_cbs_tail = closure; } else { - g_cbs_tail->next = iocb; - g_cbs_tail = iocb; + g_cbs_tail->next = closure; + g_cbs_tail = closure; } gpr_mu_unlock(&g_mu); } -void grpc_iomgr_add_callback(grpc_iomgr_closure *iocb) { - grpc_iomgr_add_delayed_callback(iocb, 1); +void grpc_iomgr_add_callback(grpc_iomgr_closure *closure) { + grpc_iomgr_add_delayed_callback(closure, 1); } int grpc_maybe_call_delayed_callbacks(gpr_mu *drop_mu, int success) { int n = 0; gpr_mu *retake_mu = NULL; - grpc_iomgr_closure *iocb; + grpc_iomgr_closure *closure; for (;;) { - int is_cb_ext_managed; /* check for new work */ if (!gpr_mu_trylock(&g_mu)) { break; } - iocb = g_cbs_head; - if (!iocb) { + closure = g_cbs_head; + if (!closure) { gpr_mu_unlock(&g_mu); break; } - g_cbs_head = iocb->next; + g_cbs_head = closure->next; if (!g_cbs_head) g_cbs_tail = NULL; gpr_mu_unlock(&g_mu); /* if we have a mutex to drop, do so before executing work */ @@ -226,13 +237,8 @@ int grpc_maybe_call_delayed_callbacks(gpr_mu *drop_mu, int success) { retake_mu = drop_mu; drop_mu = NULL; } - /* capture the managed state, as the callback may deallocate itself */ - is_cb_ext_managed = iocb->is_ext_managed; - assert(iocb->success >= 0); - iocb->cb(iocb->cb_arg, success && iocb->success); - if (!is_cb_ext_managed) { - gpr_free(iocb); - } + assert(closure->success >= 0); + closure->cb(closure->cb_arg, success && closure->success); n++; } if (retake_mu) { diff --git a/src/core/iomgr/iomgr.h b/src/core/iomgr/iomgr.h index 86bb5f35839..437e8cf9a81 100644 --- a/src/core/iomgr/iomgr.h +++ b/src/core/iomgr/iomgr.h @@ -41,18 +41,21 @@ typedef struct grpc_iomgr_closure { grpc_iomgr_cb_func cb; void *cb_arg; int success; - int is_ext_managed; /** is memory being managed externally? */ struct grpc_iomgr_closure *next; /** Do not touch */ } grpc_iomgr_closure; -grpc_iomgr_closure *grpc_iomgr_cb_create(grpc_iomgr_cb_func cb, void *cb_arg, - int is_ext_managed); +void grpc_iomgr_closure_init(grpc_iomgr_closure *closure, grpc_iomgr_cb_func cb, + void *cb_arg); + +void grpc_iomgr_managed_closure_init(grpc_iomgr_closure *manager, + grpc_iomgr_cb_func managed_cb, + void *managed_cb_arg); void grpc_iomgr_init(void); void grpc_iomgr_shutdown(void); /* This function is called from within a callback or from anywhere else and causes the invocation of a callback at some point in the future */ -void grpc_iomgr_add_callback(grpc_iomgr_closure *iocb); +void grpc_iomgr_add_callback(grpc_iomgr_closure *closure); #endif /* GRPC_INTERNAL_CORE_IOMGR_IOMGR_H */ diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c index 7a2ba4be060..db17012df00 100644 --- a/src/core/iomgr/pollset_posix.c +++ b/src/core/iomgr/pollset_posix.c @@ -366,7 +366,6 @@ static void unary_poll_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) { up_args->original_vtable = pollset->vtable; up_args->promotion_iocb.cb = unary_poll_do_promote; up_args->promotion_iocb.cb_arg = up_args; - up_args->promotion_iocb.is_ext_managed = 1; grpc_iomgr_add_callback(&up_args->promotion_iocb); grpc_pollset_kick(pollset); diff --git a/src/core/iomgr/socket_windows.c b/src/core/iomgr/socket_windows.c index 92fcf7de2ab..f0bd0d8d69a 100644 --- a/src/core/iomgr/socket_windows.c +++ b/src/core/iomgr/socket_windows.c @@ -62,17 +62,16 @@ grpc_winsocket *grpc_winsocket_create(SOCKET socket) { int grpc_winsocket_shutdown(grpc_winsocket *socket) { int callbacks_set = 0; gpr_mu_lock(&socket->state_mu); - socket->shutdown_iocb.is_ext_managed = 1; /* GPR_TRUE */ if (socket->read_info.cb) { callbacks_set++; - socket->shutdown_iocb.cb = socket->read_info.cb; - socket->shutdown_iocb.cb_arg = socket->read_info.opaque; + grpc_iomgr_closure_init(&socket->shutdown_iocb, socket->read_info.cb, + socket->read_info.opaque); grpc_iomgr_add_delayed_callback(socket->shutdown_iocb, 0); } if (socket->write_info.cb) { callbacks_set++; - socket->shutdown_iocb.cb = socket->write_info.cb; - socket->shutdown_iocb.cb_arg = socket->write_info.opaque; + grpc_iomgr_closure_init(&socket->shutdown_iocb, socket->write_info.cb, + socket->write_info.opaque); grpc_iomgr_add_delayed_callback(socket->shutdown_iocb, 0); } gpr_mu_unlock(&socket->state_mu); diff --git a/src/core/iomgr/tcp_posix.c b/src/core/iomgr/tcp_posix.c index e2cda527339..2978c2c370f 100644 --- a/src/core/iomgr/tcp_posix.c +++ b/src/core/iomgr/tcp_posix.c @@ -597,7 +597,6 @@ grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size) { tcp->write_closure.cb_arg = tcp; tcp->handle_read_iocb.cb = grpc_tcp_handle_read; - tcp->handle_read_iocb.is_ext_managed = 1; return &tcp->base; } diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c index e9229f06942..5e595899c3e 100644 --- a/src/core/security/credentials.c +++ b/src/core/security/credentials.c @@ -831,11 +831,12 @@ static void fake_oauth2_get_request_metadata(grpc_credentials *creds, grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds; if (c->is_async) { - grpc_iomgr_add_callback( - grpc_iomgr_cb_create( - on_simulated_token_fetch_done, - grpc_credentials_metadata_request_create(creds, cb, user_data), - 0 /*GPR_FALSE*/)); + grpc_iomgr_closure *on_simulated_token_fetch_done_closure = + gpr_malloc(sizeof(grpc_iomgr_closure)); + grpc_iomgr_managed_closure_init( + on_simulated_token_fetch_done_closure, on_simulated_token_fetch_done, + grpc_credentials_metadata_request_create(creds, cb, user_data)); + grpc_iomgr_add_callback(on_simulated_token_fetch_done_closure); } else { cb(user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK); } diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 99e14e3e158..3a739315a2f 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -370,7 +370,6 @@ void grpc_call_internal_unref(grpc_call *c, int allow_immediate_deletion) { } else { c->destroy_iocb.cb = destroy_call; c->destroy_iocb.cb_arg = c; - c->destroy_iocb.is_ext_managed = 1; /* GPR_TRUE */ grpc_iomgr_add_callback(&c->destroy_iocb); } } diff --git a/src/core/surface/channel.c b/src/core/surface/channel.c index 8e593b8073d..d018db7bb0e 100644 --- a/src/core/surface/channel.c +++ b/src/core/surface/channel.c @@ -196,7 +196,6 @@ void grpc_channel_internal_unref(grpc_channel *channel) { if (gpr_unref(&channel->refs)) { channel->destroy_iocb.cb = destroy_channel; channel->destroy_iocb.cb_arg = channel; - channel->destroy_iocb.is_ext_managed = 1; grpc_iomgr_add_callback(&channel->destroy_iocb); } } diff --git a/src/core/surface/server.c b/src/core/surface/server.c index a10b9214563..378d50486bf 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -308,7 +308,6 @@ static void destroy_channel(channel_data *chand) { server_ref(chand->server); chand->finish_destroy_channel_iocb.cb = finish_destroy_channel; chand->finish_destroy_channel_iocb.cb_arg = chand; - chand->finish_destroy_channel_iocb.is_ext_managed = 1; grpc_iomgr_add_callback(&chand->finish_destroy_channel_iocb); } @@ -420,23 +419,29 @@ static void server_on_recv(void *ptr, int success) { case GRPC_STREAM_RECV_CLOSED: gpr_mu_lock(&chand->server->mu); if (calld->state == NOT_STARTED) { + grpc_iomgr_closure *kill_zombie_closure = + gpr_malloc(sizeof(grpc_iomgr_closure)); calld->state = ZOMBIED; - grpc_iomgr_add_callback( - grpc_iomgr_cb_create(kill_zombie, elem, 0 /* GPR_FALSE */)); + grpc_iomgr_managed_closure_init(kill_zombie_closure, kill_zombie, elem); + grpc_iomgr_add_callback(kill_zombie_closure); } gpr_mu_unlock(&chand->server->mu); break; case GRPC_STREAM_CLOSED: gpr_mu_lock(&chand->server->mu); if (calld->state == NOT_STARTED) { + grpc_iomgr_closure *kill_zombie_closure = + gpr_malloc(sizeof(grpc_iomgr_closure)); calld->state = ZOMBIED; - grpc_iomgr_add_callback( - grpc_iomgr_cb_create(kill_zombie, elem, 0 /* GPR_FALSE */)); + grpc_iomgr_managed_closure_init(kill_zombie_closure, kill_zombie, elem); + grpc_iomgr_add_callback(kill_zombie_closure); } else if (calld->state == PENDING) { + grpc_iomgr_closure *kill_zombie_closure = + gpr_malloc(sizeof(grpc_iomgr_closure)); call_list_remove(calld, PENDING_START); calld->state = ZOMBIED; - grpc_iomgr_add_callback( - grpc_iomgr_cb_create(kill_zombie, elem, 0 /* GPR_FALSE */)); + grpc_iomgr_managed_closure_init(kill_zombie_closure, kill_zombie, elem); + grpc_iomgr_add_callback(kill_zombie_closure); } gpr_mu_unlock(&chand->server->mu); break; @@ -512,7 +517,6 @@ static void shutdown_channel(channel_data *chand) { grpc_channel_internal_ref(chand->channel); chand->finish_shutdown_channel_iocb.cb = finish_shutdown_channel; chand->finish_shutdown_channel_iocb.cb_arg = chand; - chand->finish_shutdown_channel_iocb.is_ext_managed = 1; grpc_iomgr_add_callback(&chand->finish_shutdown_channel_iocb); } @@ -951,13 +955,17 @@ void grpc_server_destroy(grpc_server *server) { while ((calld = call_list_remove_head(&server->lists[PENDING_START], PENDING_START)) != NULL) { + /* TODO(dgq): If we knew the size of the call list (or an upper bound), we + * could allocate all the memory for the closures in advance in a single + * chunk */ + grpc_iomgr_closure *kill_zombie_closure = + gpr_malloc(sizeof(grpc_iomgr_closure)); gpr_log(GPR_DEBUG, "server destroys call %p", calld->call); calld->state = ZOMBIED; - grpc_iomgr_add_callback( - grpc_iomgr_cb_create( - kill_zombie, - grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0), - 0)); /* XXX */ + grpc_iomgr_managed_closure_init( + kill_zombie_closure, kill_zombie, + grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0)); + grpc_iomgr_add_callback(kill_zombie_closure); } for (c = server->root_channel_data.next; c != &server->root_channel_data; diff --git a/test/core/iomgr/alarm_test.c b/test/core/iomgr/alarm_test.c index e416c794251..0ccec435e61 100644 --- a/test/core/iomgr/alarm_test.c +++ b/test/core/iomgr/alarm_test.c @@ -55,7 +55,7 @@ void no_op_cb(void *arg, int success) {} typedef struct { gpr_cv cv; gpr_mu mu; - grpc_iomgr_closure *iocb; + grpc_iomgr_closure *followup_closure; int counter; int done_success_ctr; int done_cancel_ctr; @@ -82,10 +82,8 @@ static void alarm_cb(void *arg /* alarm_arg */, int success) { a->success = success; gpr_cv_signal(&a->cv); gpr_mu_unlock(&a->mu); - a->iocb->cb = followup_cb; - a->iocb->cb_arg = &a->fcb_arg; - a->iocb->is_ext_managed = 1; - grpc_iomgr_add_callback(a->iocb); + grpc_iomgr_closure_init(a->followup_closure, followup_cb, &a->fcb_arg); + grpc_iomgr_add_callback(a->followup_closure); } /* Test grpc_alarm add and cancel. */ @@ -111,7 +109,7 @@ static void test_grpc_alarm(void) { arg.done = 0; gpr_mu_init(&arg.mu); gpr_cv_init(&arg.cv); - arg.iocb = gpr_malloc(sizeof(grpc_iomgr_closure)); + arg.followup_closure = gpr_malloc(sizeof(grpc_iomgr_closure)); gpr_event_init(&arg.fcb_arg); grpc_alarm_init(&alarm, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100), alarm_cb, &arg, @@ -153,7 +151,7 @@ static void test_grpc_alarm(void) { } gpr_cv_destroy(&arg.cv); gpr_mu_destroy(&arg.mu); - gpr_free(arg.iocb); + gpr_free(arg.followup_closure); arg2.counter = 0; arg2.success = SUCCESS_NOT_SET; @@ -162,7 +160,7 @@ static void test_grpc_alarm(void) { arg2.done = 0; gpr_mu_init(&arg2.mu); gpr_cv_init(&arg2.cv); - arg2.iocb = gpr_malloc(sizeof(grpc_iomgr_closure)); + arg2.followup_closure = gpr_malloc(sizeof(grpc_iomgr_closure)); gpr_event_init(&arg2.fcb_arg); @@ -214,7 +212,7 @@ static void test_grpc_alarm(void) { } gpr_cv_destroy(&arg2.cv); gpr_mu_destroy(&arg2.mu); - gpr_free(arg2.iocb); + gpr_free(arg2.followup_closure); grpc_iomgr_shutdown(); } From 0c47d80769b0e1e8c7262911262dc92133bd24d5 Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Thu, 28 May 2015 00:33:57 -0700 Subject: [PATCH 14/52] fixed compilation errors on windows code. --- src/core/iomgr/socket_windows.c | 9 ++++----- src/core/iomgr/socket_windows.h | 4 +++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/core/iomgr/socket_windows.c b/src/core/iomgr/socket_windows.c index f0bd0d8d69a..805fa8a4fc3 100644 --- a/src/core/iomgr/socket_windows.c +++ b/src/core/iomgr/socket_windows.c @@ -39,7 +39,6 @@ #include #include "src/core/iomgr/iocp_windows.h" -#include "src/core/iomgr/iomgr.h" #include "src/core/iomgr/iomgr_internal.h" #include "src/core/iomgr/pollset.h" #include "src/core/iomgr/pollset_windows.h" @@ -64,15 +63,15 @@ int grpc_winsocket_shutdown(grpc_winsocket *socket) { gpr_mu_lock(&socket->state_mu); if (socket->read_info.cb) { callbacks_set++; - grpc_iomgr_closure_init(&socket->shutdown_iocb, socket->read_info.cb, + grpc_iomgr_closure_init(&socket->shutdown_closure, socket->read_info.cb, socket->read_info.opaque); - grpc_iomgr_add_delayed_callback(socket->shutdown_iocb, 0); + grpc_iomgr_add_delayed_callback(&socket->shutdown_closure, 0); } if (socket->write_info.cb) { callbacks_set++; - grpc_iomgr_closure_init(&socket->shutdown_iocb, socket->write_info.cb, + grpc_iomgr_closure_init(&socket->shutdown_closure, socket->write_info.cb, socket->write_info.opaque); - grpc_iomgr_add_delayed_callback(socket->shutdown_iocb, 0); + grpc_iomgr_add_delayed_callback(&socket->shutdown_closure, 0); } gpr_mu_unlock(&socket->state_mu); return callbacks_set; diff --git a/src/core/iomgr/socket_windows.h b/src/core/iomgr/socket_windows.h index 8fd8ae97b6d..d5fee396043 100644 --- a/src/core/iomgr/socket_windows.h +++ b/src/core/iomgr/socket_windows.h @@ -39,6 +39,8 @@ #include #include +#include "src/core/iomgr/iomgr.h" + /* This holds the data for an outstanding read or write on a socket. The mutex to protect the concurrent access to that data is the one inside the winsocket wrapper. */ @@ -94,7 +96,7 @@ typedef struct grpc_winsocket { wait for. The socket will be collected at that time. */ int orphan; - grpc_iomgr_closure shutdown_iocb; + grpc_iomgr_closure shutdown_closure; } grpc_winsocket; /* Create a wrapped windows handle. This takes ownership of it, meaning that From 07997b6e89d155716b9dd79e02664ac95799baab Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Thu, 28 May 2015 13:51:50 -0700 Subject: [PATCH 15/52] assert -> GPR_ASSERT --- src/core/iomgr/fd_posix.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/core/iomgr/fd_posix.c b/src/core/iomgr/fd_posix.c index 672b321b951..6dcf1a3ec00 100644 --- a/src/core/iomgr/fd_posix.c +++ b/src/core/iomgr/fd_posix.c @@ -236,9 +236,8 @@ static void notify_on(grpc_fd *fd, gpr_atm *st, grpc_iomgr_closure *closure, /* swap was unsuccessful due to an intervening set_ready call. Fall through to the READY code below */ case READY: - assert(gpr_atm_no_barrier_load(st) == READY); + GPR_ASSERT(gpr_atm_no_barrier_load(st) == READY); gpr_atm_rel_store(st, NOT_READY); - closure->success = -1; process_callback(closure, !gpr_atm_acq_load(&fd->shutdown), allow_synchronous_callback); return; @@ -271,8 +270,8 @@ static void set_ready_locked(gpr_atm *st, grpc_iomgr_closure *callbacks, Fall through to the WAITING code below */ state = gpr_atm_acq_load(st); default: /* waiting */ - assert(gpr_atm_no_barrier_load(st) != READY && - gpr_atm_no_barrier_load(st) != NOT_READY); + GPR_ASSERT(gpr_atm_no_barrier_load(st) != READY && + gpr_atm_no_barrier_load(st) != NOT_READY); callbacks[(*ncallbacks)++] = *(grpc_iomgr_closure *)state; gpr_atm_rel_store(st, NOT_READY); return; @@ -291,7 +290,7 @@ static void set_ready(grpc_fd *fd, gpr_atm *st, set_ready_locked(st, &closure, &ncb); gpr_mu_unlock(&fd->set_state_mu); success = !gpr_atm_acq_load(&fd->shutdown); - assert(ncb <= 1); + GPR_ASSERT(ncb <= 1); if (ncb > 0) { grpc_iomgr_closure *managed_cb = gpr_malloc(sizeof(grpc_iomgr_closure)); grpc_iomgr_managed_closure_init(managed_cb, closure.cb, closure.cb_arg); @@ -307,7 +306,7 @@ void grpc_fd_shutdown(grpc_fd *fd) { set_ready_locked(&fd->readst, fd->shutdown_iocbs, &ncb); set_ready_locked(&fd->writest, fd->shutdown_iocbs, &ncb); gpr_mu_unlock(&fd->set_state_mu); - assert(ncb <= 2); + GPR_ASSERT(ncb <= 2); process_callbacks(fd->shutdown_iocbs, ncb, 0, 0); } From a25e6de0ca8740ef59709db52bcaba72e6ccaf83 Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Thu, 28 May 2015 15:44:52 -0700 Subject: [PATCH 16/52] fd_posix: removed redundant on_done --- src/core/iomgr/fd_posix.c | 15 ++++++--------- src/core/iomgr/fd_posix.h | 6 ++---- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/core/iomgr/fd_posix.c b/src/core/iomgr/fd_posix.c index 6dcf1a3ec00..379ca66c85c 100644 --- a/src/core/iomgr/fd_posix.c +++ b/src/core/iomgr/fd_posix.c @@ -117,10 +117,7 @@ static void ref_by(grpc_fd *fd, int n) { static void unref_by(grpc_fd *fd, int n) { gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n); if (old == n) { - close(fd->fd); - grpc_iomgr_closure_init(&fd->on_done_iocb, fd->on_done, - fd->on_done_user_data); - grpc_iomgr_add_callback(&fd->on_done_iocb); + grpc_iomgr_add_callback(&fd->on_done_closure); freelist_fd(fd); grpc_iomgr_unref(); } else { @@ -183,8 +180,8 @@ static void wake_all_watchers_locked(grpc_fd *fd) { } void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_cb_func on_done, void *user_data) { - fd->on_done = on_done ? on_done : do_nothing; - fd->on_done_user_data = user_data; + grpc_iomgr_closure_init(&fd->on_done_closure, on_done ? on_done : do_nothing, + user_data); shutdown(fd->fd, SHUT_RDWR); ref_by(fd, 1); /* remove active status, but keep referenced */ gpr_mu_lock(&fd->watcher_mu); @@ -303,11 +300,11 @@ void grpc_fd_shutdown(grpc_fd *fd) { gpr_mu_lock(&fd->set_state_mu); GPR_ASSERT(!gpr_atm_no_barrier_load(&fd->shutdown)); gpr_atm_rel_store(&fd->shutdown, 1); - set_ready_locked(&fd->readst, fd->shutdown_iocbs, &ncb); - set_ready_locked(&fd->writest, fd->shutdown_iocbs, &ncb); + set_ready_locked(&fd->readst, fd->shutdown_closures, &ncb); + set_ready_locked(&fd->writest, fd->shutdown_closures, &ncb); gpr_mu_unlock(&fd->set_state_mu); GPR_ASSERT(ncb <= 2); - process_callbacks(fd->shutdown_iocbs, ncb, 0, 0); + process_callbacks(fd->shutdown_closures, ncb, 0, 0); } void grpc_fd_notify_on_read(grpc_fd *fd, grpc_iomgr_closure *closure) { diff --git a/src/core/iomgr/fd_posix.h b/src/core/iomgr/fd_posix.h index 2d9c3245e34..db9b2a74f62 100644 --- a/src/core/iomgr/fd_posix.h +++ b/src/core/iomgr/fd_posix.h @@ -91,12 +91,10 @@ struct grpc_fd { gpr_atm readst; gpr_atm writest; - grpc_iomgr_cb_func on_done; - void *on_done_user_data; struct grpc_fd *freelist_next; - grpc_iomgr_closure on_done_iocb; - grpc_iomgr_closure shutdown_iocbs[2]; + grpc_iomgr_closure on_done_closure; + grpc_iomgr_closure shutdown_closures[2]; }; /* Create a wrapped file descriptor. From 2738ae8c44786b8798d4b111e289b4baf1a134c6 Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Thu, 28 May 2015 16:06:48 -0700 Subject: [PATCH 17/52] fd_posix: free from managed closures! --- src/core/iomgr/fd_posix.c | 16 +++++++--------- src/core/iomgr/fd_posix.h | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/core/iomgr/fd_posix.c b/src/core/iomgr/fd_posix.c index 379ca66c85c..33d90872c30 100644 --- a/src/core/iomgr/fd_posix.c +++ b/src/core/iomgr/fd_posix.c @@ -249,7 +249,7 @@ static void notify_on(grpc_fd *fd, gpr_atm *st, grpc_iomgr_closure *closure, abort(); } -static void set_ready_locked(gpr_atm *st, grpc_iomgr_closure *callbacks, +static void set_ready_locked(gpr_atm *st, grpc_iomgr_closure **callbacks, size_t *ncallbacks) { gpr_intptr state = gpr_atm_acq_load(st); @@ -269,7 +269,7 @@ static void set_ready_locked(gpr_atm *st, grpc_iomgr_closure *callbacks, default: /* waiting */ GPR_ASSERT(gpr_atm_no_barrier_load(st) != READY && gpr_atm_no_barrier_load(st) != NOT_READY); - callbacks[(*ncallbacks)++] = *(grpc_iomgr_closure *)state; + callbacks[(*ncallbacks)++] = (grpc_iomgr_closure *)state; gpr_atm_rel_store(st, NOT_READY); return; } @@ -280,7 +280,7 @@ static void set_ready(grpc_fd *fd, gpr_atm *st, /* only one set_ready can be active at once (but there may be a racing notify_on) */ int success; - grpc_iomgr_closure closure; + grpc_iomgr_closure* closure; size_t ncb = 0; gpr_mu_lock(&fd->set_state_mu); @@ -289,9 +289,7 @@ static void set_ready(grpc_fd *fd, gpr_atm *st, success = !gpr_atm_acq_load(&fd->shutdown); GPR_ASSERT(ncb <= 1); if (ncb > 0) { - grpc_iomgr_closure *managed_cb = gpr_malloc(sizeof(grpc_iomgr_closure)); - grpc_iomgr_managed_closure_init(managed_cb, closure.cb, closure.cb_arg); - process_callbacks(managed_cb, ncb, success, allow_synchronous_callback); + process_callbacks(closure, ncb, success, allow_synchronous_callback); } } @@ -300,11 +298,11 @@ void grpc_fd_shutdown(grpc_fd *fd) { gpr_mu_lock(&fd->set_state_mu); GPR_ASSERT(!gpr_atm_no_barrier_load(&fd->shutdown)); gpr_atm_rel_store(&fd->shutdown, 1); - set_ready_locked(&fd->readst, fd->shutdown_closures, &ncb); - set_ready_locked(&fd->writest, fd->shutdown_closures, &ncb); + set_ready_locked(&fd->readst, &fd->shutdown_closures[0], &ncb); + set_ready_locked(&fd->writest, &fd->shutdown_closures[0], &ncb); gpr_mu_unlock(&fd->set_state_mu); GPR_ASSERT(ncb <= 2); - process_callbacks(fd->shutdown_closures, ncb, 0, 0); + process_callbacks(fd->shutdown_closures[0], ncb, 0, 0); } void grpc_fd_notify_on_read(grpc_fd *fd, grpc_iomgr_closure *closure) { diff --git a/src/core/iomgr/fd_posix.h b/src/core/iomgr/fd_posix.h index db9b2a74f62..a7c9c34802e 100644 --- a/src/core/iomgr/fd_posix.h +++ b/src/core/iomgr/fd_posix.h @@ -94,7 +94,7 @@ struct grpc_fd { struct grpc_fd *freelist_next; grpc_iomgr_closure on_done_closure; - grpc_iomgr_closure shutdown_closures[2]; + grpc_iomgr_closure *shutdown_closures[2]; }; /* Create a wrapped file descriptor. From 284488b4347685a83f97b6123a8d7115bb8ee032 Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Thu, 28 May 2015 16:27:39 -0700 Subject: [PATCH 18/52] removed managed closures from server.c --- src/core/channel/child_channel.c | 16 ++++++------ src/core/iomgr/iomgr.h | 1 + src/core/iomgr/pollset_posix.c | 10 +++---- src/core/iomgr/tcp_posix.c | 8 +++--- src/core/security/credentials.c | 1 + src/core/surface/call.c | 8 +++--- src/core/surface/channel.c | 8 +++--- src/core/surface/server.c | 45 ++++++++++++++------------------ 8 files changed, 47 insertions(+), 50 deletions(-) diff --git a/src/core/channel/child_channel.c b/src/core/channel/child_channel.c index 213a4b881d3..600f7df1bf1 100644 --- a/src/core/channel/child_channel.c +++ b/src/core/channel/child_channel.c @@ -59,8 +59,8 @@ typedef struct { /* have we sent farewell (goaway + disconnect) */ gpr_uint8 sent_farewell; - grpc_iomgr_closure finally_destroy_channel_iocb; - grpc_iomgr_closure send_farewells_iocb; + grpc_iomgr_closure finally_destroy_channel_closure; + grpc_iomgr_closure send_farewells_closure; } lb_channel_data; typedef struct { grpc_child_channel *channel; } lb_call_data; @@ -216,16 +216,16 @@ static void maybe_destroy_channel(grpc_child_channel *channel) { lb_channel_data *chand = LINK_BACK_ELEM_FROM_CHANNEL(channel)->channel_data; if (chand->destroyed && chand->disconnected && chand->active_calls == 0 && !chand->sending_farewell && !chand->calling_back) { - chand->finally_destroy_channel_iocb.cb = finally_destroy_channel; - chand->finally_destroy_channel_iocb.cb_arg = channel; - grpc_iomgr_add_callback(&chand->finally_destroy_channel_iocb); + chand->finally_destroy_channel_closure.cb = finally_destroy_channel; + chand->finally_destroy_channel_closure.cb_arg = channel; + grpc_iomgr_add_callback(&chand->finally_destroy_channel_closure); } else if (chand->destroyed && !chand->disconnected && chand->active_calls == 0 && !chand->sending_farewell && !chand->sent_farewell) { chand->sending_farewell = 1; - chand->send_farewells_iocb.cb = send_farewells; - chand->send_farewells_iocb.cb_arg = channel; - grpc_iomgr_add_callback(&chand->send_farewells_iocb); + chand->send_farewells_closure.cb = send_farewells; + chand->send_farewells_closure.cb_arg = channel; + grpc_iomgr_add_callback(&chand->send_farewells_closure); } } diff --git a/src/core/iomgr/iomgr.h b/src/core/iomgr/iomgr.h index 437e8cf9a81..913f83f80e7 100644 --- a/src/core/iomgr/iomgr.h +++ b/src/core/iomgr/iomgr.h @@ -47,6 +47,7 @@ typedef struct grpc_iomgr_closure { void grpc_iomgr_closure_init(grpc_iomgr_closure *closure, grpc_iomgr_cb_func cb, void *cb_arg); +/* TODO(dgq): get rid of the managed_closure concept. */ void grpc_iomgr_managed_closure_init(grpc_iomgr_closure *manager, grpc_iomgr_cb_func managed_cb, void *managed_cb_arg); diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c index db17012df00..a8e60690022 100644 --- a/src/core/iomgr/pollset_posix.c +++ b/src/core/iomgr/pollset_posix.c @@ -257,7 +257,7 @@ typedef struct grpc_unary_promote_args { const grpc_pollset_vtable *original_vtable; grpc_pollset *pollset; grpc_fd *fd; - grpc_iomgr_closure promotion_iocb; + grpc_iomgr_closure promotion_closure; } grpc_unary_promote_args; static void unary_poll_do_promote(void *args, int success) { @@ -280,7 +280,7 @@ static void unary_poll_do_promote(void *args, int success) { /* First we need to ensure that nobody is polling concurrently */ while (pollset->counter != 0) { grpc_pollset_kick(pollset); - grpc_iomgr_add_callback(&up_args->promotion_iocb); + grpc_iomgr_add_callback(&up_args->promotion_closure); gpr_mu_unlock(&pollset->mu); return; } @@ -364,9 +364,9 @@ static void unary_poll_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) { up_args->pollset = pollset; up_args->fd = fd; up_args->original_vtable = pollset->vtable; - up_args->promotion_iocb.cb = unary_poll_do_promote; - up_args->promotion_iocb.cb_arg = up_args; - grpc_iomgr_add_callback(&up_args->promotion_iocb); + up_args->promotion_closure.cb = unary_poll_do_promote; + up_args->promotion_closure.cb_arg = up_args; + grpc_iomgr_add_callback(&up_args->promotion_closure); grpc_pollset_kick(pollset); } diff --git a/src/core/iomgr/tcp_posix.c b/src/core/iomgr/tcp_posix.c index 2978c2c370f..2f19f9d442f 100644 --- a/src/core/iomgr/tcp_posix.c +++ b/src/core/iomgr/tcp_posix.c @@ -281,7 +281,7 @@ typedef struct { grpc_iomgr_closure read_closure; grpc_iomgr_closure write_closure; - grpc_iomgr_closure handle_read_iocb; + grpc_iomgr_closure handle_read_closure; } grpc_tcp; static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success); @@ -445,8 +445,8 @@ static void grpc_tcp_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, tcp->finished_edge = 0; grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure); } else { - tcp->handle_read_iocb.cb_arg = tcp; - grpc_iomgr_add_callback(&tcp->handle_read_iocb); + tcp->handle_read_closure.cb_arg = tcp; + grpc_iomgr_add_callback(&tcp->handle_read_closure); } } @@ -596,7 +596,7 @@ grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size) { tcp->write_closure.cb = grpc_tcp_handle_write; tcp->write_closure.cb_arg = tcp; - tcp->handle_read_iocb.cb = grpc_tcp_handle_read; + tcp->handle_read_closure.cb = grpc_tcp_handle_read; return &tcp->base; } diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c index 5e595899c3e..a960e77db64 100644 --- a/src/core/security/credentials.c +++ b/src/core/security/credentials.c @@ -833,6 +833,7 @@ static void fake_oauth2_get_request_metadata(grpc_credentials *creds, if (c->is_async) { grpc_iomgr_closure *on_simulated_token_fetch_done_closure = gpr_malloc(sizeof(grpc_iomgr_closure)); + /* TODO(dgq): get rid of the managed_closure altogether */ grpc_iomgr_managed_closure_init( on_simulated_token_fetch_done_closure, on_simulated_token_fetch_done, grpc_credentials_metadata_request_create(creds, cb, user_data)); diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 3a739315a2f..948d0cdc36f 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -226,7 +226,7 @@ struct grpc_call { gpr_slice_buffer incoming_message; gpr_uint32 incoming_message_length; - grpc_iomgr_closure destroy_iocb; + grpc_iomgr_closure destroy_closure; }; #define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1)) @@ -368,9 +368,9 @@ void grpc_call_internal_unref(grpc_call *c, int allow_immediate_deletion) { if (allow_immediate_deletion) { destroy_call(c, 1); } else { - c->destroy_iocb.cb = destroy_call; - c->destroy_iocb.cb_arg = c; - grpc_iomgr_add_callback(&c->destroy_iocb); + c->destroy_closure.cb = destroy_call; + c->destroy_closure.cb_arg = c; + grpc_iomgr_add_callback(&c->destroy_closure); } } } diff --git a/src/core/surface/channel.c b/src/core/surface/channel.c index d018db7bb0e..947011c613f 100644 --- a/src/core/surface/channel.c +++ b/src/core/surface/channel.c @@ -61,7 +61,7 @@ struct grpc_channel { gpr_mu registered_call_mu; registered_call *registered_calls; - grpc_iomgr_closure destroy_iocb; + grpc_iomgr_closure destroy_closure; }; #define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c) + 1)) @@ -194,9 +194,9 @@ static void destroy_channel(void *p, int ok) { void grpc_channel_internal_unref(grpc_channel *channel) { if (gpr_unref(&channel->refs)) { - channel->destroy_iocb.cb = destroy_channel; - channel->destroy_iocb.cb_arg = channel; - grpc_iomgr_add_callback(&channel->destroy_iocb); + channel->destroy_closure.cb = destroy_channel; + channel->destroy_closure.cb_arg = channel; + grpc_iomgr_add_callback(&channel->destroy_closure); } } diff --git a/src/core/surface/server.c b/src/core/surface/server.c index 378d50486bf..21b5f9162d9 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -122,8 +122,8 @@ struct channel_data { channel_registered_method *registered_methods; gpr_uint32 registered_method_slots; gpr_uint32 registered_method_max_probes; - grpc_iomgr_closure finish_shutdown_channel_iocb; - grpc_iomgr_closure finish_destroy_channel_iocb; + grpc_iomgr_closure finish_shutdown_channel_closure; + grpc_iomgr_closure finish_destroy_channel_closure; }; struct grpc_server { @@ -180,6 +180,8 @@ struct call_data { void (*on_done_recv)(void *user_data, int success); void *recv_user_data; + grpc_iomgr_closure kill_zombie_closure; + call_data **root[CALL_LIST_COUNT]; call_link links[CALL_LIST_COUNT]; }; @@ -306,9 +308,9 @@ static void destroy_channel(channel_data *chand) { GPR_ASSERT(chand->server != NULL); orphan_channel(chand); server_ref(chand->server); - chand->finish_destroy_channel_iocb.cb = finish_destroy_channel; - chand->finish_destroy_channel_iocb.cb_arg = chand; - grpc_iomgr_add_callback(&chand->finish_destroy_channel_iocb); + chand->finish_destroy_channel_closure.cb = finish_destroy_channel; + chand->finish_destroy_channel_closure.cb_arg = chand; + grpc_iomgr_add_callback(&chand->finish_destroy_channel_closure); } static void finish_start_new_rpc_and_unlock(grpc_server *server, @@ -419,29 +421,24 @@ static void server_on_recv(void *ptr, int success) { case GRPC_STREAM_RECV_CLOSED: gpr_mu_lock(&chand->server->mu); if (calld->state == NOT_STARTED) { - grpc_iomgr_closure *kill_zombie_closure = - gpr_malloc(sizeof(grpc_iomgr_closure)); calld->state = ZOMBIED; - grpc_iomgr_managed_closure_init(kill_zombie_closure, kill_zombie, elem); - grpc_iomgr_add_callback(kill_zombie_closure); + grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem); + grpc_iomgr_add_callback(&calld->kill_zombie_closure); } gpr_mu_unlock(&chand->server->mu); break; case GRPC_STREAM_CLOSED: gpr_mu_lock(&chand->server->mu); if (calld->state == NOT_STARTED) { - grpc_iomgr_closure *kill_zombie_closure = - gpr_malloc(sizeof(grpc_iomgr_closure)); calld->state = ZOMBIED; - grpc_iomgr_managed_closure_init(kill_zombie_closure, kill_zombie, elem); - grpc_iomgr_add_callback(kill_zombie_closure); + grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem); + grpc_iomgr_add_callback(&calld->kill_zombie_closure); } else if (calld->state == PENDING) { - grpc_iomgr_closure *kill_zombie_closure = - gpr_malloc(sizeof(grpc_iomgr_closure)); call_list_remove(calld, PENDING_START); calld->state = ZOMBIED; - grpc_iomgr_managed_closure_init(kill_zombie_closure, kill_zombie, elem); - grpc_iomgr_add_callback(kill_zombie_closure); + grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem); + grpc_iomgr_add_callback(&calld->kill_zombie_closure); + } gpr_mu_unlock(&chand->server->mu); break; @@ -515,9 +512,9 @@ static void finish_shutdown_channel(void *cd, int success) { static void shutdown_channel(channel_data *chand) { grpc_channel_internal_ref(chand->channel); - chand->finish_shutdown_channel_iocb.cb = finish_shutdown_channel; - chand->finish_shutdown_channel_iocb.cb_arg = chand; - grpc_iomgr_add_callback(&chand->finish_shutdown_channel_iocb); + chand->finish_shutdown_channel_closure.cb = finish_shutdown_channel; + chand->finish_shutdown_channel_closure.cb_arg = chand; + grpc_iomgr_add_callback(&chand->finish_shutdown_channel_closure); } static void init_call_elem(grpc_call_element *elem, @@ -958,14 +955,12 @@ void grpc_server_destroy(grpc_server *server) { /* TODO(dgq): If we knew the size of the call list (or an upper bound), we * could allocate all the memory for the closures in advance in a single * chunk */ - grpc_iomgr_closure *kill_zombie_closure = - gpr_malloc(sizeof(grpc_iomgr_closure)); gpr_log(GPR_DEBUG, "server destroys call %p", calld->call); calld->state = ZOMBIED; - grpc_iomgr_managed_closure_init( - kill_zombie_closure, kill_zombie, + grpc_iomgr_closure_init( + &calld->kill_zombie_closure, kill_zombie, grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0)); - grpc_iomgr_add_callback(kill_zombie_closure); + grpc_iomgr_add_callback(&calld->kill_zombie_closure); } for (c = server->root_channel_data.next; c != &server->root_channel_data; From 8b8cce05d782e7db52b5574fa9249029ffc767eb Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Sun, 31 May 2015 12:39:40 -0700 Subject: [PATCH 19/52] Removed managed closures from iomgr. The only remaining need for those (whereby the closure frees itself upon completion) remains in security/credentials.c, where the code has been inlined (to be removed at a later time). --- src/core/iomgr/iomgr.c | 29 ----------------------------- src/core/security/credentials.c | 29 +++++++++++++++++++++++++---- 2 files changed, 25 insertions(+), 33 deletions(-) diff --git a/src/core/iomgr/iomgr.c b/src/core/iomgr/iomgr.c index 1d6fa9053eb..85867b6edfe 100644 --- a/src/core/iomgr/iomgr.c +++ b/src/core/iomgr/iomgr.c @@ -33,7 +33,6 @@ #include "src/core/iomgr/iomgr.h" -#include #include #include "src/core/iomgr/iomgr_internal.h" @@ -64,7 +63,6 @@ static void background_callback_executor(void *ignored) { g_cbs_head = closure->next; if (!g_cbs_head) g_cbs_tail = NULL; gpr_mu_unlock(&g_mu); - assert(closure->success >= 0); closure->cb(closure->cb_arg, closure->success); gpr_mu_lock(&g_mu); } else if (grpc_alarm_check(&g_mu, gpr_now(), &deadline)) { @@ -169,32 +167,6 @@ void grpc_iomgr_closure_init(grpc_iomgr_closure *closure, grpc_iomgr_cb_func cb, closure->next = NULL; } -typedef struct { - grpc_iomgr_closure managed; - grpc_iomgr_closure *manager; -} managed_closure_arg; - -static void closure_manager_func(void *arg, int success) { - managed_closure_arg *mc_arg = (managed_closure_arg*) arg; - - mc_arg->managed.cb(mc_arg->managed.cb_arg, success); - gpr_free(mc_arg->manager); - gpr_free(mc_arg); -} - -void grpc_iomgr_managed_closure_init(grpc_iomgr_closure *manager, - grpc_iomgr_cb_func managed_cb, - void *managed_cb_arg) { - managed_closure_arg *managed_arg = gpr_malloc(sizeof(managed_closure_arg)); - - managed_arg->managed.cb = managed_cb; - managed_arg->managed.cb_arg = managed_cb_arg; - managed_arg->manager= manager; - - grpc_iomgr_closure_init(manager, closure_manager_func, managed_arg); -} - - void grpc_iomgr_add_delayed_callback(grpc_iomgr_closure *closure, int success) { closure->success = success; gpr_mu_lock(&g_mu); @@ -237,7 +209,6 @@ int grpc_maybe_call_delayed_callbacks(gpr_mu *drop_mu, int success) { retake_mu = drop_mu; drop_mu = NULL; } - assert(closure->success >= 0); closure->cb(closure->cb_arg, success && closure->success); n++; } diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c index a960e77db64..648ac60eb62 100644 --- a/src/core/security/credentials.c +++ b/src/core/security/credentials.c @@ -824,6 +824,20 @@ void on_simulated_token_fetch_done(void *user_data, int success) { grpc_credentials_metadata_request_destroy(r); } +/* TODO(dgq): get rid of the concept of "managed closure" altogether */ +typedef struct { + grpc_iomgr_closure managed; + grpc_iomgr_closure *manager; +} managed_closure_arg; + +static void closure_manager_func(void *arg, int success) { + managed_closure_arg *mc_arg = (managed_closure_arg*) arg; + + mc_arg->managed.cb(mc_arg->managed.cb_arg, success); + gpr_free(mc_arg->manager); + gpr_free(mc_arg); +} + static void fake_oauth2_get_request_metadata(grpc_credentials *creds, const char *service_url, grpc_credentials_metadata_cb cb, @@ -831,12 +845,19 @@ static void fake_oauth2_get_request_metadata(grpc_credentials *creds, grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds; if (c->is_async) { + /* TODO(dgq): get rid of the managed closure */ grpc_iomgr_closure *on_simulated_token_fetch_done_closure = gpr_malloc(sizeof(grpc_iomgr_closure)); - /* TODO(dgq): get rid of the managed_closure altogether */ - grpc_iomgr_managed_closure_init( - on_simulated_token_fetch_done_closure, on_simulated_token_fetch_done, - grpc_credentials_metadata_request_create(creds, cb, user_data)); + managed_closure_arg *managed_arg = gpr_malloc(sizeof(managed_closure_arg)); + + managed_arg->manager = on_simulated_token_fetch_done_closure; + managed_arg->managed.cb = on_simulated_token_fetch_done; + managed_arg->managed.cb_arg = + grpc_credentials_metadata_request_create(creds, cb, user_data); + + grpc_iomgr_closure_init(on_simulated_token_fetch_done_closure, + closure_manager_func, managed_arg); + grpc_iomgr_add_callback(on_simulated_token_fetch_done_closure); } else { cb(user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK); From 0f5ee82cea9acdb44191353b4d37a689615ea483 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Sat, 30 May 2015 23:13:57 -0700 Subject: [PATCH 20/52] Move RouteGuideClient to generated_libraries/ --- .../RouteGuideClient/RouteGuide.pbobjc.h | 0 .../RouteGuideClient/RouteGuide.pbobjc.m | 0 .../RouteGuideClient/RouteGuide.pbrpc.h | 0 .../RouteGuideClient/RouteGuide.pbrpc.m | 0 .../RouteGuideClient/Route_guide.podspec | 0 .../RouteGuideClient/route_guide.proto | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename src/objective-c/{examples/Sample => generated_libraries}/RouteGuideClient/RouteGuide.pbobjc.h (100%) rename src/objective-c/{examples/Sample => generated_libraries}/RouteGuideClient/RouteGuide.pbobjc.m (100%) rename src/objective-c/{examples/Sample => generated_libraries}/RouteGuideClient/RouteGuide.pbrpc.h (100%) rename src/objective-c/{examples/Sample => generated_libraries}/RouteGuideClient/RouteGuide.pbrpc.m (100%) rename src/objective-c/{examples/Sample => generated_libraries}/RouteGuideClient/Route_guide.podspec (100%) rename src/objective-c/{examples/Sample => generated_libraries}/RouteGuideClient/route_guide.proto (100%) diff --git a/src/objective-c/examples/Sample/RouteGuideClient/RouteGuide.pbobjc.h b/src/objective-c/generated_libraries/RouteGuideClient/RouteGuide.pbobjc.h similarity index 100% rename from src/objective-c/examples/Sample/RouteGuideClient/RouteGuide.pbobjc.h rename to src/objective-c/generated_libraries/RouteGuideClient/RouteGuide.pbobjc.h diff --git a/src/objective-c/examples/Sample/RouteGuideClient/RouteGuide.pbobjc.m b/src/objective-c/generated_libraries/RouteGuideClient/RouteGuide.pbobjc.m similarity index 100% rename from src/objective-c/examples/Sample/RouteGuideClient/RouteGuide.pbobjc.m rename to src/objective-c/generated_libraries/RouteGuideClient/RouteGuide.pbobjc.m diff --git a/src/objective-c/examples/Sample/RouteGuideClient/RouteGuide.pbrpc.h b/src/objective-c/generated_libraries/RouteGuideClient/RouteGuide.pbrpc.h similarity index 100% rename from src/objective-c/examples/Sample/RouteGuideClient/RouteGuide.pbrpc.h rename to src/objective-c/generated_libraries/RouteGuideClient/RouteGuide.pbrpc.h diff --git a/src/objective-c/examples/Sample/RouteGuideClient/RouteGuide.pbrpc.m b/src/objective-c/generated_libraries/RouteGuideClient/RouteGuide.pbrpc.m similarity index 100% rename from src/objective-c/examples/Sample/RouteGuideClient/RouteGuide.pbrpc.m rename to src/objective-c/generated_libraries/RouteGuideClient/RouteGuide.pbrpc.m diff --git a/src/objective-c/examples/Sample/RouteGuideClient/Route_guide.podspec b/src/objective-c/generated_libraries/RouteGuideClient/Route_guide.podspec similarity index 100% rename from src/objective-c/examples/Sample/RouteGuideClient/Route_guide.podspec rename to src/objective-c/generated_libraries/RouteGuideClient/Route_guide.podspec diff --git a/src/objective-c/examples/Sample/RouteGuideClient/route_guide.proto b/src/objective-c/generated_libraries/RouteGuideClient/route_guide.proto similarity index 100% rename from src/objective-c/examples/Sample/RouteGuideClient/route_guide.proto rename to src/objective-c/generated_libraries/RouteGuideClient/route_guide.proto From 1c762bd94549d1fc0f9b3f041308eb554870e2f0 Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Sun, 31 May 2015 17:04:43 -0700 Subject: [PATCH 21/52] Added some comments. --- src/core/iomgr/fd_posix.c | 3 ++- src/core/iomgr/iomgr.c | 3 +-- src/core/iomgr/iomgr.h | 32 +++++++++++++++++++++++--------- src/core/iomgr/pollset_windows.c | 10 +++++----- 4 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/core/iomgr/fd_posix.c b/src/core/iomgr/fd_posix.c index 33d90872c30..5bbf171c6d4 100644 --- a/src/core/iomgr/fd_posix.c +++ b/src/core/iomgr/fd_posix.c @@ -302,7 +302,8 @@ void grpc_fd_shutdown(grpc_fd *fd) { set_ready_locked(&fd->writest, &fd->shutdown_closures[0], &ncb); gpr_mu_unlock(&fd->set_state_mu); GPR_ASSERT(ncb <= 2); - process_callbacks(fd->shutdown_closures[0], ncb, 0, 0); + process_callbacks(fd->shutdown_closures[0], ncb, 0 /* GPR_FALSE */, + 0 /* GPR_FALSE */); } void grpc_fd_notify_on_read(grpc_fd *fd, grpc_iomgr_closure *closure) { diff --git a/src/core/iomgr/iomgr.c b/src/core/iomgr/iomgr.c index 85867b6edfe..b983a89daa8 100644 --- a/src/core/iomgr/iomgr.c +++ b/src/core/iomgr/iomgr.c @@ -163,7 +163,6 @@ void grpc_iomgr_closure_init(grpc_iomgr_closure *closure, grpc_iomgr_cb_func cb, void *cb_arg) { closure->cb = cb; closure->cb_arg = cb_arg; - closure->success = -1; /* uninitialized */ closure->next = NULL; } @@ -182,7 +181,7 @@ void grpc_iomgr_add_delayed_callback(grpc_iomgr_closure *closure, int success) { void grpc_iomgr_add_callback(grpc_iomgr_closure *closure) { - grpc_iomgr_add_delayed_callback(closure, 1); + grpc_iomgr_add_delayed_callback(closure, 1 /* GPR_TRUE */); } diff --git a/src/core/iomgr/iomgr.h b/src/core/iomgr/iomgr.h index 913f83f80e7..a10e481e481 100644 --- a/src/core/iomgr/iomgr.h +++ b/src/core/iomgr/iomgr.h @@ -34,29 +34,43 @@ #ifndef GRPC_INTERNAL_CORE_IOMGR_IOMGR_H #define GRPC_INTERNAL_CORE_IOMGR_IOMGR_H -/* gRPC Callback definition */ +/** gRPC Callback definition. + * + * \param arg Arbitrary input. + * \param success An indication on the state of the iomgr. On false, cleanup + * actions should be taken (eg, shutdown). */ typedef void (*grpc_iomgr_cb_func)(void *arg, int success); +/** A closure over a grpc_iomgr_cb_func. */ typedef struct grpc_iomgr_closure { + /** Bound callback. */ grpc_iomgr_cb_func cb; + + /** Arguments to be passed to "cb". */ void *cb_arg; + + /** Internal. A boolean indication to "cb" on the state of the iomgr. + * For instance, closures created during a shutdown would have this field set + * to false. */ int success; - struct grpc_iomgr_closure *next; /** Do not touch */ + + /**< Internal. Do not touch */ + struct grpc_iomgr_closure *next; } grpc_iomgr_closure; +/** Initializes \a closure with \a cb and \a cb_arg. */ void grpc_iomgr_closure_init(grpc_iomgr_closure *closure, grpc_iomgr_cb_func cb, void *cb_arg); -/* TODO(dgq): get rid of the managed_closure concept. */ -void grpc_iomgr_managed_closure_init(grpc_iomgr_closure *manager, - grpc_iomgr_cb_func managed_cb, - void *managed_cb_arg); - +/** Initializes the iomgr. */ void grpc_iomgr_init(void); + +/** Signals the intention to shutdown the iomgr. */ void grpc_iomgr_shutdown(void); -/* This function is called from within a callback or from anywhere else - and causes the invocation of a callback at some point in the future */ +/** Registers a closure to be invoked at some point in the future. + * + * Can be called from within a callback or from anywhere else */ void grpc_iomgr_add_callback(grpc_iomgr_closure *closure); #endif /* GRPC_INTERNAL_CORE_IOMGR_IOMGR_H */ diff --git a/src/core/iomgr/pollset_windows.c b/src/core/iomgr/pollset_windows.c index 5af0685f9d9..b1f4c09a2cf 100644 --- a/src/core/iomgr/pollset_windows.c +++ b/src/core/iomgr/pollset_windows.c @@ -66,15 +66,15 @@ int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) { gpr_timespec now; now = gpr_now(); if (gpr_time_cmp(now, deadline) > 0) { - return 0; + return 0 /* GPR_FALSE */; } - if (grpc_maybe_call_delayed_callbacks(NULL, 1)) { - return 1; + if (grpc_maybe_call_delayed_callbacks(NULL, 1 /* GPR_TRUE */)) { + return 1 /* GPR_TRUE */; } if (grpc_alarm_check(NULL, now, &deadline)) { - return 1; + return 1 /* GPR_TRUE */; } - return 0; + return 0 /* GPR_FALSE */; } void grpc_pollset_kick(grpc_pollset *p) { } From 244365d5216424dc384915f1e0f99adcfc1ef246 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Sun, 31 May 2015 12:31:48 -0700 Subject: [PATCH 22/52] =?UTF-8?q?Add=20RouteGuideClient=20to=20tests?= =?UTF-8?q?=E2=80=99=20Podfile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/objective-c/tests/Podfile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile index d8fea6edb15..c099fb51823 100644 --- a/src/objective-c/tests/Podfile +++ b/src/objective-c/tests/Podfile @@ -4,6 +4,7 @@ platform :ios, '8.0' pod 'gRPC', :path => "../../.." pod 'Protobuf', :git => 'https://github.com/google/protobuf.git' pod 'RemoteTest', :path => "../generated_libraries/RemoteTestClient" +pod 'Route_guide', :path => "../generated_libraries/RouteGuideClient" link_with 'AllTests' From e17c72bbbd9e39801b2cf95f286129450a3aea57 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Sun, 31 May 2015 13:04:01 -0700 Subject: [PATCH 23/52] Add SampleTests as LocalClearTextTests to tests project --- src/objective-c/tests/LocalClearTextTests.m | 158 ++++++++++++++++++ .../tests/Tests.xcodeproj/project.pbxproj | 4 + 2 files changed, 162 insertions(+) create mode 100644 src/objective-c/tests/LocalClearTextTests.m diff --git a/src/objective-c/tests/LocalClearTextTests.m b/src/objective-c/tests/LocalClearTextTests.m new file mode 100644 index 00000000000..6a9496b623a --- /dev/null +++ b/src/objective-c/tests/LocalClearTextTests.m @@ -0,0 +1,158 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#import +#import + +#import +#import +#import +#import +#import +#import + +// These tests require the gRPC-Java "RouteGuide" sample server to be running locally. To do so, +// install Gradle by following the instructions here: https://docs.gradle.org/current/userguide/installation.html +// And use it to run the server by following the instructions here: https://github.com/grpc/grpc-java/tree/master/examples + +@interface LocalClearTextTests : XCTestCase +@end + +@implementation LocalClearTextTests + +- (void)testConnectionToLocalServer { + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Server reachable."]; + + // This method isn't implemented by the local server. + GRPCMethodName *method = [[GRPCMethodName alloc] initWithPackage:@"grpc.testing" + interface:@"TestService" + method:@"EmptyCall"]; + + id requestsWriter = [GRXWriter writerWithValue:[NSData data]]; + + GRPCCall *call = [[GRPCCall alloc] initWithHost:@"http://127.0.0.1:8980" + method:method + requestsWriter:requestsWriter]; + + id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { + XCTFail(@"Received unexpected response: %@", value); + } completionHandler:^(NSError *errorOrNil) { + XCTAssertNotNil(errorOrNil, @"Finished without error!"); + XCTAssertEqual(errorOrNil.code, 12, @"Finished with unexpected error: %@", errorOrNil); + [expectation fulfill]; + }]; + + [call startWithWriteable:responsesWriteable]; + + [self waitForExpectationsWithTimeout:2.0 handler:nil]; +} + +- (void)testEmptyRPC { + __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."]; + __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."]; + + GRPCMethodName *method = [[GRPCMethodName alloc] initWithPackage:@"grpc.example.routeguide" + interface:@"RouteGuide" + method:@"RecordRoute"]; + + id requestsWriter = [GRXWriter emptyWriter]; + + GRPCCall *call = [[GRPCCall alloc] initWithHost:@"http://127.0.0.1:8980" + method:method + requestsWriter:requestsWriter]; + + id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { + XCTAssertNotNil(value, @"nil value received as response."); + XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value); + [response fulfill]; + } completionHandler:^(NSError *errorOrNil) { + XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil); + [completion fulfill]; + }]; + + [call startWithWriteable:responsesWriteable]; + + [self waitForExpectationsWithTimeout:2.0 handler:nil]; +} + +- (void)testSimpleProtoRPC { + __weak XCTestExpectation *response = [self expectationWithDescription:@"Response received."]; + __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; + + GRPCMethodName *method = [[GRPCMethodName alloc] initWithPackage:@"grpc.example.routeguide" + interface:@"RouteGuide" + method:@"GetFeature"]; + + RGDPoint *point = [RGDPoint message]; + point.latitude = 28E7; + point.longitude = -15E7; + id requestsWriter = [GRXWriter writerWithValue:[point data]]; + + GRPCCall *call = [[GRPCCall alloc] initWithHost:@"http://127.0.0.1:8980" + method:method + requestsWriter:requestsWriter]; + + id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { + XCTAssertNotNil(value, @"nil value received as response."); + RGDFeature *feature = [RGDFeature parseFromData:value error:NULL]; + XCTAssertEqualObjects(point, feature.location); + XCTAssertNotNil(feature.name, @"Response's name is nil."); + [response fulfill]; + } completionHandler:^(NSError *errorOrNil) { + XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil); + [completion fulfill]; + }]; + + [call startWithWriteable:responsesWriteable]; + + [self waitForExpectationsWithTimeout:2.0 handler:nil]; +} + +- (void)testSimpleProtoRPCUsingGeneratedService { + __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; + + RGDPoint *point = [RGDPoint message]; + point.latitude = 28E7; + point.longitude = -15E7; + + RGDRouteGuide *service = [[RGDRouteGuide alloc] initWithHost:@"http://127.0.0.1:8980"]; + [service getFeatureWithRequest:point handler:^(RGDFeature *response, NSError *error) { + XCTAssertNil(error, @"Finished with unexpected error: %@", error); + XCTAssertEqualObjects(point, response.location); + XCTAssertNotNil(response.name, @"Response's name is nil."); + [completion fulfill]; + }]; + + [self waitForExpectationsWithTimeout:2.0 handler:nil]; +} +@end diff --git a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj index 3a98fec11a3..9eed26a84be 100644 --- a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj +++ b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 63175DFF1B1B9FAF00027841 /* LocalClearTextTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63175DFE1B1B9FAF00027841 /* LocalClearTextTests.m */; }; 63423F4A1B150A5F006CF63C /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; 63423F511B151B77006CF63C /* RxLibraryUnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63423F501B151B77006CF63C /* RxLibraryUnitTests.m */; }; 635697CD1B14FC11007A7283 /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 635697CC1B14FC11007A7283 /* Tests.m */; }; @@ -39,6 +40,7 @@ /* Begin PBXFileReference section */ 0A4F89D9C90E9C30990218F0 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 35F2B6BF3BAE8F0DC4AFD76E /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 63175DFE1B1B9FAF00027841 /* LocalClearTextTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LocalClearTextTests.m; sourceTree = ""; }; 63423F441B150A5F006CF63C /* AllTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AllTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 63423F501B151B77006CF63C /* RxLibraryUnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RxLibraryUnitTests.m; sourceTree = ""; }; 635697C71B14FC11007A7283 /* libTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTests.a; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -107,6 +109,7 @@ 635697C91B14FC11007A7283 /* Tests */ = { isa = PBXGroup; children = ( + 63175DFE1B1B9FAF00027841 /* LocalClearTextTests.m */, 635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */, 63423F501B151B77006CF63C /* RxLibraryUnitTests.m */, 635697CC1B14FC11007A7283 /* Tests.m */, @@ -246,6 +249,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 63175DFF1B1B9FAF00027841 /* LocalClearTextTests.m in Sources */, 63423F511B151B77006CF63C /* RxLibraryUnitTests.m in Sources */, 635ED2EC1B1A3BC400FDE5C3 /* InteropTests.m in Sources */, ); From e90cd37a1dd9d101cb51a6fd2628773b9135cbdb Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Sun, 31 May 2015 18:15:26 -0700 Subject: [PATCH 24/52] Added "inf" as a valid option to run_test.py's -n flag. Especially useful in combination with -f. --- tools/run_tests/jobset.py | 4 +++- tools/run_tests/run_tests.py | 30 +++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/tools/run_tests/jobset.py b/tools/run_tests/jobset.py index e2b03bd0ab0..61a95b0d555 100755 --- a/tools/run_tests/jobset.py +++ b/tools/run_tests/jobset.py @@ -339,13 +339,15 @@ def run(cmdlines, maxjobs=None, newline_on_success=False, travis=False, + infinite_runs=False, stop_on_failure=False, cache=None): js = Jobset(check_cancelled, maxjobs if maxjobs is not None else _DEFAULT_MAX_JOBS, newline_on_success, travis, stop_on_failure, cache if cache is not None else NoCache()) - if not travis: + # We can't sort an infinite sequence of runs. + if not travis or infinite_runs: cmdlines = shuffle_iteratable(cmdlines) else: cmdlines = sorted(cmdlines, key=lambda x: x.shortname) diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index 602edc70ba4..609b6c657d9 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -330,7 +330,28 @@ argp.add_argument('-c', '--config', choices=['all'] + sorted(_CONFIGS.keys()), nargs='+', default=_DEFAULT) -argp.add_argument('-n', '--runs_per_test', default=1, type=int) + +def runs_per_test_type(arg_str): + """Auxilary function to parse the "runs_per_test" flag. + + Returns: + A positive integer or 0, the latter indicating an infinite number of + runs. + + Raises: + argparse.ArgumentTypeError: Upon invalid input. + """ + if arg_str == 'inf': + return 0 + try: + n = int(arg_str) + if n <= 0: raise ValueError + except: + msg = "'{}' isn't a positive integer or 'inf'".format(arg_str) + raise argparse.ArgumentTypeError(msg) +argp.add_argument('-n', '--runs_per_test', default=1, type=runs_per_test_type, + help='A positive integer or "inf". If "inf", all tests will run in an ' + 'infinite loop. Especially useful in combination with "-f"') argp.add_argument('-r', '--regex', default='.*', type=str) argp.add_argument('-j', '--jobs', default=2 * multiprocessing.cpu_count(), type=int) argp.add_argument('-s', '--slowdown', default=1.0, type=float) @@ -453,11 +474,14 @@ def _build_and_run(check_cancelled, newline_on_success, travis, cache): antagonists = [subprocess.Popen(['tools/run_tests/antagonist.py']) for _ in range(0, args.antagonists)] try: + infinite_runs = runs_per_test == 0 # run all the tests - all_runs = itertools.chain.from_iterable( - itertools.repeat(one_run, runs_per_test)) + runs_sequence = (itertools.repeat(one_run) if infinite_runs + else itertools.repeat(one_run, runs_per_test)) + all_runs = itertools.chain.from_iterable(runs_sequence) if not jobset.run(all_runs, check_cancelled, newline_on_success=newline_on_success, travis=travis, + infinite_runs=infinite_runs, maxjobs=args.jobs, stop_on_failure=args.stop_on_failure, cache=cache): From b3be22956cd8053c85cd26119e980eda8a5300f3 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Sun, 31 May 2015 19:11:20 -0700 Subject: [PATCH 25/52] Add RemoteTests as GRPCClientTests to tests project --- src/objective-c/tests/GRPCClientTests.m | 146 ++++++++++++++++++ .../tests/Tests.xcodeproj/project.pbxproj | 4 + 2 files changed, 150 insertions(+) create mode 100644 src/objective-c/tests/GRPCClientTests.m diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m new file mode 100644 index 00000000000..713ea2848a1 --- /dev/null +++ b/src/objective-c/tests/GRPCClientTests.m @@ -0,0 +1,146 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#import +#import + +#import +#import +#import +#import +#import + +// These are a few tests similar to InteropTests, but which use the generic gRPC client (GRPCCall) +// rather than a generated proto library on top of it. + +@interface GRPCClientTests : XCTestCase +@end + +@implementation GRPCClientTests + +- (void)testConnectionToRemoteServer { + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Server reachable."]; + + // This method isn't implemented by the remote server. + GRPCMethodName *method = [[GRPCMethodName alloc] initWithPackage:@"grpc.testing" + interface:@"TestService" + method:@"Nonexistent"]; + + id requestsWriter = [GRXWriter writerWithValue:[NSData data]]; + + GRPCCall *call = [[GRPCCall alloc] initWithHost:@"grpc-test.sandbox.google.com" + method:method + requestsWriter:requestsWriter]; + + id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { + XCTFail(@"Received unexpected response: %@", value); + } completionHandler:^(NSError *errorOrNil) { + XCTAssertNotNil(errorOrNil, @"Finished without error!"); + // TODO(jcanizales): The server should return code 12 UNIMPLEMENTED, not 5 NOT FOUND. + XCTAssertEqual(errorOrNil.code, 5, @"Finished with unexpected error: %@", errorOrNil); + [expectation fulfill]; + }]; + + [call startWithWriteable:responsesWriteable]; + + [self waitForExpectationsWithTimeout:2. handler:nil]; +} + +- (void)testEmptyRPC { + __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."]; + __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."]; + + GRPCMethodName *method = [[GRPCMethodName alloc] initWithPackage:@"grpc.testing" + interface:@"TestService" + method:@"EmptyCall"]; + + id requestsWriter = [GRXWriter writerWithValue:[NSData data]]; + + GRPCCall *call = [[GRPCCall alloc] initWithHost:@"grpc-test.sandbox.google.com" + method:method + requestsWriter:requestsWriter]; + + id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { + XCTAssertNotNil(value, @"nil value received as response."); + XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value); + [response fulfill]; + } completionHandler:^(NSError *errorOrNil) { + XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil); + [completion fulfill]; + }]; + + [call startWithWriteable:responsesWriteable]; + + [self waitForExpectationsWithTimeout:2. handler:nil]; +} + +- (void)testSimpleProtoRPC { + __weak XCTestExpectation *response = [self expectationWithDescription:@"Response received."]; + __weak XCTestExpectation *expectedResponse = + [self expectationWithDescription:@"Expected response."]; + __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; + + GRPCMethodName *method = [[GRPCMethodName alloc] initWithPackage:@"grpc.testing" + interface:@"TestService" + method:@"UnaryCall"]; + + RMTSimpleRequest *request = [[RMTSimpleRequest alloc] init]; + request.responseSize = 100; + request.fillUsername = YES; + request.fillOauthScope = YES; + id requestsWriter = [GRXWriter writerWithValue:[request data]]; + + GRPCCall *call = [[GRPCCall alloc] initWithHost:@"grpc-test.sandbox.google.com" + method:method + requestsWriter:requestsWriter]; + + id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { + XCTAssertNotNil(value, @"nil value received as response."); + [response fulfill]; + XCTAssertGreaterThan(value.length, 0, @"Empty response received."); + RMTSimpleResponse *response = [RMTSimpleResponse parseFromData:value error:NULL]; + // We expect empty strings, not nil: + XCTAssertNotNil(response.username, @"Response's username is nil."); + XCTAssertNotNil(response.oauthScope, @"Response's OAuth scope is nil."); + [expectedResponse fulfill]; + } completionHandler:^(NSError *errorOrNil) { + XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil); + [completion fulfill]; + }]; + + [call startWithWriteable:responsesWriteable]; + + [self waitForExpectationsWithTimeout:2. handler:nil]; +} + +@end diff --git a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj index 9eed26a84be..34be705db2b 100644 --- a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj +++ b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 6312AE4E1B1BF49B00341DEE /* GRPCClientTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6312AE4D1B1BF49B00341DEE /* GRPCClientTests.m */; }; 63175DFF1B1B9FAF00027841 /* LocalClearTextTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63175DFE1B1B9FAF00027841 /* LocalClearTextTests.m */; }; 63423F4A1B150A5F006CF63C /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; 63423F511B151B77006CF63C /* RxLibraryUnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63423F501B151B77006CF63C /* RxLibraryUnitTests.m */; }; @@ -40,6 +41,7 @@ /* Begin PBXFileReference section */ 0A4F89D9C90E9C30990218F0 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 35F2B6BF3BAE8F0DC4AFD76E /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 6312AE4D1B1BF49B00341DEE /* GRPCClientTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GRPCClientTests.m; sourceTree = ""; }; 63175DFE1B1B9FAF00027841 /* LocalClearTextTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LocalClearTextTests.m; sourceTree = ""; }; 63423F441B150A5F006CF63C /* AllTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AllTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 63423F501B151B77006CF63C /* RxLibraryUnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RxLibraryUnitTests.m; sourceTree = ""; }; @@ -109,6 +111,7 @@ 635697C91B14FC11007A7283 /* Tests */ = { isa = PBXGroup; children = ( + 6312AE4D1B1BF49B00341DEE /* GRPCClientTests.m */, 63175DFE1B1B9FAF00027841 /* LocalClearTextTests.m */, 635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */, 63423F501B151B77006CF63C /* RxLibraryUnitTests.m */, @@ -251,6 +254,7 @@ files = ( 63175DFF1B1B9FAF00027841 /* LocalClearTextTests.m in Sources */, 63423F511B151B77006CF63C /* RxLibraryUnitTests.m in Sources */, + 6312AE4E1B1BF49B00341DEE /* GRPCClientTests.m in Sources */, 635ED2EC1B1A3BC400FDE5C3 /* InteropTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; From 2ab53833bf1d8ccd9a16d7cd2ea99ba40d999bfd Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Sat, 30 May 2015 23:15:18 -0700 Subject: [PATCH 26/52] Remove remaining tests and RouteGuide from sample app --- src/objective-c/examples/Sample/Podfile | 6 - .../Sample/Sample.xcodeproj/project.pbxproj | 169 ------------------ .../examples/Sample/SampleTests/Info.plist | 24 --- .../examples/Sample/SampleTests/RemoteTests.m | 143 --------------- .../examples/Sample/SampleTests/SampleTests.m | 157 ---------------- 5 files changed, 499 deletions(-) delete mode 100644 src/objective-c/examples/Sample/SampleTests/Info.plist delete mode 100644 src/objective-c/examples/Sample/SampleTests/RemoteTests.m delete mode 100644 src/objective-c/examples/Sample/SampleTests/SampleTests.m diff --git a/src/objective-c/examples/Sample/Podfile b/src/objective-c/examples/Sample/Podfile index 0d077387c19..f3c49c12a17 100644 --- a/src/objective-c/examples/Sample/Podfile +++ b/src/objective-c/examples/Sample/Podfile @@ -3,13 +3,7 @@ platform :ios, '8.0' pod 'gRPC', :path => "../../../.." pod 'Protobuf', :git => 'https://github.com/google/protobuf.git' -pod 'Route_guide', :path => "RouteGuideClient" pod 'RemoteTest', :path => "../../generated_libraries/RemoteTestClient" -link_with 'Sample', 'SampleTests' - target 'Sample' do end - -target 'SampleTests' do -end diff --git a/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj b/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj index 877d65a7011..916aa24d9d2 100644 --- a/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj +++ b/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj @@ -7,31 +7,17 @@ objects = { /* Begin PBXBuildFile section */ - 60BBBBB15823BBF7639D7AA9 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DC7B7C4C0410F43B9621631 /* libPods.a */; }; - 6356D1DE1AC11FE00075FBBC /* RemoteTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6356D1DD1AC11FE00075FBBC /* RemoteTests.m */; }; 6369A2701A9322E20015FC5C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A26F1A9322E20015FC5C /* main.m */; }; 6369A2731A9322E20015FC5C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2721A9322E20015FC5C /* AppDelegate.m */; }; 6369A2761A9322E20015FC5C /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2751A9322E20015FC5C /* ViewController.m */; }; 6369A2791A9322E20015FC5C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6369A2771A9322E20015FC5C /* Main.storyboard */; }; 6369A27B1A9322E20015FC5C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6369A27A1A9322E20015FC5C /* Images.xcassets */; }; 6369A27E1A9322E20015FC5C /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6369A27C1A9322E20015FC5C /* LaunchScreen.xib */; }; - 6369A28A1A9322E20015FC5C /* SampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2891A9322E20015FC5C /* SampleTests.m */; }; FC81FE63CA655031F3524EC0 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DC7B7C4C0410F43B9621631 /* libPods.a */; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - 6369A2841A9322E20015FC5C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 6369A2621A9322E20015FC5C /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6369A2691A9322E20015FC5C; - remoteInfo = Sample; - }; -/* End PBXContainerItemProxy section */ - /* Begin PBXFileReference section */ 2DC7B7C4C0410F43B9621631 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 6356D1DD1AC11FE00075FBBC /* RemoteTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RemoteTests.m; sourceTree = ""; }; 6369A26A1A9322E20015FC5C /* Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6369A26E1A9322E20015FC5C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6369A26F1A9322E20015FC5C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; @@ -42,9 +28,6 @@ 6369A2781A9322E20015FC5C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 6369A27A1A9322E20015FC5C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 6369A27D1A9322E20015FC5C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6369A2831A9322E20015FC5C /* SampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 6369A2881A9322E20015FC5C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6369A2891A9322E20015FC5C /* SampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleTests.m; sourceTree = ""; }; AC29DD6FCDF962F519FEBB0D /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; C68330F8D451CC6ACEABA09F /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -58,14 +41,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 6369A2801A9322E20015FC5C /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 60BBBBB15823BBF7639D7AA9 /* libPods.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -73,7 +48,6 @@ isa = PBXGroup; children = ( 6369A26C1A9322E20015FC5C /* Sample */, - 6369A2861A9322E20015FC5C /* SampleTests */, 6369A26B1A9322E20015FC5C /* Products */, AB3331C9AE6488E61B2B094E /* Pods */, C4C2C5219053E079C9EFB930 /* Frameworks */, @@ -84,7 +58,6 @@ isa = PBXGroup; children = ( 6369A26A1A9322E20015FC5C /* Sample.app */, - 6369A2831A9322E20015FC5C /* SampleTests.xctest */, ); name = Products; sourceTree = ""; @@ -113,24 +86,6 @@ name = "Supporting Files"; sourceTree = ""; }; - 6369A2861A9322E20015FC5C /* SampleTests */ = { - isa = PBXGroup; - children = ( - 6369A2891A9322E20015FC5C /* SampleTests.m */, - 6369A2871A9322E20015FC5C /* Supporting Files */, - 6356D1DD1AC11FE00075FBBC /* RemoteTests.m */, - ); - path = SampleTests; - sourceTree = ""; - }; - 6369A2871A9322E20015FC5C /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6369A2881A9322E20015FC5C /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; AB3331C9AE6488E61B2B094E /* Pods */ = { isa = PBXGroup; children = ( @@ -170,26 +125,6 @@ productReference = 6369A26A1A9322E20015FC5C /* Sample.app */; productType = "com.apple.product-type.application"; }; - 6369A2821A9322E20015FC5C /* SampleTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6369A2901A9322E20015FC5C /* Build configuration list for PBXNativeTarget "SampleTests" */; - buildPhases = ( - 75C393B2FDC60A22B2121058 /* Check Pods Manifest.lock */, - 6369A27F1A9322E20015FC5C /* Sources */, - 6369A2801A9322E20015FC5C /* Frameworks */, - 6369A2811A9322E20015FC5C /* Resources */, - 7B8CDC152F76D6014A96C798 /* Copy Pods Resources */, - ); - buildRules = ( - ); - dependencies = ( - 6369A2851A9322E20015FC5C /* PBXTargetDependency */, - ); - name = SampleTests; - productName = SampleTests; - productReference = 6369A2831A9322E20015FC5C /* SampleTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -202,10 +137,6 @@ 6369A2691A9322E20015FC5C = { CreatedOnToolsVersion = 6.1.1; }; - 6369A2821A9322E20015FC5C = { - CreatedOnToolsVersion = 6.1.1; - TestTargetID = 6369A2691A9322E20015FC5C; - }; }; }; buildConfigurationList = 6369A2651A9322E20015FC5C /* Build configuration list for PBXProject "Sample" */; @@ -222,7 +153,6 @@ projectRoot = ""; targets = ( 6369A2691A9322E20015FC5C /* Sample */, - 6369A2821A9322E20015FC5C /* SampleTests */, ); }; /* End PBXProject section */ @@ -238,13 +168,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 6369A2811A9322E20015FC5C /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ @@ -278,36 +201,6 @@ shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; - 75C393B2FDC60A22B2121058 /* Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Check Pods Manifest.lock"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; - showEnvVarsInLog = 0; - }; - 7B8CDC152F76D6014A96C798 /* Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -321,25 +214,8 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 6369A27F1A9322E20015FC5C /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6369A28A1A9322E20015FC5C /* SampleTests.m in Sources */, - 6356D1DE1AC11FE00075FBBC /* RemoteTests.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 6369A2851A9322E20015FC5C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 6369A2691A9322E20015FC5C /* Sample */; - targetProxy = 6369A2841A9322E20015FC5C /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin PBXVariantGroup section */ 6369A2771A9322E20015FC5C /* Main.storyboard */ = { isa = PBXVariantGroup; @@ -460,42 +336,6 @@ }; name = Release; }; - 6369A2911A9322E20015FC5C /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = AC29DD6FCDF962F519FEBB0D /* Pods.debug.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = SampleTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Sample.app/Sample"; - }; - name = Debug; - }; - 6369A2921A9322E20015FC5C /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C68330F8D451CC6ACEABA09F /* Pods.release.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - INFOPLIST_FILE = SampleTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Sample.app/Sample"; - }; - name = Release; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -517,15 +357,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 6369A2901A9322E20015FC5C /* Build configuration list for PBXNativeTarget "SampleTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6369A2911A9322E20015FC5C /* Debug */, - 6369A2921A9322E20015FC5C /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; /* End XCConfigurationList section */ }; rootObject = 6369A2621A9322E20015FC5C /* Project object */; diff --git a/src/objective-c/examples/Sample/SampleTests/Info.plist b/src/objective-c/examples/Sample/SampleTests/Info.plist deleted file mode 100644 index f547b0b7072..00000000000 --- a/src/objective-c/examples/Sample/SampleTests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.grpc.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - diff --git a/src/objective-c/examples/Sample/SampleTests/RemoteTests.m b/src/objective-c/examples/Sample/SampleTests/RemoteTests.m deleted file mode 100644 index ceb72cfaecb..00000000000 --- a/src/objective-c/examples/Sample/SampleTests/RemoteTests.m +++ /dev/null @@ -1,143 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#import -#import - -#import -#import -#import -#import -#import - -@interface RemoteTests : XCTestCase -@end - -@implementation RemoteTests - -- (void)testConnectionToRemoteServer { - __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Server reachable."]; - - // This method isn't implemented by the remote server. - GRPCMethodName *method = [[GRPCMethodName alloc] initWithPackage:@"grpc.testing" - interface:@"TestService" - method:@"Nonexistent"]; - - id requestsWriter = [GRXWriter writerWithValue:[NSData data]]; - - GRPCCall *call = [[GRPCCall alloc] initWithHost:@"grpc-test.sandbox.google.com" - method:method - requestsWriter:requestsWriter]; - - id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { - XCTFail(@"Received unexpected response: %@", value); - } completionHandler:^(NSError *errorOrNil) { - XCTAssertNotNil(errorOrNil, @"Finished without error!"); - // TODO(jcanizales): The server should return code 12 UNIMPLEMENTED, not 5 NOT FOUND. - XCTAssertEqual(errorOrNil.code, 5, @"Finished with unexpected error: %@", errorOrNil); - [expectation fulfill]; - }]; - - [call startWithWriteable:responsesWriteable]; - - [self waitForExpectationsWithTimeout:2. handler:nil]; -} - -- (void)testEmptyRPC { - __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."]; - __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."]; - - GRPCMethodName *method = [[GRPCMethodName alloc] initWithPackage:@"grpc.testing" - interface:@"TestService" - method:@"EmptyCall"]; - - id requestsWriter = [GRXWriter writerWithValue:[NSData data]]; - - GRPCCall *call = [[GRPCCall alloc] initWithHost:@"grpc-test.sandbox.google.com" - method:method - requestsWriter:requestsWriter]; - - id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { - XCTAssertNotNil(value, @"nil value received as response."); - XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value); - [response fulfill]; - } completionHandler:^(NSError *errorOrNil) { - XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil); - [completion fulfill]; - }]; - - [call startWithWriteable:responsesWriteable]; - - [self waitForExpectationsWithTimeout:2. handler:nil]; -} - -- (void)testSimpleProtoRPC { - __weak XCTestExpectation *response = [self expectationWithDescription:@"Response received."]; - __weak XCTestExpectation *expectedResponse = - [self expectationWithDescription:@"Expected response."]; - __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; - - GRPCMethodName *method = [[GRPCMethodName alloc] initWithPackage:@"grpc.testing" - interface:@"TestService" - method:@"UnaryCall"]; - - RMTSimpleRequest *request = [[RMTSimpleRequest alloc] init]; - request.responseSize = 100; - request.fillUsername = YES; - request.fillOauthScope = YES; - id requestsWriter = [GRXWriter writerWithValue:[request data]]; - - GRPCCall *call = [[GRPCCall alloc] initWithHost:@"grpc-test.sandbox.google.com" - method:method - requestsWriter:requestsWriter]; - - id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { - XCTAssertNotNil(value, @"nil value received as response."); - [response fulfill]; - XCTAssertGreaterThan(value.length, 0, @"Empty response received."); - RMTSimpleResponse *response = [RMTSimpleResponse parseFromData:value error:NULL]; - // We expect empty strings, not nil: - XCTAssertNotNil(response.username, @"Response's username is nil."); - XCTAssertNotNil(response.oauthScope, @"Response's OAuth scope is nil."); - [expectedResponse fulfill]; - } completionHandler:^(NSError *errorOrNil) { - XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil); - [completion fulfill]; - }]; - - [call startWithWriteable:responsesWriteable]; - - [self waitForExpectationsWithTimeout:2. handler:nil]; -} - -@end diff --git a/src/objective-c/examples/Sample/SampleTests/SampleTests.m b/src/objective-c/examples/Sample/SampleTests/SampleTests.m deleted file mode 100644 index 83cfd8c1b59..00000000000 --- a/src/objective-c/examples/Sample/SampleTests/SampleTests.m +++ /dev/null @@ -1,157 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#import -#import - -#import -#import -#import -#import -#import -#import - -@interface SampleTests : XCTestCase -@end - -// These tests require the gRPC-Java "RouteGuide" sample server to be running locally. Install the -// gRPC-Java library following the instructions here: https://github.com/grpc/grpc-java And run the -// server by following the instructions here: https://github.com/grpc/grpc-java/tree/master/examples -@implementation SampleTests - -- (void)testConnectionToLocalServer { - __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Server reachable."]; - - // This method isn't implemented by the local server. - GRPCMethodName *method = [[GRPCMethodName alloc] initWithPackage:@"grpc.testing" - interface:@"TestService" - method:@"EmptyCall"]; - - id requestsWriter = [GRXWriter writerWithValue:[NSData data]]; - - GRPCCall *call = [[GRPCCall alloc] initWithHost:@"http://127.0.0.1:8980" - method:method - requestsWriter:requestsWriter]; - - id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { - XCTFail(@"Received unexpected response: %@", value); - } completionHandler:^(NSError *errorOrNil) { - XCTAssertNotNil(errorOrNil, @"Finished without error!"); - XCTAssertEqual(errorOrNil.code, 12, @"Finished with unexpected error: %@", errorOrNil); - [expectation fulfill]; - }]; - - [call startWithWriteable:responsesWriteable]; - - [self waitForExpectationsWithTimeout:2.0 handler:nil]; -} - -- (void)testEmptyRPC { - __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."]; - __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."]; - - GRPCMethodName *method = [[GRPCMethodName alloc] initWithPackage:@"grpc.example.routeguide" - interface:@"RouteGuide" - method:@"RecordRoute"]; - - id requestsWriter = [GRXWriter emptyWriter]; - - GRPCCall *call = [[GRPCCall alloc] initWithHost:@"http://127.0.0.1:8980" - method:method - requestsWriter:requestsWriter]; - - id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { - XCTAssertNotNil(value, @"nil value received as response."); - XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value); - [response fulfill]; - } completionHandler:^(NSError *errorOrNil) { - XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil); - [completion fulfill]; - }]; - - [call startWithWriteable:responsesWriteable]; - - [self waitForExpectationsWithTimeout:2.0 handler:nil]; -} - -- (void)testSimpleProtoRPC { - __weak XCTestExpectation *response = [self expectationWithDescription:@"Response received."]; - __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; - - GRPCMethodName *method = [[GRPCMethodName alloc] initWithPackage:@"grpc.example.routeguide" - interface:@"RouteGuide" - method:@"GetFeature"]; - - RGDPoint *point = [RGDPoint message]; - point.latitude = 28E7; - point.longitude = -15E7; - id requestsWriter = [GRXWriter writerWithValue:[point data]]; - - GRPCCall *call = [[GRPCCall alloc] initWithHost:@"http://127.0.0.1:8980" - method:method - requestsWriter:requestsWriter]; - - id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { - XCTAssertNotNil(value, @"nil value received as response."); - RGDFeature *feature = [RGDFeature parseFromData:value error:NULL]; - XCTAssertEqualObjects(point, feature.location); - XCTAssertNotNil(feature.name, @"Response's name is nil."); - [response fulfill]; - } completionHandler:^(NSError *errorOrNil) { - XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil); - [completion fulfill]; - }]; - - [call startWithWriteable:responsesWriteable]; - - [self waitForExpectationsWithTimeout:2.0 handler:nil]; -} - -- (void)testSimpleProtoRPCUsingGeneratedService { - __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; - - RGDPoint *point = [RGDPoint message]; - point.latitude = 28E7; - point.longitude = -15E7; - - RGDRouteGuide *service = [[RGDRouteGuide alloc] initWithHost:@"http://127.0.0.1:8980"]; - [service getFeatureWithRequest:point handler:^(RGDFeature *response, NSError *error) { - XCTAssertNil(error, @"Finished with unexpected error: %@", error); - XCTAssertEqualObjects(point, response.location); - XCTAssertNotNil(response.name, @"Response's name is nil."); - [completion fulfill]; - }]; - - [self waitForExpectationsWithTimeout:2.0 handler:nil]; -} -@end From 08dfef224e2012e0d3eca83a7407be239ccced8d Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Sun, 31 May 2015 19:58:07 -0700 Subject: [PATCH 27/52] Make sample app easier to understand - Remove the launch screen. - Add a label explaining where to look for the code and results. - Delete unnecessary boilerplate code. --- .../Sample/Sample.xcodeproj/project.pbxproj | 12 ------ .../examples/Sample/Sample/AppDelegate.h | 3 -- .../examples/Sample/Sample/AppDelegate.m | 8 ---- .../Sample/Sample/Base.lproj/LaunchScreen.xib | 41 ------------------- .../Sample/Sample/Base.lproj/Main.storyboard | 38 +++++++++++++++-- .../examples/Sample/Sample/Info.plist | 2 +- .../examples/Sample/Sample/ViewController.m | 3 -- 7 files changed, 36 insertions(+), 71 deletions(-) delete mode 100644 src/objective-c/examples/Sample/Sample/Base.lproj/LaunchScreen.xib diff --git a/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj b/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj index 916aa24d9d2..611eb6032d5 100644 --- a/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj +++ b/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj @@ -12,7 +12,6 @@ 6369A2761A9322E20015FC5C /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2751A9322E20015FC5C /* ViewController.m */; }; 6369A2791A9322E20015FC5C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6369A2771A9322E20015FC5C /* Main.storyboard */; }; 6369A27B1A9322E20015FC5C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6369A27A1A9322E20015FC5C /* Images.xcassets */; }; - 6369A27E1A9322E20015FC5C /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6369A27C1A9322E20015FC5C /* LaunchScreen.xib */; }; FC81FE63CA655031F3524EC0 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DC7B7C4C0410F43B9621631 /* libPods.a */; }; /* End PBXBuildFile section */ @@ -27,7 +26,6 @@ 6369A2751A9322E20015FC5C /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 6369A2781A9322E20015FC5C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 6369A27A1A9322E20015FC5C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6369A27D1A9322E20015FC5C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; AC29DD6FCDF962F519FEBB0D /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; C68330F8D451CC6ACEABA09F /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -71,7 +69,6 @@ 6369A2751A9322E20015FC5C /* ViewController.m */, 6369A2771A9322E20015FC5C /* Main.storyboard */, 6369A27A1A9322E20015FC5C /* Images.xcassets */, - 6369A27C1A9322E20015FC5C /* LaunchScreen.xib */, 6369A26D1A9322E20015FC5C /* Supporting Files */, ); path = Sample; @@ -163,7 +160,6 @@ buildActionMask = 2147483647; files = ( 6369A2791A9322E20015FC5C /* Main.storyboard in Resources */, - 6369A27E1A9322E20015FC5C /* LaunchScreen.xib in Resources */, 6369A27B1A9322E20015FC5C /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -225,14 +221,6 @@ name = Main.storyboard; sourceTree = ""; }; - 6369A27C1A9322E20015FC5C /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6369A27D1A9322E20015FC5C /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ diff --git a/src/objective-c/examples/Sample/Sample/AppDelegate.h b/src/objective-c/examples/Sample/Sample/AppDelegate.h index b1857f28e08..102e7f3adea 100644 --- a/src/objective-c/examples/Sample/Sample/AppDelegate.h +++ b/src/objective-c/examples/Sample/Sample/AppDelegate.h @@ -34,8 +34,5 @@ #import @interface AppDelegate : UIResponder - @property (strong, nonatomic) UIWindow *window; - @end - diff --git a/src/objective-c/examples/Sample/Sample/AppDelegate.m b/src/objective-c/examples/Sample/Sample/AppDelegate.m index 12e1ad9d676..a38e36651ed 100644 --- a/src/objective-c/examples/Sample/Sample/AppDelegate.m +++ b/src/objective-c/examples/Sample/Sample/AppDelegate.m @@ -33,13 +33,5 @@ #import "AppDelegate.h" -@interface AppDelegate () -@end - @implementation AppDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - return YES; -} - @end diff --git a/src/objective-c/examples/Sample/Sample/Base.lproj/LaunchScreen.xib b/src/objective-c/examples/Sample/Sample/Base.lproj/LaunchScreen.xib deleted file mode 100644 index c51a8e199eb..00000000000 --- a/src/objective-c/examples/Sample/Sample/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/objective-c/examples/Sample/Sample/Base.lproj/Main.storyboard b/src/objective-c/examples/Sample/Sample/Base.lproj/Main.storyboard index f56d2f3bb56..8887b9e19ff 100644 --- a/src/objective-c/examples/Sample/Sample/Base.lproj/Main.storyboard +++ b/src/objective-c/examples/Sample/Sample/Base.lproj/Main.storyboard @@ -1,13 +1,14 @@ - + - + + - + @@ -15,7 +16,38 @@ + + + + + + + + + + + + + + + diff --git a/src/objective-c/examples/Sample/Sample/Info.plist b/src/objective-c/examples/Sample/Sample/Info.plist index ffdc8b30122..4436635ab4e 100644 --- a/src/objective-c/examples/Sample/Sample/Info.plist +++ b/src/objective-c/examples/Sample/Sample/Info.plist @@ -23,7 +23,7 @@ LSRequiresIPhoneOS UILaunchStoryboardName - LaunchScreen + Main UIMainStoryboardFile Main UIRequiredDeviceCapabilities diff --git a/src/objective-c/examples/Sample/Sample/ViewController.m b/src/objective-c/examples/Sample/Sample/ViewController.m index 9b331fe43fb..0011a4508df 100644 --- a/src/objective-c/examples/Sample/Sample/ViewController.m +++ b/src/objective-c/examples/Sample/Sample/ViewController.m @@ -40,9 +40,6 @@ #import #import -@interface ViewController () -@end - @implementation ViewController - (void)viewDidLoad { From 52592fc78428c88c8a5f342c0ba04d5e328b7789 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Tue, 26 May 2015 11:53:31 -0700 Subject: [PATCH 28/52] Use class names for types as generated by the messages plugin --- src/compiler/objective_c_generator.cc | 63 ++++++++++---------- src/compiler/objective_c_generator.h | 9 +-- src/compiler/objective_c_generator_helpers.h | 12 +++- src/compiler/objective_c_plugin.cc | 4 +- 4 files changed, 50 insertions(+), 38 deletions(-) diff --git a/src/compiler/objective_c_generator.cc b/src/compiler/objective_c_generator.cc index 1bf0254f5b8..b235911479c 100644 --- a/src/compiler/objective_c_generator.cc +++ b/src/compiler/objective_c_generator.cc @@ -32,19 +32,20 @@ */ #include +#include +#include "src/compiler/config.h" #include "src/compiler/objective_c_generator.h" #include "src/compiler/objective_c_generator_helpers.h" -#include "src/compiler/config.h" - -#include +#include +using ::google::protobuf::compiler::objectivec::ClassName; using ::grpc::protobuf::io::Printer; using ::grpc::protobuf::MethodDescriptor; using ::grpc::protobuf::ServiceDescriptor; -using ::std::map; using ::grpc::string; +using ::std::map; namespace grpc_objective_c_generator { namespace { @@ -69,7 +70,7 @@ void PrintMethodSignature(Printer *printer, if (method->client_streaming()) { printer->Print("RequestsWriter:(id)request"); } else { - printer->Print(vars, "Request:($prefix$$request_type$ *)request"); + printer->Print(vars, "Request:($request_class$ *)request"); } // TODO(jcanizales): Put this on a new line and align colons. @@ -78,8 +79,7 @@ void PrintMethodSignature(Printer *printer, if (method->server_streaming()) { printer->Print("BOOL done, "); } - printer->Print(vars, - "$prefix$$response_type$ *response, NSError *error))handler"); + printer->Print(vars, "$response_class$ *response, NSError *error))handler"); } void PrintSimpleSignature(Printer *printer, @@ -99,12 +99,17 @@ void PrintAdvancedSignature(Printer *printer, PrintMethodSignature(printer, method, vars); } +inline map GetMethodVars(const MethodDescriptor *method) { + return {{ "method_name", method->name() }, + { "request_type", method->input_type()->name() }, + { "response_type", method->output_type()->name() }, + { "request_class", ClassName(method->input_type()) }, + { "response_class", ClassName(method->output_type()) }}; +} + void PrintMethodDeclarations(Printer *printer, - const MethodDescriptor *method, - map vars) { - vars["method_name"] = method->name(); - vars["request_type"] = method->input_type()->name(); - vars["response_type"] = method->output_type()->name(); + const MethodDescriptor *method) { + map vars = GetMethodVars(method); PrintProtoRpcDeclarationAsPragma(printer, method, vars); @@ -141,8 +146,7 @@ void PrintAdvancedImplementation(Printer *printer, printer->Print("[GRXWriter writerWithValue:request]\n"); } - printer->Print(vars, - " responseClass:[$prefix$$response_type$ class]\n"); + printer->Print(vars, " responseClass:[$response_class$ class]\n"); printer->Print(" responsesWriteable:[GRXWriteable "); if (method->server_streaming()) { @@ -155,11 +159,8 @@ void PrintAdvancedImplementation(Printer *printer, } void PrintMethodImplementations(Printer *printer, - const MethodDescriptor *method, - map vars) { - vars["method_name"] = method->name(); - vars["request_type"] = method->input_type()->name(); - vars["response_type"] = method->output_type()->name(); + const MethodDescriptor *method) { + map vars = GetMethodVars(method); PrintProtoRpcDeclarationAsPragma(printer, method, vars); @@ -174,7 +175,7 @@ void PrintMethodImplementations(Printer *printer, } // namespace -string GetHeader(const ServiceDescriptor *service, const string prefix) { +string GetHeader(const ServiceDescriptor *service) { string output; { // Scope the output stream so it closes and finalizes output to the string. @@ -184,19 +185,19 @@ string GetHeader(const ServiceDescriptor *service, const string prefix) { printer.Print("@protocol GRXWriteable;\n"); printer.Print("@protocol GRXWriter;\n\n"); - map vars = {{"service_name", service->name()}, - {"prefix", prefix}}; - printer.Print(vars, "@protocol $prefix$$service_name$ \n\n"); + map vars = {{"service_class", ServiceClassName(service)}}; + + printer.Print(vars, "@protocol $service_class$ \n\n"); for (int i = 0; i < service->method_count(); i++) { - PrintMethodDeclarations(&printer, service->method(i), vars); + PrintMethodDeclarations(&printer, service->method(i)); } printer.Print("@end\n\n"); printer.Print("// Basic service implementation, over gRPC, that only does" " marshalling and parsing.\n"); - printer.Print(vars, "@interface $prefix$$service_name$ :" - " ProtoService<$prefix$$service_name$>\n"); + printer.Print(vars, "@interface $service_class$ :" + " ProtoService<$service_class$>\n"); printer.Print("- (instancetype)initWithHost:(NSString *)host" " NS_DESIGNATED_INITIALIZER;\n"); printer.Print("@end\n"); @@ -204,7 +205,7 @@ string GetHeader(const ServiceDescriptor *service, const string prefix) { return output; } -string GetSource(const ServiceDescriptor *service, const string prefix) { +string GetSource(const ServiceDescriptor *service) { string output; { // Scope the output stream so it closes and finalizes output to the string. @@ -212,15 +213,15 @@ string GetSource(const ServiceDescriptor *service, const string prefix) { Printer printer(&output_stream, '$'); map vars = {{"service_name", service->name()}, - {"package", service->file()->package()}, - {"prefix", prefix}}; + {"service_class", ServiceClassName(service)}, + {"package", service->file()->package()}}; printer.Print(vars, "static NSString *const kPackageName = @\"$package$\";\n"); printer.Print(vars, "static NSString *const kServiceName = @\"$service_name$\";\n\n"); - printer.Print(vars, "@implementation $prefix$$service_name$\n\n"); + printer.Print(vars, "@implementation $service_class$\n\n"); printer.Print("// Designated initializer\n"); printer.Print("- (instancetype)initWithHost:(NSString *)host {\n"); @@ -236,7 +237,7 @@ string GetSource(const ServiceDescriptor *service, const string prefix) { printer.Print("}\n\n\n"); for (int i = 0; i < service->method_count(); i++) { - PrintMethodImplementations(&printer, service->method(i), vars); + PrintMethodImplementations(&printer, service->method(i)); } printer.Print("@end\n"); diff --git a/src/compiler/objective_c_generator.h b/src/compiler/objective_c_generator.h index 548e96fcf19..40a0c87f99c 100644 --- a/src/compiler/objective_c_generator.h +++ b/src/compiler/objective_c_generator.h @@ -38,15 +38,16 @@ namespace grpc_objective_c_generator { +using ::grpc::protobuf::ServiceDescriptor; +using ::grpc::string; + // Returns the content to be included in the "global_scope" insertion point of // the generated header file. -grpc::string GetHeader(const grpc::protobuf::ServiceDescriptor *service, - const grpc::string prefix); +string GetHeader(const ServiceDescriptor *service); // Returns the content to be included in the "global_scope" insertion point of // the generated implementation file. -grpc::string GetSource(const grpc::protobuf::ServiceDescriptor *service, - const grpc::string prefix); +string GetSource(const ServiceDescriptor *service); } // namespace grpc_objective_c_generator diff --git a/src/compiler/objective_c_generator_helpers.h b/src/compiler/objective_c_generator_helpers.h index d92a2b5e9af..1f8c80014f0 100644 --- a/src/compiler/objective_c_generator_helpers.h +++ b/src/compiler/objective_c_generator_helpers.h @@ -40,9 +40,19 @@ namespace grpc_objective_c_generator { -inline grpc::string MessageHeaderName(const grpc::protobuf::FileDescriptor *file) { +using ::grpc::protobuf::FileDescriptor; +using ::grpc::protobuf::ServiceDescriptor; +using ::grpc::string; + +inline string MessageHeaderName(const FileDescriptor *file) { return grpc_generator::FileNameInUpperCamel(file) + ".pbobjc.h"; } +inline string ServiceClassName(const ServiceDescriptor *service) { + const FileDescriptor *file = service->file(); + string prefix = file->options().objc_class_prefix(); + return prefix + service->name(); +} + } #endif // GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_HELPERS_H diff --git a/src/compiler/objective_c_plugin.cc b/src/compiler/objective_c_plugin.cc index 3cb170e95cf..b5ac2bafa99 100644 --- a/src/compiler/objective_c_plugin.cc +++ b/src/compiler/objective_c_plugin.cc @@ -77,7 +77,7 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { string declarations; for (int i = 0; i < file->service_count(); i++) { const grpc::protobuf::ServiceDescriptor *service = file->service(i); - declarations += grpc_objective_c_generator::GetHeader(service, prefix); + declarations += grpc_objective_c_generator::GetHeader(service); } Write(context, file_name + ".pbrpc.h", @@ -95,7 +95,7 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { string definitions; for (int i = 0; i < file->service_count(); i++) { const grpc::protobuf::ServiceDescriptor *service = file->service(i); - definitions += grpc_objective_c_generator::GetSource(service, prefix); + definitions += grpc_objective_c_generator::GetSource(service); } Write(context, file_name + ".pbrpc.m", imports + '\n' + definitions); From 9d48ebfdc3eae8f68dcf1f60490ca14f5ca49aee Mon Sep 17 00:00:00 2001 From: Alistair Veitch Date: Mon, 1 Jun 2015 10:01:03 -0700 Subject: [PATCH 29/52] address comments --- include/grpc/census.h | 5 +++-- src/core/surface/server.c | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/include/grpc/census.h b/include/grpc/census.h index 338d02ba1cf..a02724ed751 100644 --- a/include/grpc/census.h +++ b/include/grpc/census.h @@ -39,7 +39,6 @@ #define CENSUS_CENSUS_H #include -#include /* Identify census functionality that can be enabled via census_initialize(). */ enum census_functions { @@ -59,7 +58,9 @@ void census_shutdown(); /* Internally, Census relies on a context, which should be propagated across * RPC's. From the RPC subsystems viewpoint, this is an opaque data structure. * A context must be used as the first argument to all other census - * functions. The context can be serialized for passing across the wire. */ + * functions. Conceptually, contexts should be thought of as specific to + * single RPC/thread. The context can be serialized for passing across the + * wire. */ typedef struct census_context census_context; /* This function is called by the RPC subsystem whenever it needs to get a diff --git a/src/core/surface/server.c b/src/core/surface/server.c index b8ac4106872..735b8ac4b0e 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -620,7 +620,9 @@ grpc_server *grpc_server_create_from_filters(grpc_channel_filter **filters, size_t filter_count, const grpc_channel_args *args) { size_t i; - int census_enabled = grpc_channel_args_is_census_enabled(args); + /* TODO(census): restore this once we finalize census filter etc. + int census_enabled = grpc_channel_args_is_census_enabled(args); */ + int census_enabled = 0; grpc_server *server = gpr_malloc(sizeof(grpc_server)); @@ -646,7 +648,7 @@ grpc_server *grpc_server_create_from_filters(grpc_channel_filter **filters, server->channel_filters = gpr_malloc(server->channel_filter_count * sizeof(grpc_channel_filter *)); server->channel_filters[0] = &server_surface_filter; - /* TODO(census) + /* TODO(census): restore this once we rework census filter if (census_enabled) { server->channel_filters[1] = &grpc_server_census_filter; } */ From 269676209ead4602e0cb0bd02ebf378dcd5df7b3 Mon Sep 17 00:00:00 2001 From: Alistair Veitch Date: Mon, 1 Jun 2015 10:45:54 -0700 Subject: [PATCH 30/52] add init checks --- include/grpc/census.h | 4 +++- src/core/census/initialize.c | 16 ++++++++++++++-- src/core/surface/init.c | 4 +++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/include/grpc/census.h b/include/grpc/census.h index a02724ed751..9b89f9fce9d 100644 --- a/include/grpc/census.h +++ b/include/grpc/census.h @@ -51,7 +51,9 @@ enum census_functions { /* Shutdown and startup census subsystem. The 'functions' argument should be * the OR (|) of census_functions values. If census fails to initialize, then - * census_initialize() will return a non-zero value. */ + * census_initialize() will return a non-zero value. It is an error to call + * census_initialize() more than once (without an intervening + * census_shutdown()). */ int census_initialize(int functions); void census_shutdown(); diff --git a/src/core/census/initialize.c b/src/core/census/initialize.c index d72c08b91ca..057ac78ee72 100644 --- a/src/core/census/initialize.c +++ b/src/core/census/initialize.c @@ -33,6 +33,18 @@ #include -int census_initialize(int functions) { return 0; } +static int census_fns_enabled = CENSUS_NONE; -void census_shutdown() {} +int census_initialize(int functions) { + if (census_fns_enabled != CENSUS_NONE) { + return 1; + } + if (functions != CENSUS_NONE) { + return 1; + } else { + census_fns_enabled = functions; + return 0; + } +} + +void census_shutdown() { census_fns_enabled = CENSUS_NONE; } diff --git a/src/core/surface/init.c b/src/core/surface/init.c index 5cd5d9197f3..ac6871c6f22 100644 --- a/src/core/surface/init.c +++ b/src/core/surface/init.c @@ -64,7 +64,9 @@ void grpc_init(void) { grpc_security_pre_init(); grpc_iomgr_init(); grpc_tracer_init("GRPC_TRACE"); - census_initialize(CENSUS_NONE); + if (census_initialize(CENSUS_NONE)) { + gpr_log(GPR_ERROR, "Could not initialize census."); + } grpc_timers_global_init(); } gpr_mu_unlock(&g_init_mu); From 0fcb2f202fc65b60ae1416ed33664bc0cd4904ce Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 1 Jun 2015 10:46:43 -0700 Subject: [PATCH 31/52] fix buildall.bat script --- src/csharp/buildall.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/csharp/buildall.bat b/src/csharp/buildall.bat index 34ad9233074..68c61ef0396 100644 --- a/src/csharp/buildall.bat +++ b/src/csharp/buildall.bat @@ -5,7 +5,7 @@ setlocal @call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" x86 @rem Build the C# native extension -msbuild ..\..\vsprojects\grpc.sln /t:grpc_csharp_ext || goto :error +msbuild ..\..\vsprojects\grpc.sln /t:grpc_csharp_ext /p:PlatformToolset=v120 || goto :error msbuild Grpc.sln /p:Configuration=Debug || goto :error msbuild Grpc.sln /p:Configuration=Release || goto :error From 583b9a689ab2083839975b0b3cfa0790d978acd9 Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Mon, 1 Jun 2015 12:33:12 -0700 Subject: [PATCH 32/52] Addressed comments: fixed memory leak introduced by changes. --- tools/run_tests/jobset.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tools/run_tests/jobset.py b/tools/run_tests/jobset.py index 61a95b0d555..51d61db7f6c 100755 --- a/tools/run_tests/jobset.py +++ b/tools/run_tests/jobset.py @@ -66,6 +66,7 @@ def shuffle_iteratable(it): # p as we take elements - this gives us a somewhat random set of values before # we've seen all the values, but starts producing values without having to # compute ALL of them at once, allowing tests to start a little earlier + LARGE_THRESHOLD = 1000 nextit = [] p = 1 for val in it: @@ -74,6 +75,17 @@ def shuffle_iteratable(it): yield val else: nextit.append(val) + # if the input iterates over a large number of values (potentially + # infinite, we'd be in the loop for a while (again, potentially forever). + # We need to reset "nextit" every so often to, in the case of an infinite + # iterator, avoid growing "nextit" without ever freeing it. + if len(nextit) > LARGE_THRESHOLD: + random.shuffle(nextit) + for val in nextit: + yield val + nextit = [] + p = 1 + # after taking a random sampling, we shuffle the rest of the elements and # yield them random.shuffle(nextit) From 69ba87161604267e0b60fb49bef2602ddd3e56d5 Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Mon, 1 Jun 2015 11:29:42 -0700 Subject: [PATCH 33/52] Implemented cb handling without the need for "managed closures". The concept of managed closure is officially extinct. --- src/core/security/credentials.c | 35 ++++++++------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c index 648ac60eb62..9bf5c32e745 100644 --- a/src/core/security/credentials.c +++ b/src/core/security/credentials.c @@ -54,6 +54,7 @@ typedef struct { grpc_credentials *creds; grpc_credentials_metadata_cb cb; + grpc_iomgr_closure *on_simulated_token_fetch_done_closure; void *user_data; } grpc_credentials_metadata_request; @@ -65,6 +66,8 @@ grpc_credentials_metadata_request_create(grpc_credentials *creds, gpr_malloc(sizeof(grpc_credentials_metadata_request)); r->creds = grpc_credentials_ref(creds); r->cb = cb; + r->on_simulated_token_fetch_done_closure = + gpr_malloc(sizeof(grpc_iomgr_closure)); r->user_data = user_data; return r; } @@ -72,6 +75,7 @@ grpc_credentials_metadata_request_create(grpc_credentials *creds, static void grpc_credentials_metadata_request_destroy( grpc_credentials_metadata_request *r) { grpc_credentials_unref(r->creds); + gpr_free(r->on_simulated_token_fetch_done_closure); gpr_free(r); } @@ -824,20 +828,6 @@ void on_simulated_token_fetch_done(void *user_data, int success) { grpc_credentials_metadata_request_destroy(r); } -/* TODO(dgq): get rid of the concept of "managed closure" altogether */ -typedef struct { - grpc_iomgr_closure managed; - grpc_iomgr_closure *manager; -} managed_closure_arg; - -static void closure_manager_func(void *arg, int success) { - managed_closure_arg *mc_arg = (managed_closure_arg*) arg; - - mc_arg->managed.cb(mc_arg->managed.cb_arg, success); - gpr_free(mc_arg->manager); - gpr_free(mc_arg); -} - static void fake_oauth2_get_request_metadata(grpc_credentials *creds, const char *service_url, grpc_credentials_metadata_cb cb, @@ -845,20 +835,11 @@ static void fake_oauth2_get_request_metadata(grpc_credentials *creds, grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds; if (c->is_async) { - /* TODO(dgq): get rid of the managed closure */ - grpc_iomgr_closure *on_simulated_token_fetch_done_closure = - gpr_malloc(sizeof(grpc_iomgr_closure)); - managed_closure_arg *managed_arg = gpr_malloc(sizeof(managed_closure_arg)); - - managed_arg->manager = on_simulated_token_fetch_done_closure; - managed_arg->managed.cb = on_simulated_token_fetch_done; - managed_arg->managed.cb_arg = + grpc_credentials_metadata_request *cb_arg = grpc_credentials_metadata_request_create(creds, cb, user_data); - - grpc_iomgr_closure_init(on_simulated_token_fetch_done_closure, - closure_manager_func, managed_arg); - - grpc_iomgr_add_callback(on_simulated_token_fetch_done_closure); + grpc_iomgr_closure_init(cb_arg->on_simulated_token_fetch_done_closure, + on_simulated_token_fetch_done, cb_arg); + grpc_iomgr_add_callback(cb_arg->on_simulated_token_fetch_done_closure); } else { cb(user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK); } From fa275a97b968060383fe27c26b1d85f08d9582f9 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 1 Jun 2015 13:55:54 -0700 Subject: [PATCH 34/52] Label all iomgr objects This allows a list of them to be dumped to isolate where memory leaks are occuring. --- src/core/iomgr/endpoint_pair.h | 3 +- src/core/iomgr/endpoint_pair_posix.c | 17 ++++- src/core/iomgr/fd_posix.c | 7 +- src/core/iomgr/fd_posix.h | 6 +- src/core/iomgr/iomgr.c | 65 +++++++++++++------ src/core/iomgr/iomgr_internal.h | 10 ++- src/core/iomgr/resolve_address_posix.c | 9 ++- src/core/iomgr/tcp_client_posix.c | 22 +++++-- src/core/iomgr/tcp_server_posix.c | 23 +++++-- test/core/bad_client/bad_client.c | 2 +- .../end2end/fixtures/chttp2_socket_pair.c | 2 +- .../chttp2_socket_pair_one_byte_at_a_time.c | 2 +- .../chttp2_socket_pair_with_grpc_trace.c | 2 +- test/core/iomgr/fd_posix_test.c | 8 +-- test/core/iomgr/tcp_posix_test.c | 16 +++-- test/core/security/secure_endpoint_test.c | 2 +- 16 files changed, 136 insertions(+), 60 deletions(-) diff --git a/src/core/iomgr/endpoint_pair.h b/src/core/iomgr/endpoint_pair.h index dffbd36d4c6..25087be0c7e 100644 --- a/src/core/iomgr/endpoint_pair.h +++ b/src/core/iomgr/endpoint_pair.h @@ -41,6 +41,7 @@ typedef struct { grpc_endpoint *server; } grpc_endpoint_pair; -grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(size_t read_slice_size); +grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name, + size_t read_slice_size); #endif /* GRPC_INTERNAL_CORE_IOMGR_ENDPOINT_PAIR_H */ diff --git a/src/core/iomgr/endpoint_pair_posix.c b/src/core/iomgr/endpoint_pair_posix.c index ac511b97b26..9b3b63f1e7e 100644 --- a/src/core/iomgr/endpoint_pair_posix.c +++ b/src/core/iomgr/endpoint_pair_posix.c @@ -44,6 +44,8 @@ #include #include "src/core/iomgr/tcp_posix.h" +#include "src/core/support/string.h" +#include #include static void create_sockets(int sv[2]) { @@ -55,12 +57,21 @@ static void create_sockets(int sv[2]) { GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0); } -grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(size_t read_slice_size) { +grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name, + size_t read_slice_size) { int sv[2]; grpc_endpoint_pair p; + char *final_name; create_sockets(sv); - p.client = grpc_tcp_create(grpc_fd_create(sv[1]), read_slice_size); - p.server = grpc_tcp_create(grpc_fd_create(sv[0]), read_slice_size); + + gpr_asprintf(&final_name, "%s:client", name); + p.client = + grpc_tcp_create(grpc_fd_create(sv[1], final_name), read_slice_size); + gpr_free(final_name); + gpr_asprintf(&final_name, "%s:server", name); + p.server = + grpc_tcp_create(grpc_fd_create(sv[0], final_name), read_slice_size); + gpr_free(final_name); return p; } diff --git a/src/core/iomgr/fd_posix.c b/src/core/iomgr/fd_posix.c index b697fcc64a2..4ba06676ab5 100644 --- a/src/core/iomgr/fd_posix.c +++ b/src/core/iomgr/fd_posix.c @@ -41,7 +41,6 @@ #include #include -#include "src/core/iomgr/iomgr_internal.h" #include #include #include @@ -119,7 +118,7 @@ static void unref_by(grpc_fd *fd, int n) { close(fd->fd); grpc_iomgr_add_callback(fd->on_done, fd->on_done_user_data); freelist_fd(fd); - grpc_iomgr_unref(); + grpc_iomgr_unregister_object(&fd->iomgr_object); } else { GPR_ASSERT(old > n); } @@ -138,9 +137,9 @@ void grpc_fd_global_shutdown(void) { static void do_nothing(void *ignored, int success) {} -grpc_fd *grpc_fd_create(int fd) { +grpc_fd *grpc_fd_create(int fd, const char *name) { grpc_fd *r = alloc_fd(fd); - grpc_iomgr_ref(); + grpc_iomgr_register_object(&r->iomgr_object, name); grpc_pollset_add_fd(grpc_backup_pollset(), r); return r; } diff --git a/src/core/iomgr/fd_posix.h b/src/core/iomgr/fd_posix.h index cfc533b7f56..a15ed7c90de 100644 --- a/src/core/iomgr/fd_posix.h +++ b/src/core/iomgr/fd_posix.h @@ -34,7 +34,7 @@ #ifndef GRPC_INTERNAL_CORE_IOMGR_FD_POSIX_H #define GRPC_INTERNAL_CORE_IOMGR_FD_POSIX_H -#include "src/core/iomgr/iomgr.h" +#include "src/core/iomgr/iomgr_internal.h" #include "src/core/iomgr/pollset.h" #include #include @@ -99,12 +99,14 @@ struct grpc_fd { grpc_iomgr_cb_func on_done; void *on_done_user_data; struct grpc_fd *freelist_next; + + grpc_iomgr_object iomgr_object; }; /* Create a wrapped file descriptor. Requires fd is a non-blocking file descriptor. This takes ownership of closing fd. */ -grpc_fd *grpc_fd_create(int fd); +grpc_fd *grpc_fd_create(int fd, const char *name); /* Releases fd to be asynchronously destroyed. on_done is called when the underlying file descriptor is definitely close()d. diff --git a/src/core/iomgr/iomgr.c b/src/core/iomgr/iomgr.c index d22542fc91d..1377b6dc9e3 100644 --- a/src/core/iomgr/iomgr.c +++ b/src/core/iomgr/iomgr.c @@ -37,6 +37,7 @@ #include "src/core/iomgr/iomgr_internal.h" #include "src/core/iomgr/alarm_internal.h" +#include "src/core/support/string.h" #include #include #include @@ -54,8 +55,8 @@ static gpr_cv g_rcv; static delayed_callback *g_cbs_head = NULL; static delayed_callback *g_cbs_tail = NULL; static int g_shutdown; -static int g_refs; static gpr_event g_background_callback_executor_done; +static grpc_iomgr_object g_root_object; /* Execute followup callbacks continuously. Other threads may check in and help during pollset_work() */ @@ -96,34 +97,49 @@ void grpc_iomgr_init(void) { gpr_mu_init(&g_mu); gpr_cv_init(&g_rcv); grpc_alarm_list_init(gpr_now()); - g_refs = 0; + g_root_object.next = g_root_object.prev = &g_root_object; + g_root_object.name = "root"; grpc_iomgr_platform_init(); gpr_event_init(&g_background_callback_executor_done); gpr_thd_new(&id, background_callback_executor, NULL, NULL); } +static size_t count_objects(void) { + grpc_iomgr_object *obj; + size_t n = 0; + for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) { + n++; + } + return n; +} + void grpc_iomgr_shutdown(void) { delayed_callback *cb; + grpc_iomgr_object *obj; gpr_timespec shutdown_deadline = gpr_time_add(gpr_now(), gpr_time_from_seconds(10)); gpr_mu_lock(&g_mu); g_shutdown = 1; - while (g_cbs_head || g_refs) { - gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed%s", g_refs, + while (g_cbs_head || g_root_object.next != &g_root_object) { + size_t nobjs = count_objects(); + gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed%s", nobjs, g_cbs_head ? " and executing final callbacks" : ""); - while (g_cbs_head) { - cb = g_cbs_head; - g_cbs_head = cb->next; - if (!g_cbs_head) g_cbs_tail = NULL; - gpr_mu_unlock(&g_mu); - - cb->cb(cb->cb_arg, 0); - gpr_free(cb); - gpr_mu_lock(&g_mu); + if (g_cbs_head) { + do { + cb = g_cbs_head; + g_cbs_head = cb->next; + if (!g_cbs_head) g_cbs_tail = NULL; + gpr_mu_unlock(&g_mu); + + cb->cb(cb->cb_arg, 0); + gpr_free(cb); + gpr_mu_lock(&g_mu); + } while (g_cbs_head); + continue; } - if (g_refs) { + if (nobjs > 0) { int timeout = 0; gpr_timespec short_deadline = gpr_time_add(gpr_now(), gpr_time_from_millis(100)); @@ -137,7 +153,10 @@ void grpc_iomgr_shutdown(void) { gpr_log(GPR_DEBUG, "Failed to free %d iomgr objects before shutdown deadline: " "memory leaks are likely", - g_refs); + count_objects()); + for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) { + gpr_log(GPR_DEBUG, "LEAKED OBJECT: %s", obj->name); + } break; } } @@ -153,17 +172,21 @@ void grpc_iomgr_shutdown(void) { gpr_cv_destroy(&g_rcv); } -void grpc_iomgr_ref(void) { +void grpc_iomgr_register_object(grpc_iomgr_object *obj, const char *name) { + obj->name = gpr_strdup(name); gpr_mu_lock(&g_mu); - ++g_refs; + obj->next = &g_root_object; + obj->prev = obj->next->prev; + obj->next->prev = obj->prev->next = obj; gpr_mu_unlock(&g_mu); } -void grpc_iomgr_unref(void) { +void grpc_iomgr_unregister_object(grpc_iomgr_object *obj) { + gpr_free(obj->name); gpr_mu_lock(&g_mu); - if (0 == --g_refs) { - gpr_cv_signal(&g_rcv); - } + obj->next->prev = obj->prev; + obj->prev->next = obj->next; + gpr_cv_signal(&g_rcv); gpr_mu_unlock(&g_mu); } diff --git a/src/core/iomgr/iomgr_internal.h b/src/core/iomgr/iomgr_internal.h index 07923258b9b..54eadf1edc1 100644 --- a/src/core/iomgr/iomgr_internal.h +++ b/src/core/iomgr/iomgr_internal.h @@ -38,12 +38,18 @@ #include "src/core/iomgr/iomgr_internal.h" #include +typedef struct grpc_iomgr_object { + char *name; + struct grpc_iomgr_object *next; + struct grpc_iomgr_object *prev; +} grpc_iomgr_object; + int grpc_maybe_call_delayed_callbacks(gpr_mu *drop_mu, int success); void grpc_iomgr_add_delayed_callback(grpc_iomgr_cb_func cb, void *cb_arg, int success); -void grpc_iomgr_ref(void); -void grpc_iomgr_unref(void); +void grpc_iomgr_register_object(grpc_iomgr_object *obj, const char *name); +void grpc_iomgr_unregister_object(grpc_iomgr_object *obj); void grpc_iomgr_platform_init(void); void grpc_iomgr_platform_shutdown(void); diff --git a/src/core/iomgr/resolve_address_posix.c b/src/core/iomgr/resolve_address_posix.c index 9a9283c93c3..fcf48fe0d7b 100644 --- a/src/core/iomgr/resolve_address_posix.c +++ b/src/core/iomgr/resolve_address_posix.c @@ -55,6 +55,7 @@ typedef struct { char *default_port; grpc_resolve_cb cb; void *arg; + grpc_iomgr_object iomgr_object; } request; grpc_resolved_addresses *grpc_blocking_resolve_address( @@ -153,9 +154,9 @@ static void do_request(void *rp) { grpc_resolve_cb cb = r->cb; gpr_free(r->name); gpr_free(r->default_port); + grpc_iomgr_unregister_object(&r->iomgr_object); gpr_free(r); cb(arg, resolved); - grpc_iomgr_unref(); } void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) { @@ -167,7 +168,11 @@ void grpc_resolve_address(const char *name, const char *default_port, grpc_resolve_cb cb, void *arg) { request *r = gpr_malloc(sizeof(request)); gpr_thd_id id; - grpc_iomgr_ref(); + char *tmp; + gpr_asprintf(&tmp, "resolve_address:name='%s':default_port='%s'", name, + default_port); + grpc_iomgr_register_object(&r->iomgr_object, tmp); + gpr_free(tmp); r->name = gpr_strdup(name); r->default_port = gpr_strdup(default_port); r->cb = cb; diff --git a/src/core/iomgr/tcp_client_posix.c b/src/core/iomgr/tcp_client_posix.c index 2401fe00e45..aa21ba9b9ef 100644 --- a/src/core/iomgr/tcp_client_posix.c +++ b/src/core/iomgr/tcp_client_posix.c @@ -48,6 +48,7 @@ #include "src/core/iomgr/sockaddr_utils.h" #include "src/core/iomgr/socket_utils_posix.h" #include "src/core/iomgr/tcp_posix.h" +#include "src/core/support/string.h" #include #include #include @@ -185,6 +186,8 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep), async_connect *ac; struct sockaddr_in6 addr6_v4mapped; struct sockaddr_in addr4_copy; + char *name; + char *addr_str; /* Use dualstack sockets where available. */ if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { @@ -211,24 +214,27 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep), err = connect(fd, addr, addr_len); } while (err < 0 && errno == EINTR); + grpc_sockaddr_to_string(&addr_str, addr, 1); + gpr_asprintf(&name, "tcp-client:%s", addr_str); + if (err >= 0) { gpr_log(GPR_DEBUG, "instant connect"); - cb(arg, - grpc_tcp_create(grpc_fd_create(fd), GRPC_TCP_DEFAULT_READ_SLICE_SIZE)); - return; + cb(arg, grpc_tcp_create(grpc_fd_create(fd, name), + GRPC_TCP_DEFAULT_READ_SLICE_SIZE)); + goto done; } if (errno != EWOULDBLOCK && errno != EINPROGRESS) { - gpr_log(GPR_ERROR, "connect error: %s", strerror(errno)); + gpr_log(GPR_ERROR, "connect error to '%s': %s", addr_str, strerror(errno)); close(fd); cb(arg, NULL); - return; + goto done; } ac = gpr_malloc(sizeof(async_connect)); ac->cb = cb; ac->cb_arg = arg; - ac->fd = grpc_fd_create(fd); + ac->fd = grpc_fd_create(fd, name); gpr_mu_init(&ac->mu); ac->refs = 2; ac->write_closure.cb = on_writable; @@ -236,6 +242,10 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep), grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, gpr_now()); grpc_fd_notify_on_write(ac->fd, &ac->write_closure); + +done: + gpr_free(name); + gpr_free(addr_str); } #endif diff --git a/src/core/iomgr/tcp_server_posix.c b/src/core/iomgr/tcp_server_posix.c index d1cd8a769cd..3cd40faafc6 100644 --- a/src/core/iomgr/tcp_server_posix.c +++ b/src/core/iomgr/tcp_server_posix.c @@ -60,6 +60,7 @@ #include "src/core/iomgr/sockaddr_utils.h" #include "src/core/iomgr/socket_utils_posix.h" #include "src/core/iomgr/tcp_posix.h" +#include "src/core/support/string.h" #include #include #include @@ -281,6 +282,8 @@ static void on_read(void *arg, int success) { for (;;) { struct sockaddr_storage addr; socklen_t addrlen = sizeof(addr); + char *addr_str; + char *name; /* Note: If we ever decide to return this address to the user, remember to strip off the ::ffff:0.0.0.0/96 prefix first. */ int fd = grpc_accept4(sp->fd, (struct sockaddr *)&addr, &addrlen, 1, 1); @@ -299,9 +302,15 @@ static void on_read(void *arg, int success) { grpc_set_socket_no_sigpipe_if_possible(fd); - sp->server->cb( - sp->server->cb_arg, - grpc_tcp_create(grpc_fd_create(fd), GRPC_TCP_DEFAULT_READ_SLICE_SIZE)); + grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1); + gpr_asprintf(&name, "tcp-server-connection:%s", addr_str); + + sp->server->cb(sp->server->cb_arg, + grpc_tcp_create(grpc_fd_create(fd, name), + GRPC_TCP_DEFAULT_READ_SLICE_SIZE)); + + gpr_free(addr_str); + gpr_free(name); } abort(); @@ -318,9 +327,13 @@ static int add_socket_to_server(grpc_tcp_server *s, int fd, const struct sockaddr *addr, int addr_len) { server_port *sp; int port; + char *addr_str; + char *name; port = prepare_socket(fd, addr, addr_len); if (port >= 0) { + grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1); + gpr_asprintf(&name, "tcp-server-listener:%s", addr_str); gpr_mu_lock(&s->mu); GPR_ASSERT(!s->cb && "must add ports before starting server"); /* append it to the list under a lock */ @@ -331,11 +344,13 @@ static int add_socket_to_server(grpc_tcp_server *s, int fd, sp = &s->ports[s->nports++]; sp->server = s; sp->fd = fd; - sp->emfd = grpc_fd_create(fd); + sp->emfd = grpc_fd_create(fd, name); memcpy(sp->addr.untyped, addr, addr_len); sp->addr_len = addr_len; GPR_ASSERT(sp->emfd); gpr_mu_unlock(&s->mu); + gpr_free(addr_str); + gpr_free(name); } return port; diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c index 9d1c4ce2d71..4cc1ad43127 100644 --- a/test/core/bad_client/bad_client.c +++ b/test/core/bad_client/bad_client.c @@ -88,7 +88,7 @@ void grpc_run_bad_client_test(const char *name, const char *client_payload, grpc_init(); /* Create endpoints */ - sfd = grpc_iomgr_create_endpoint_pair(65536); + sfd = grpc_iomgr_create_endpoint_pair("fixture", 65536); /* Create server, completion events */ a.server = grpc_server_create_from_filters(NULL, 0, NULL); diff --git a/test/core/end2end/fixtures/chttp2_socket_pair.c b/test/core/end2end/fixtures/chttp2_socket_pair.c index e0221d0452a..48c121c7c4c 100644 --- a/test/core/end2end/fixtures/chttp2_socket_pair.c +++ b/test/core/end2end/fixtures/chttp2_socket_pair.c @@ -98,7 +98,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_socketpair( f.client_cq = grpc_completion_queue_create(); f.server_cq = grpc_completion_queue_create(); - *sfd = grpc_iomgr_create_endpoint_pair(65536); + *sfd = grpc_iomgr_create_endpoint_pair("fixture", 65536); return f; } diff --git a/test/core/end2end/fixtures/chttp2_socket_pair_one_byte_at_a_time.c b/test/core/end2end/fixtures/chttp2_socket_pair_one_byte_at_a_time.c index 37b5529d7f5..1d2e6f51c1d 100644 --- a/test/core/end2end/fixtures/chttp2_socket_pair_one_byte_at_a_time.c +++ b/test/core/end2end/fixtures/chttp2_socket_pair_one_byte_at_a_time.c @@ -98,7 +98,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_socketpair( f.client_cq = grpc_completion_queue_create(); f.server_cq = grpc_completion_queue_create(); - *sfd = grpc_iomgr_create_endpoint_pair(1); + *sfd = grpc_iomgr_create_endpoint_pair("fixture", 1); return f; } diff --git a/test/core/end2end/fixtures/chttp2_socket_pair_with_grpc_trace.c b/test/core/end2end/fixtures/chttp2_socket_pair_with_grpc_trace.c index b15a18f1a73..d32dbec25e7 100644 --- a/test/core/end2end/fixtures/chttp2_socket_pair_with_grpc_trace.c +++ b/test/core/end2end/fixtures/chttp2_socket_pair_with_grpc_trace.c @@ -99,7 +99,7 @@ static grpc_end2end_test_fixture chttp2_create_fixture_socketpair( f.client_cq = grpc_completion_queue_create(); f.server_cq = grpc_completion_queue_create(); - *sfd = grpc_iomgr_create_endpoint_pair(65536); + *sfd = grpc_iomgr_create_endpoint_pair("fixture", 65536); return f; } diff --git a/test/core/iomgr/fd_posix_test.c b/test/core/iomgr/fd_posix_test.c index 57e2c6fc177..2c8a89e4cdd 100644 --- a/test/core/iomgr/fd_posix_test.c +++ b/test/core/iomgr/fd_posix_test.c @@ -208,7 +208,7 @@ static void listen_cb(void *arg, /*=sv_arg*/ fcntl(fd, F_SETFL, flags | O_NONBLOCK); se = gpr_malloc(sizeof(*se)); se->sv = sv; - se->em_fd = grpc_fd_create(fd); + se->em_fd = grpc_fd_create(fd, "listener"); se->session_read_closure.cb = session_read_cb; se->session_read_closure.cb_arg = se; grpc_fd_notify_on_read(se->em_fd, &se->session_read_closure); @@ -236,7 +236,7 @@ static int server_start(server *sv) { port = ntohs(sin.sin_port); GPR_ASSERT(listen(fd, MAX_NUM_FD) == 0); - sv->em_fd = grpc_fd_create(fd); + sv->em_fd = grpc_fd_create(fd, "server"); /* Register to be interested in reading from listen_fd. */ sv->listen_closure.cb = listen_cb; sv->listen_closure.cb_arg = sv; @@ -351,7 +351,7 @@ static void client_start(client *cl, int port) { } } - cl->em_fd = grpc_fd_create(fd); + cl->em_fd = grpc_fd_create(fd, "client"); client_session_write(cl, 1); } @@ -447,7 +447,7 @@ static void test_grpc_fd_change(void) { flags = fcntl(sv[1], F_GETFL, 0); GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0); - em_fd = grpc_fd_create(sv[0]); + em_fd = grpc_fd_create(sv[0], "test_grpc_fd_change"); /* Register the first callback, then make its FD readable */ grpc_fd_notify_on_read(em_fd, &first_closure); diff --git a/test/core/iomgr/tcp_posix_test.c b/test/core/iomgr/tcp_posix_test.c index 40abed5f6e1..2cfcc8311cb 100644 --- a/test/core/iomgr/tcp_posix_test.c +++ b/test/core/iomgr/tcp_posix_test.c @@ -172,7 +172,7 @@ static void read_test(ssize_t num_bytes, ssize_t slice_size) { create_sockets(sv); - ep = grpc_tcp_create(grpc_fd_create(sv[1]), slice_size); + ep = grpc_tcp_create(grpc_fd_create(sv[1], "read_test"), slice_size); written_bytes = fill_socket_partial(sv[0], num_bytes); gpr_log(GPR_INFO, "Wrote %d bytes", written_bytes); @@ -213,7 +213,7 @@ static void large_read_test(ssize_t slice_size) { create_sockets(sv); - ep = grpc_tcp_create(grpc_fd_create(sv[1]), slice_size); + ep = grpc_tcp_create(grpc_fd_create(sv[1], "large_read_test"), slice_size); written_bytes = fill_socket(sv[0]); gpr_log(GPR_INFO, "Wrote %d bytes", written_bytes); @@ -350,7 +350,8 @@ static void write_test(ssize_t num_bytes, ssize_t slice_size) { create_sockets(sv); - ep = grpc_tcp_create(grpc_fd_create(sv[1]), GRPC_TCP_DEFAULT_READ_SLICE_SIZE); + ep = grpc_tcp_create(grpc_fd_create(sv[1], "write_test"), + GRPC_TCP_DEFAULT_READ_SLICE_SIZE); gpr_mu_init(&state.mu); gpr_cv_init(&state.cv); @@ -406,7 +407,8 @@ static void write_error_test(ssize_t num_bytes, ssize_t slice_size) { create_sockets(sv); - ep = grpc_tcp_create(grpc_fd_create(sv[1]), GRPC_TCP_DEFAULT_READ_SLICE_SIZE); + ep = grpc_tcp_create(grpc_fd_create(sv[1], "write_error_test"), + GRPC_TCP_DEFAULT_READ_SLICE_SIZE); close(sv[0]); gpr_mu_init(&state.mu); @@ -473,8 +475,10 @@ static grpc_endpoint_test_fixture create_fixture_tcp_socketpair( grpc_endpoint_test_fixture f; create_sockets(sv); - f.client_ep = grpc_tcp_create(grpc_fd_create(sv[0]), slice_size); - f.server_ep = grpc_tcp_create(grpc_fd_create(sv[1]), slice_size); + f.client_ep = + grpc_tcp_create(grpc_fd_create(sv[0], "fixture:client"), slice_size); + f.server_ep = + grpc_tcp_create(grpc_fd_create(sv[1], "fixture:server"), slice_size); return f; } diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c index 6477454e8ab..30b23624d89 100644 --- a/test/core/security/secure_endpoint_test.c +++ b/test/core/security/secure_endpoint_test.c @@ -51,7 +51,7 @@ static grpc_endpoint_test_fixture secure_endpoint_create_fixture_tcp_socketpair( grpc_endpoint_test_fixture f; grpc_endpoint_pair tcp; - tcp = grpc_iomgr_create_endpoint_pair(slice_size); + tcp = grpc_iomgr_create_endpoint_pair("fixture", slice_size); if (leftover_nslices == 0) { f.client_ep = From 69fe0759bee3579d743d2e71f36504366ee0d275 Mon Sep 17 00:00:00 2001 From: Yang Gao Date: Mon, 1 Jun 2015 14:32:38 -0700 Subject: [PATCH 35/52] Various minor fixes --- include/grpc++/impl/sync_no_cxx11.h | 6 +++--- include/grpc++/impl/thd_no_cxx11.h | 4 ++++ src/cpp/server/thread_pool.cc | 5 +++-- src/cpp/server/thread_pool.h | 2 +- test/core/support/tls_test.c | 1 + test/cpp/end2end/end2end_test.cc | 1 + test/cpp/end2end/thread_stress_test.cc | 1 + 7 files changed, 14 insertions(+), 6 deletions(-) diff --git a/include/grpc++/impl/sync_no_cxx11.h b/include/grpc++/impl/sync_no_cxx11.h index 5636373b814..dda939bf715 100644 --- a/include/grpc++/impl/sync_no_cxx11.h +++ b/include/grpc++/impl/sync_no_cxx11.h @@ -76,9 +76,9 @@ class lock_guard { template class unique_lock : public lock_guard { public: - unique_lock(mutex &mu) : lock_guard(mu) { } - void lock() { lock_internal(); } - void unlock() { unlock_internal(); } + unique_lock(mutex &mu) : lock_guard(mu) { } + void lock() { this->lock_internal(); } + void unlock() { this->unlock_internal(); } }; class condition_variable { diff --git a/include/grpc++/impl/thd_no_cxx11.h b/include/grpc++/impl/thd_no_cxx11.h index a01b931df86..a6bdd7dfe9e 100644 --- a/include/grpc++/impl/thd_no_cxx11.h +++ b/include/grpc++/impl/thd_no_cxx11.h @@ -82,6 +82,10 @@ class thread { thread_function_base *func_; gpr_thd_id thd_; bool joined_; + + // Disallow copy and assign. + thread(const thread&); + void operator=(const thread&); }; } // namespace grpc diff --git a/src/cpp/server/thread_pool.cc b/src/cpp/server/thread_pool.cc index e8d0e89ed21..118cabcb612 100644 --- a/src/cpp/server/thread_pool.cc +++ b/src/cpp/server/thread_pool.cc @@ -60,7 +60,7 @@ void ThreadPool::ThreadFunc() { ThreadPool::ThreadPool(int num_threads) : shutdown_(false) { for (int i = 0; i < num_threads; i++) { - threads_.push_back(grpc::thread(&ThreadPool::ThreadFunc, this)); + threads_.push_back(new grpc::thread(&ThreadPool::ThreadFunc, this)); } } @@ -71,7 +71,8 @@ ThreadPool::~ThreadPool() { cv_.notify_all(); } for (auto t = threads_.begin(); t != threads_.end(); t++) { - t->join(); + (*t)->join(); + delete *t; } } diff --git a/src/cpp/server/thread_pool.h b/src/cpp/server/thread_pool.h index 0f24d6e9b32..26f25611b5e 100644 --- a/src/cpp/server/thread_pool.h +++ b/src/cpp/server/thread_pool.h @@ -57,7 +57,7 @@ class ThreadPool GRPC_FINAL : public ThreadPoolInterface { grpc::condition_variable cv_; bool shutdown_; std::queue> callbacks_; - std::vector threads_; + std::vector threads_; void ThreadFunc(); }; diff --git a/test/core/support/tls_test.c b/test/core/support/tls_test.c index 8632fd44901..0a3c28417f6 100644 --- a/test/core/support/tls_test.c +++ b/test/core/support/tls_test.c @@ -54,6 +54,7 @@ static void thd_body(void *arg) { gpr_tls_set(&test_var, i); GPR_ASSERT(gpr_tls_get(&test_var) == i); } + gpr_tls_set(&test_var, 0); } /* ------------------------------------------------- */ diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 7a15591b44b..f48cf953a4f 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -31,6 +31,7 @@ * */ +#include #include #include "src/core/security/credentials.h" diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc index 310227a29c8..5ee29e40f43 100644 --- a/test/cpp/end2end/thread_stress_test.cc +++ b/test/cpp/end2end/thread_stress_test.cc @@ -31,6 +31,7 @@ * */ +#include #include #include "test/core/util/port.h" From 980ef7666da1fb40ea6430b6bfef383b7d8528ac Mon Sep 17 00:00:00 2001 From: Alistair Veitch Date: Mon, 1 Jun 2015 14:35:31 -0700 Subject: [PATCH 36/52] change census_context_deserialize signature --- include/grpc/census.h | 7 ++++--- src/core/census/context.c | 12 ++++++------ src/core/census/grpc_context.c | 6 +++++- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/include/grpc/census.h b/include/grpc/census.h index 9b89f9fce9d..5f08c10032f 100644 --- a/include/grpc/census.h +++ b/include/grpc/census.h @@ -82,10 +82,11 @@ size_t census_context_serialize(const census_context *context, char *buffer, /* Create a new census context, possibly from a serialized buffer. If 'buffer' * is non-NULL, it is assumed that it is a buffer encoded by * census_context_serialize(). If `buffer` is NULL, a new, empty context is - * created. + * created. The decoded/new contest is returned in 'context'. * - * Returns NULL on error (buffer is incorrectly formatted) */ -census_context *census_context_deserialize(char *buffer); + * Returns 0 if no errors, non-zero if buffer is incorrectly formatted, in + * which case a new empty context will be returned. */ +int census_context_deserialize(const char *buffer, census_context **context); /* The given context is destroyed. Once destroyed, using the context in * future census calls will result in undefined behavior. */ diff --git a/src/core/census/context.c b/src/core/census/context.c index a940e96ec0c..1358c5127b7 100644 --- a/src/core/census/context.c +++ b/src/core/census/context.c @@ -45,14 +45,14 @@ size_t census_context_serialize(const census_context *context, char *buffer, return 0; } -census_context *census_context_deserialize(char *buffer) { - census_context *ret; +int census_context_deserialize(const char *buffer, census_context **context) { + int ret = 0; if (buffer != NULL) { - /* TODO(aveitch): implement deserialization */ - return NULL; + /* TODO(aveitch): implement deserialization. */ + ret = 1; } - ret = gpr_malloc(sizeof(census_context)); - memset(ret, 0, sizeof(census_context)); + *context = gpr_malloc(sizeof(census_context)); + memset(*context, 0, sizeof(census_context)); return ret; } diff --git a/src/core/census/grpc_context.c b/src/core/census/grpc_context.c index 4b1ba49e707..cf2353199f3 100644 --- a/src/core/census/grpc_context.c +++ b/src/core/census/grpc_context.c @@ -34,7 +34,11 @@ #include #include "src/core/census/grpc_context.h" -void *grpc_census_context_create() { return census_context_deserialize(NULL); } +void *grpc_census_context_create() { + census_context *context; + census_context_deserialize(NULL, &context); + return (void *)context; +} void grpc_census_context_destroy(void *context) { census_context_destroy((census_context *)context); From 555c16a3e77c4c195b505c4699e70e8f857369fc Mon Sep 17 00:00:00 2001 From: Donna Dionne Date: Mon, 1 Jun 2015 15:21:33 -0700 Subject: [PATCH 37/52] Adding csharp_dotnet into cloud suite of tests Currently the build is manual but will be automated over time --- tools/gce_setup/cloud_prod_runner.sh | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tools/gce_setup/cloud_prod_runner.sh b/tools/gce_setup/cloud_prod_runner.sh index 576c2b24d19..4206a66db78 100755 --- a/tools/gce_setup/cloud_prod_runner.sh +++ b/tools/gce_setup/cloud_prod_runner.sh @@ -36,13 +36,18 @@ main() { source grpc_docker.sh test_cases=(large_unary empty_unary ping_pong client_streaming server_streaming cancel_after_begin cancel_after_first_response) auth_test_cases=(service_account_creds compute_engine_creds jwt_token_creds) - clients=(cxx java go ruby node csharp_mono python php) + clients=(cxx java go ruby node csharp_mono csharp_dotnet python php) for test_case in "${test_cases[@]}" do for client in "${clients[@]}" do + client_vm="grpc-docker-testclients" + if [ "$client" = "csharp_dotnet" ] + then + client_vm="grpc-windows-interop1" + fi log_file_name=cloud_{$test_case}_{$client}.txt - if grpc_cloud_prod_test $test_case grpc-docker-testclients $client > /tmp/$log_file_name 2>&1 + if grpc_cloud_prod_test $test_case $client_vm $client > /tmp/$log_file_name 2>&1 then echo " ['$test_case', '$client', 'prod', true, 'log']," >> /tmp/cloud_prod_result.txt else @@ -56,8 +61,13 @@ main() { do for client in "${clients[@]}" do + client_vm="grpc-docker-testclients" + if [ "$client" = "csharp_dotnet" ] + then + client_vm="grpc-windows-interop1" + fi log_file_name=cloud_{$test_case}_{$client}.txt - if grpc_cloud_prod_auth_test $test_case grpc-docker-testclients $client > /tmp/$log_file_name 2>&1 + if grpc_cloud_prod_auth_test $test_case $client_vm $client > /tmp/$log_file_name 2>&1 then echo " ['$test_case', '$client', 'prod', true, 'log']," >> /tmp/cloud_prod_result.txt else From b00aa67b3cced0da0b52089bfdea8d455be99900 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 1 Jun 2015 15:48:03 -0700 Subject: [PATCH 38/52] run_tests.py support for C# on windows --- src/csharp/.nuget/packages.config | 4 ++ src/csharp/Grpc.sln | 62 ++++++++++++++++++------------- src/csharp/buildall.bat | 4 ++ tools/run_tests/run_csharp.bat | 16 ++++++++ tools/run_tests/run_tests.py | 20 +++++++++- 5 files changed, 78 insertions(+), 28 deletions(-) create mode 100644 src/csharp/.nuget/packages.config create mode 100644 tools/run_tests/run_csharp.bat diff --git a/src/csharp/.nuget/packages.config b/src/csharp/.nuget/packages.config new file mode 100644 index 00000000000..a7df95cf6bd --- /dev/null +++ b/src/csharp/.nuget/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/csharp/Grpc.sln b/src/csharp/Grpc.sln index e2a374e362a..978739f23aa 100644 --- a/src/csharp/Grpc.sln +++ b/src/csharp/Grpc.sln @@ -1,6 +1,8 @@  -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Examples", "Grpc.Examples\Grpc.Examples.csproj", "{7DC1433E-3225-42C7-B7EA-546D56E27A4B}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Core", "Grpc.Core\Grpc.Core.csproj", "{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}" @@ -21,52 +23,60 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Examples.MathServer", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Auth", "Grpc.Auth\Grpc.Auth.csproj", "{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{B5B87121-35FE-49D1-8CB1-8A91AAA398A9}" + ProjectSection(SolutionItems) = preProject + .nuget\packages.config = .nuget\packages.config + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x86 = Debug|x86 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|x86.ActiveCfg = Debug|Any CPU - {143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|x86.Build.0 = Debug|Any CPU - {143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|x86.ActiveCfg = Release|Any CPU - {143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|x86.Build.0 = Release|Any CPU - {3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|x86.ActiveCfg = Debug|x86 - {3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|x86.Build.0 = Debug|x86 - {3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|x86.ActiveCfg = Release|x86 - {3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|x86.Build.0 = Release|x86 - {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|x86.ActiveCfg = Debug|x86 - {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|x86.Build.0 = Debug|x86 - {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|x86.ActiveCfg = Release|x86 - {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|x86.Build.0 = Release|x86 {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|x86.ActiveCfg = Debug|Any CPU {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|x86.Build.0 = Debug|Any CPU {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|x86.ActiveCfg = Release|Any CPU {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|x86.Build.0 = Release|Any CPU + {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|x86.ActiveCfg = Debug|Any CPU + {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|x86.Build.0 = Debug|Any CPU + {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|x86.ActiveCfg = Release|Any CPU + {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|x86.Build.0 = Release|Any CPU {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|x86.ActiveCfg = Debug|Any CPU {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|x86.Build.0 = Debug|Any CPU {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|x86.ActiveCfg = Release|Any CPU {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|x86.Build.0 = Release|Any CPU + {143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|x86.ActiveCfg = Debug|Any CPU + {143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|x86.Build.0 = Debug|Any CPU + {143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|x86.ActiveCfg = Release|Any CPU + {143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|x86.Build.0 = Release|Any CPU + {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|x86.ActiveCfg = Debug|x86 + {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|x86.Build.0 = Debug|x86 + {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|x86.ActiveCfg = Release|x86 + {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|x86.Build.0 = Release|x86 + {C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|x86.ActiveCfg = Debug|x86 + {C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|x86.Build.0 = Debug|x86 + {C61154BA-DD4A-4838-8420-0162A28925E0}.Release|x86.ActiveCfg = Release|x86 + {C61154BA-DD4A-4838-8420-0162A28925E0}.Release|x86.Build.0 = Release|x86 + {3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|x86.ActiveCfg = Debug|x86 + {3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|x86.Build.0 = Debug|x86 + {3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|x86.ActiveCfg = Release|x86 + {3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|x86.Build.0 = Release|x86 {A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|x86.ActiveCfg = Debug|x86 {A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|x86.Build.0 = Debug|x86 {A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|x86.ActiveCfg = Release|x86 {A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|x86.Build.0 = Release|x86 - {AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|x86.ActiveCfg = Debug|Any CPU - {AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|x86.Build.0 = Debug|Any CPU - {AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|x86.ActiveCfg = Release|Any CPU - {AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|x86.Build.0 = Release|Any CPU {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|x86.ActiveCfg = Debug|x86 {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|x86.Build.0 = Debug|x86 {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|x86.ActiveCfg = Release|x86 {BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|x86.Build.0 = Release|x86 - {C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|x86.ActiveCfg = Debug|x86 - {C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|x86.Build.0 = Debug|x86 - {C61154BA-DD4A-4838-8420-0162A28925E0}.Release|x86.ActiveCfg = Release|x86 - {C61154BA-DD4A-4838-8420-0162A28925E0}.Release|x86.Build.0 = Release|x86 - {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|x86.ActiveCfg = Debug|Any CPU - {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|x86.Build.0 = Debug|Any CPU - {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|x86.ActiveCfg = Release|Any CPU - {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|x86.Build.0 = Release|Any CPU + {AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|x86.ActiveCfg = Debug|Any CPU + {AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|x86.Build.0 = Debug|Any CPU + {AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|x86.ActiveCfg = Release|Any CPU + {AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution StartupItem = Grpc.Examples\Grpc.Examples.csproj diff --git a/src/csharp/buildall.bat b/src/csharp/buildall.bat index 68c61ef0396..16860aec3c3 100644 --- a/src/csharp/buildall.bat +++ b/src/csharp/buildall.bat @@ -1,6 +1,10 @@ @rem Convenience script to build gRPC C# from command line setlocal + +@rem enter this directory +cd /d %~dp0 + @rem Set VS variables (uses Visual Studio 2013) @call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" x86 diff --git a/tools/run_tests/run_csharp.bat b/tools/run_tests/run_csharp.bat new file mode 100644 index 00000000000..17c622cc2df --- /dev/null +++ b/tools/run_tests/run_csharp.bat @@ -0,0 +1,16 @@ +@rem Runs C# tests for given assembly from command line. The Grpc.sln solution needs to be built before running the tests. + +setlocal + +@rem enter this directory +cd /d %~dp0\..\..\src\csharp + +packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe -labels "%1/bin/Debug/%1.dll" || goto :error + +endlocal + +goto :EOF + +:error +echo Failed! +exit /b %errorlevel% diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index bd5959cd000..651566188f9 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -234,20 +234,36 @@ class RubyLanguage(object): class CSharpLanguage(object): + def __init__(self): + if platform.system() == 'Windows': + plat = 'windows' + else: + plat = 'posix' + self.platform = plat + def test_specs(self, config, travis): assemblies = ['Grpc.Core.Tests', 'Grpc.Examples.Tests', 'Grpc.IntegrationTesting'] - return [config.job_spec(['tools/run_tests/run_csharp.sh', assembly], + if self.platform == 'windows': + cmd = 'tools\\run_tests\\run_csharp.bat' + else: + cmd = 'tools/run_tests/run_csharp.sh' + return [config.job_spec([cmd, assembly], None, shortname=assembly, environ={'GRPC_TRACE': 'surface,batch'}) for assembly in assemblies ] def make_targets(self): + # For Windows, this target doesn't really build anything, + # everything is build by buildall script later. return ['grpc_csharp_ext'] def build_steps(self): - return [['tools/run_tests/build_csharp.sh']] + if self.platform == 'windows': + return [['src\\csharp\\buildall.bat']] + else: + return [['tools/run_tests/build_csharp.sh']] def supports_multi_config(self): return False From d12029e63c82543c9e02ef813b7dc2119e80bf99 Mon Sep 17 00:00:00 2001 From: Donna Dionne Date: Mon, 1 Jun 2015 16:57:54 -0700 Subject: [PATCH 39/52] Adding csharp_dotnet into interop tests Currently the binaries are built manually which will be automatd in the future. --- tools/gce_setup/interop_test.sh | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tools/gce_setup/interop_test.sh b/tools/gce_setup/interop_test.sh index d6e5fce6b2f..0b5be6ab8a8 100755 --- a/tools/gce_setup/interop_test.sh +++ b/tools/gce_setup/interop_test.sh @@ -38,14 +38,24 @@ log_link=https://pantheon.corp.google.com/m/cloudstorage/b/stoked-keyword-656-ou main() { source grpc_docker.sh - clients=(cxx java go ruby node csharp_mono python php) - servers=(cxx java go ruby node python csharp_mono) + clients=(cxx java go ruby node csharp_mono csharp_dotnet python php) + servers=(cxx java go ruby node csharp_mono csharp_dotnet python csharp_mono) for client in "${clients[@]}" do + client_vm_test=$client_vm + if [ "$client" = "csharp_dotnet" ] + then + client_vm_test="grpc-windows-interop1" + fi for server in "${servers[@]}" do log_file_name=cloud_{$test_case}_{$client}_{$server}.txt - if grpc_interop_test $test_case $client_vm $client $server_vm $server> /tmp/$log_file_name 2>&1 + server_vm_test=$server_vm + if [ "$server" = "csharp_dotnet" ] + then + server_vm_test="grpc-windows-interop1" + fi + if grpc_interop_test $test_case $client_vm_test $client $server_vm_test $server> /tmp/$log_file_name 2>&1 then echo " ['$test_case', '$client', '$server', true, 'log']," >> /tmp/$result.txt else From 8535263b94ee56bbd0e4c9ee168719217459b858 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Tue, 2 Jun 2015 02:01:51 +0200 Subject: [PATCH 40/52] Fixing tools compilation. --- src/core/transport/chttp2/gen_hpack_tables.c | 6 +++--- test/core/security/fetch_oauth2.c | 5 +++-- test/core/security/print_google_default_creds_token.c | 5 +++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/core/transport/chttp2/gen_hpack_tables.c b/src/core/transport/chttp2/gen_hpack_tables.c index 86b593129b0..bdaa3cf094b 100644 --- a/src/core/transport/chttp2/gen_hpack_tables.c +++ b/src/core/transport/chttp2/gen_hpack_tables.c @@ -219,10 +219,10 @@ static int state_index(int bitofs, symset syms, int *isnew) { emit - the symbol to emit on this nibble (or -1 if no symbol has been found) syms - the set of symbols that could be matched */ -static void build_dec_tbl(int state, int nibble, int nibbits, int bitofs, +static void build_dec_tbl(int state, int nibble, int nibbits, unsigned bitofs, int emit, symset syms) { int i; - int bit; + unsigned bit; /* If we have four bits in the nibble we're looking at, then we can fill in a slot in the lookup tables. */ @@ -338,7 +338,7 @@ static void generate_base64_inverse_table(void) { static const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; unsigned char inverse[256]; - int i; + unsigned i; memset(inverse, 255, sizeof(inverse)); for (i = 0; i < strlen(alphabet); i++) { diff --git a/test/core/security/fetch_oauth2.c b/test/core/security/fetch_oauth2.c index 7a40fe0dbb8..3202df33289 100644 --- a/test/core/security/fetch_oauth2.c +++ b/test/core/security/fetch_oauth2.c @@ -51,7 +51,8 @@ typedef struct { int is_done; } synchronizer; -static void on_oauth2_response(void *user_data, grpc_mdelem **md_elems, +static void on_oauth2_response(void *user_data, + grpc_credentials_md *md_elems, size_t num_md, grpc_credentials_status status) { synchronizer *sync = user_data; char *token; @@ -60,7 +61,7 @@ static void on_oauth2_response(void *user_data, grpc_mdelem **md_elems, gpr_log(GPR_ERROR, "Fetching token failed."); } else { GPR_ASSERT(num_md == 1); - token_slice = md_elems[0]->value->slice; + token_slice = md_elems[0].value; token = gpr_malloc(GPR_SLICE_LENGTH(token_slice) + 1); memcpy(token, GPR_SLICE_START_PTR(token_slice), GPR_SLICE_LENGTH(token_slice)); diff --git a/test/core/security/print_google_default_creds_token.c b/test/core/security/print_google_default_creds_token.c index 76e69ef7163..051e8607c40 100644 --- a/test/core/security/print_google_default_creds_token.c +++ b/test/core/security/print_google_default_creds_token.c @@ -49,7 +49,8 @@ typedef struct { int is_done; } synchronizer; -static void on_metadata_response(void *user_data, grpc_mdelem **md_elems, +static void on_metadata_response(void *user_data, + grpc_credentials_md *md_elems, size_t num_md, grpc_credentials_status status) { synchronizer *sync = user_data; @@ -58,7 +59,7 @@ static void on_metadata_response(void *user_data, grpc_mdelem **md_elems, } else { GPR_ASSERT(num_md == 1); printf("\nGot token: %s\n\n", - (const char *)GPR_SLICE_START_PTR(md_elems[0]->value->slice)); + (const char *)GPR_SLICE_START_PTR(md_elems[0].value)); } gpr_mu_lock(&sync->mu); sync->is_done = 1; From 59657dbef81bc8b702da799060ab4edaff05667f Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 1 Jun 2015 20:01:15 -0700 Subject: [PATCH 41/52] Add a completion queue test - create completion queue - call shutdown - call next --- test/core/surface/completion_queue_test.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/core/surface/completion_queue_test.c b/test/core/surface/completion_queue_test.c index e26f379bfc3..f895336fba2 100644 --- a/test/core/surface/completion_queue_test.c +++ b/test/core/surface/completion_queue_test.c @@ -94,6 +94,16 @@ static void test_cq_end_op(void) { shutdown_and_destroy(cc); } +static void test_shutdown_then_next(void) { + grpc_completion_queue *cc; + LOG_TEST("test_shutdown_then_next"); + + cc = grpc_completion_queue_create(); + grpc_completion_queue_shutdown(cc); + GPR_ASSERT(grpc_completion_queue_next(cc, gpr_inf_past).type == GRPC_QUEUE_SHUTDOWN); + grpc_completion_queue_destroy(cc); +} + static void test_pluck(void) { grpc_event ev; grpc_completion_queue *cc; @@ -291,6 +301,7 @@ int main(int argc, char **argv) { grpc_iomgr_init(); test_no_op(); test_wait_empty(); + test_shutdown_then_next(); test_cq_end_op(); test_pluck(); test_threading(1, 1); From c0c484481f2824b11f59c1c2bb77c9af07e15378 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 1 Jun 2015 20:04:36 -0700 Subject: [PATCH 42/52] Extend the test case --- test/core/surface/completion_queue_test.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/test/core/surface/completion_queue_test.c b/test/core/surface/completion_queue_test.c index f895336fba2..9e7b2ea1df5 100644 --- a/test/core/surface/completion_queue_test.c +++ b/test/core/surface/completion_queue_test.c @@ -94,9 +94,9 @@ static void test_cq_end_op(void) { shutdown_and_destroy(cc); } -static void test_shutdown_then_next(void) { +static void test_shutdown_then_next_polling(void) { grpc_completion_queue *cc; - LOG_TEST("test_shutdown_then_next"); + LOG_TEST("test_shutdown_then_next_polling"); cc = grpc_completion_queue_create(); grpc_completion_queue_shutdown(cc); @@ -104,6 +104,16 @@ static void test_shutdown_then_next(void) { grpc_completion_queue_destroy(cc); } +static void test_shutdown_then_next_with_timeout(void) { + grpc_completion_queue *cc; + LOG_TEST("test_shutdown_then_next_with_timeout"); + + cc = grpc_completion_queue_create(); + grpc_completion_queue_shutdown(cc); + GPR_ASSERT(grpc_completion_queue_next(cc, gpr_inf_future).type == GRPC_QUEUE_SHUTDOWN); + grpc_completion_queue_destroy(cc); +} + static void test_pluck(void) { grpc_event ev; grpc_completion_queue *cc; @@ -301,7 +311,8 @@ int main(int argc, char **argv) { grpc_iomgr_init(); test_no_op(); test_wait_empty(); - test_shutdown_then_next(); + test_shutdown_then_next_polling(); + test_shutdown_then_next_with_timeout(); test_cq_end_op(); test_pluck(); test_threading(1, 1); From 50e53e27d5e589c455f9dab927ceb9a8502b64fc Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 1 Jun 2015 20:18:21 -0700 Subject: [PATCH 43/52] Fix bug with finite runs per test --- tools/run_tests/run_tests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index bd5959cd000..b1cde270448 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -346,6 +346,7 @@ def runs_per_test_type(arg_str): try: n = int(arg_str) if n <= 0: raise ValueError + return n except: msg = "'{}' isn't a positive integer or 'inf'".format(arg_str) raise argparse.ArgumentTypeError(msg) From 33da33237d25da760012f1a472fb67fc71b795bf Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 2 Jun 2015 10:29:40 -0700 Subject: [PATCH 44/52] Fix Windows compilation --- src/core/iomgr/endpoint_pair_windows.c | 6 +++--- src/core/iomgr/resolve_address_windows.c | 8 ++++++-- src/core/iomgr/socket_windows.c | 6 +++--- src/core/iomgr/socket_windows.h | 7 +++++-- src/core/iomgr/tcp_client_windows.c | 2 +- src/core/iomgr/tcp_server_windows.c | 5 +++-- 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/core/iomgr/endpoint_pair_windows.c b/src/core/iomgr/endpoint_pair_windows.c index 988d622d01d..c6790b2937b 100644 --- a/src/core/iomgr/endpoint_pair_windows.c +++ b/src/core/iomgr/endpoint_pair_windows.c @@ -77,12 +77,12 @@ static void create_sockets(SOCKET sv[2]) { sv[0] = svr_sock; } -grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(size_t read_slice_size) { +grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name, size_t read_slice_size) { SOCKET sv[2]; grpc_endpoint_pair p; create_sockets(sv); - p.client = grpc_tcp_create(grpc_winsocket_create(sv[1])); - p.server = grpc_tcp_create(grpc_winsocket_create(sv[0])); + p.client = grpc_tcp_create(grpc_winsocket_create(sv[1], "endpoint:client")); + p.server = grpc_tcp_create(grpc_winsocket_create(sv[0], "endpoint:server")); return p; } diff --git a/src/core/iomgr/resolve_address_windows.c b/src/core/iomgr/resolve_address_windows.c index 9b416dfe8aa..7d0d2f9e7a5 100644 --- a/src/core/iomgr/resolve_address_windows.c +++ b/src/core/iomgr/resolve_address_windows.c @@ -54,6 +54,7 @@ typedef struct { char *default_port; grpc_resolve_cb cb; void *arg; + grpc_iomgr_object iomgr_object; } request; grpc_resolved_addresses *grpc_blocking_resolve_address( @@ -135,7 +136,7 @@ static void do_request(void *rp) { gpr_free(r->default_port); gpr_free(r); cb(arg, resolved); - grpc_iomgr_unref(); + grpc_iomgr_unregister_object(&r->iomgr_object); } void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) { @@ -147,7 +148,10 @@ void grpc_resolve_address(const char *name, const char *default_port, grpc_resolve_cb cb, void *arg) { request *r = gpr_malloc(sizeof(request)); gpr_thd_id id; - grpc_iomgr_ref(); + const char *label; + gpr_asprintf(&label, "resolve:%s", name); + grpc_iomgr_register_object(&r->iomgr_object, label); + gpr_free(label); r->name = gpr_strdup(name); r->default_port = gpr_strdup(default_port); r->cb = cb; diff --git a/src/core/iomgr/socket_windows.c b/src/core/iomgr/socket_windows.c index 805fa8a4fc3..e4ba0a2b662 100644 --- a/src/core/iomgr/socket_windows.c +++ b/src/core/iomgr/socket_windows.c @@ -44,12 +44,12 @@ #include "src/core/iomgr/pollset_windows.h" #include "src/core/iomgr/socket_windows.h" -grpc_winsocket *grpc_winsocket_create(SOCKET socket) { +grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name) { grpc_winsocket *r = gpr_malloc(sizeof(grpc_winsocket)); memset(r, 0, sizeof(grpc_winsocket)); r->socket = socket; gpr_mu_init(&r->state_mu); - grpc_iomgr_ref(); + grpc_iomgr_register_object(&r->iomgr_object, name); grpc_iocp_add_socket(r); return r; } @@ -91,7 +91,7 @@ void grpc_winsocket_orphan(grpc_winsocket *winsocket) { grpc_winsocket_destroy(winsocket); } closesocket(socket); - grpc_iomgr_unref(); + grpc_iomgr_unregister_object(&winsocket->iomgr_object); } void grpc_winsocket_destroy(grpc_winsocket *winsocket) { diff --git a/src/core/iomgr/socket_windows.h b/src/core/iomgr/socket_windows.h index d5fee396043..7080919af09 100644 --- a/src/core/iomgr/socket_windows.h +++ b/src/core/iomgr/socket_windows.h @@ -39,7 +39,7 @@ #include #include -#include "src/core/iomgr/iomgr.h" +#include "src/core/iomgr/iomgr_internal.h" /* This holds the data for an outstanding read or write on a socket. The mutex to protect the concurrent access to that data is the one @@ -97,11 +97,14 @@ typedef struct grpc_winsocket { int orphan; grpc_iomgr_closure shutdown_closure; + + /* A label for iomgr to track outstanding objects */ + grpc_iomgr_object iomgr_object; } grpc_winsocket; /* Create a wrapped windows handle. This takes ownership of it, meaning that it will be responsible for closing it. */ -grpc_winsocket *grpc_winsocket_create(SOCKET socket); +grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name); /* Initiate an asynchronous shutdown of the socket. Will call off any pending operation to cancel them. Returns the number of callbacks that got setup. */ diff --git a/src/core/iomgr/tcp_client_windows.c b/src/core/iomgr/tcp_client_windows.c index cf5174327dd..2a040ffc4a5 100644 --- a/src/core/iomgr/tcp_client_windows.c +++ b/src/core/iomgr/tcp_client_windows.c @@ -193,7 +193,7 @@ void grpc_tcp_client_connect(void(*cb)(void *arg, grpc_endpoint *tcp), goto failure; } - socket = grpc_winsocket_create(sock); + socket = grpc_winsocket_create(sock, "client"); info = &socket->write_info; info->outstanding = 1; success = ConnectEx(sock, addr, addr_len, NULL, 0, NULL, &info->overlapped); diff --git a/src/core/iomgr/tcp_server_windows.c b/src/core/iomgr/tcp_server_windows.c index d22acc7453f..9ef369dfd8d 100644 --- a/src/core/iomgr/tcp_server_windows.c +++ b/src/core/iomgr/tcp_server_windows.c @@ -270,7 +270,8 @@ static void on_accept(void *arg, int from_iocp) { gpr_free(utf8_message); closesocket(sock); } else { - ep = grpc_tcp_create(grpc_winsocket_create(sock)); + /* TODO(ctiller): add sockaddr address to label */ + ep = grpc_tcp_create(grpc_winsocket_create(sock, "server")); } } else { /* If we're not notified from the IOCP, it means we are asked to shutdown. @@ -336,7 +337,7 @@ static int add_socket_to_server(grpc_tcp_server *s, SOCKET sock, } sp = &s->ports[s->nports++]; sp->server = s; - sp->socket = grpc_winsocket_create(sock); + sp->socket = grpc_winsocket_create(sock, "listener"); sp->shutting_down = 0; sp->AcceptEx = AcceptEx; sp->new_socket = INVALID_SOCKET; From 945b41312cba1345c05f4f9b2b4727986dd96638 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Tue, 2 Jun 2015 20:13:40 +0200 Subject: [PATCH 45/52] Swapping the library order so that anything that openssl requires is properly tagged afterward. --- Makefile | 6 +++--- templates/Makefile.template | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 647847f7d0e..5b0db6e292f 100644 --- a/Makefile +++ b/Makefile @@ -3073,15 +3073,15 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc.$(SHARED_EXT): $(LIBGRPC_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/gpr.$(SHARED_EXT) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc.def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc-imp.a -o $(LIBDIR)/$(CONFIG)/grpc.$(SHARED_EXT) $(LIBGRPC_OBJS) $(LDLIBS) $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS) -lgpr-imp + $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc.def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc-imp.a -o $(LIBDIR)/$(CONFIG)/grpc.$(SHARED_EXT) $(LIBGRPC_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) -lgpr-imp else $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT): $(LIBGRPC_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name libgrpc.$(SHARED_EXT) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT) $(LIBGRPC_OBJS) $(LDLIBS) $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS) -lgpr + $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name libgrpc.$(SHARED_EXT) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT) $(LIBGRPC_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) -lgpr else - $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.0 -o $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT) $(LIBGRPC_OBJS) $(LDLIBS) $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS) -lgpr + $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.0 -o $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT) $(LIBGRPC_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) -lgpr $(Q) ln -sf libgrpc.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc.so.0 $(Q) ln -sf libgrpc.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc.so endif diff --git a/templates/Makefile.template b/templates/Makefile.template index bc8f1bb1d07..38adb2f6c8c 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -1220,7 +1220,7 @@ endif mingw_lib_deps = mingw_lib_deps + ' $(LIBDIR)/$(CONFIG)/' + dep + '.$(SHARED_EXT)' if lib.get('secure', 'check') == 'yes': - common = common + ' $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS)' + common = common + ' $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE)' for src in lib.src: sources_that_need_openssl.add(src) else: From d62d345b836f20ca0bc1c4fbe57072fee0f8375d Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Tue, 2 Jun 2015 11:28:03 -0700 Subject: [PATCH 46/52] Corrects the cancel_after_first_response test - stops attempting to verify by catching the CancelledError - instead the test examines the operation state after cancellation, which is equally valid and more stable. Also - simplifies bidi on the server --- src/ruby/bin/interop/interop_client.rb | 4 +- src/ruby/lib/grpc/generic/active_call.rb | 11 ++-- src/ruby/lib/grpc/generic/bidi_call.rb | 64 +++++++++++------------- 3 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/ruby/bin/interop/interop_client.rb b/src/ruby/bin/interop/interop_client.rb index 8df03ffb3cd..16fb1b199dd 100755 --- a/src/ruby/bin/interop/interop_client.rb +++ b/src/ruby/bin/interop/interop_client.rb @@ -274,6 +274,7 @@ class NamedTests op = @stub.streaming_input_call(reqs, return_op: true) op.cancel assert_raises(GRPC::Cancelled) { op.execute } + assert(op.cancelled, 'call operation should be CANCELLED') p 'OK: cancel_after_begin' end @@ -282,7 +283,8 @@ class NamedTests ppp = PingPongPlayer.new(msg_sizes) op = @stub.full_duplex_call(ppp.each_item, return_op: true) ppp.canceller_op = op # causes ppp to cancel after the 1st message - assert_raises(GRPC::Cancelled) { op.execute.each { |r| ppp.queue.push(r) } } + op.execute.each { |r| ppp.queue.push(r) } + assert(op.cancelled, 'call operation should be CANCELLED') p 'OK: cancel_after_first_response' end diff --git a/src/ruby/lib/grpc/generic/active_call.rb b/src/ruby/lib/grpc/generic/active_call.rb index 04abab8ac37..3814ef34b41 100644 --- a/src/ruby/lib/grpc/generic/active_call.rb +++ b/src/ruby/lib/grpc/generic/active_call.rb @@ -55,7 +55,6 @@ module GRPC # The ActiveCall class provides simple methods for sending marshallable # data to a call class ActiveCall - include Core::StatusCodes include Core::TimeConsts include Core::CallOps extend Forwardable @@ -129,6 +128,11 @@ module GRPC @output_metadata ||= {} end + # cancelled indicates if the call was cancelled + def cancelled + !@call.status.nil? && @call.status.code == Core::StatusCodes::CANCELLED + end + # multi_req_view provides a restricted view of this ActiveCall for use # in a server client-streaming handler. def multi_req_view @@ -162,6 +166,7 @@ module GRPC ops[RECV_STATUS_ON_CLIENT] = nil if assert_finished batch_result = @call.run_batch(@cq, self, INFINITE_FUTURE, ops) return unless assert_finished + @call.status = batch_result.status batch_result.check_status end @@ -178,6 +183,7 @@ module GRPC @call.metadata.merge!(batch_result.status.metadata) end end + @call.status = batch_result.status batch_result.check_status end @@ -410,9 +416,6 @@ module GRPC start_call(**kw) unless @started bd = BidiCall.new(@call, @cq, @marshal, @unmarshal, @deadline) bd.run_on_client(requests, &blk) - rescue GRPC::Core::CallError => e - finished # checks for Cancelled - raise e end # run_server_bidi orchestrates a BiDi stream processing on a server. diff --git a/src/ruby/lib/grpc/generic/bidi_call.rb b/src/ruby/lib/grpc/generic/bidi_call.rb index f1b9f6b00da..489dd5162a0 100644 --- a/src/ruby/lib/grpc/generic/bidi_call.rb +++ b/src/ruby/lib/grpc/generic/bidi_call.rb @@ -78,11 +78,9 @@ module GRPC # @param requests the Enumerable of requests to send # @return an Enumerator of requests to yield def run_on_client(requests, &blk) - @enq_th = start_write_loop(requests) + @enq_th = Thread.new { write_loop(requests) } @loop_th = start_read_loop - replies = each_queued_msg - return replies if blk.nil? - replies.each { |r| blk.call(r) } + each_queued_msg(&blk) end # Begins orchestration of the Bidi stream for a server generating replies. @@ -98,9 +96,8 @@ module GRPC # @param gen_each_reply [Proc] generates the BiDi stream replies. def run_on_server(gen_each_reply) replys = gen_each_reply.call(each_queued_msg) - @enq_th = start_write_loop(replys, is_client: false) @loop_th = start_read_loop - @enq_th.join if @enq_th.alive? + write_loop(replys, is_client: false) end private @@ -126,37 +123,32 @@ module GRPC end end - # during bidi-streaming, read the requests to send from a separate thread - # read so that read_loop does not block waiting for requests to read. - def start_write_loop(requests, is_client: true) - Thread.new do # TODO: run on a thread pool - GRPC.logger.debug('bidi-write-loop: starting') - begin - write_tag = Object.new - count = 0 - requests.each do |req| - GRPC.logger.debug("bidi-write-loop: #{count}") - count += 1 - payload = @marshal.call(req) - @call.run_batch(@cq, write_tag, INFINITE_FUTURE, - SEND_MESSAGE => payload) - end - GRPC.logger.debug("bidi-write-loop: #{count} writes done") - if is_client - GRPC.logger.debug("bidi-write-loop: client sent #{count}, waiting") - @call.run_batch(@cq, write_tag, INFINITE_FUTURE, - SEND_CLOSE_FROM_CLIENT => nil) - batch_result = @call.run_batch(@cq, write_tag, INFINITE_FUTURE, - RECV_STATUS_ON_CLIENT => nil) - batch_result.check_status - end - rescue StandardError => e - GRPC.logger.warn('bidi-write-loop: failed') - GRPC.logger.warn(e) - raise e - end - GRPC.logger.debug('bidi-write-loop: finished') + def write_loop(requests, is_client: true) + GRPC.logger.debug('bidi-write-loop: starting') + write_tag = Object.new + count = 0 + requests.each do |req| + GRPC.logger.debug("bidi-write-loop: #{count}") + count += 1 + payload = @marshal.call(req) + @call.run_batch(@cq, write_tag, INFINITE_FUTURE, + SEND_MESSAGE => payload) + end + GRPC.logger.debug("bidi-write-loop: #{count} writes done") + if is_client + GRPC.logger.debug("bidi-write-loop: client sent #{count}, waiting") + batch_result = @call.run_batch(@cq, write_tag, INFINITE_FUTURE, + SEND_CLOSE_FROM_CLIENT => nil, + RECV_STATUS_ON_CLIENT => nil) + @call.status = batch_result.status + batch_result.check_status + GRPC.logger.debug("bidi-write-loop: done status #{@call.status}") end + GRPC.logger.debug('bidi-write-loop: finished') + rescue StandardError => e + GRPC.logger.warn('bidi-write-loop: failed') + GRPC.logger.warn(e) + raise e end # starts the read loop From b9692ca809e4318ae87995cae771e40c04f7c27f Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Tue, 2 Jun 2015 12:01:16 -0700 Subject: [PATCH 47/52] Fix NSDictionary <-> metadata codec --- .../GRPCClient/private/NSDictionary+GRPC.m | 73 ++++++++++++++++--- 1 file changed, 63 insertions(+), 10 deletions(-) diff --git a/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m index c350f32f2ac..7705aa46a10 100644 --- a/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m +++ b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m @@ -35,21 +35,77 @@ #include +#pragma mark Category for binary metadata elements + +@interface NSData (GRPCMetadata) ++ (instancetype)grpc_dataFromMetadataValue:(grpc_metadata *)metadata; + +// Fill a metadata object with the binary value in this NSData and the given key. +- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key; +@end + +@implementation NSData (GRPCMetadata) ++ (instancetype)grpc_dataFromMetadataValue:(grpc_metadata *)metadata { + // TODO(jcanizales): Should we use a non-copy constructor? + return [self dataWithBytes:metadata->value length:metadata->value_length]; +} + +- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key { + // TODO(jcanizales): Encode Unicode chars as ASCII. + metadata->key = [key stringByAppendingString:@"-bin"].UTF8String; + metadata->value = self.bytes; + metadata->value_length = self.length; +} +@end + +#pragma mark Category for textual metadata elements + +@interface NSString (GRPCMetadata) ++ (instancetype)grpc_stringFromMetadataValue:(grpc_metadata *)metadata; + +// Fill a metadata object with the textual value in this NSString and the given key. +- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key; +@end + +@implementation NSString (GRPCMetadata) ++ (instancetype)grpc_stringFromMetadataValue:(grpc_metadata *)metadata { + return [[self alloc] initWithBytes:metadata->value + length:metadata->value_length + encoding:NSASCIIStringEncoding]; +} + +- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key { + // TODO(jcanizales): Encode Unicode chars as ASCII. + metadata->key = key.UTF8String; + metadata->value = self.UTF8String; + metadata->value_length = self.length; +} +@end + +#pragma mark Category for metadata arrays + @implementation NSDictionary (GRPC) + (instancetype)grpc_dictionaryFromMetadata:(grpc_metadata *)entries count:(size_t)count { NSMutableDictionary *metadata = [NSMutableDictionary dictionaryWithCapacity:count]; for (grpc_metadata *entry = entries; entry < entries + count; entry++) { - // TODO(jcanizales): Verify in a C library test that it's converting header names to lower case automatically. - NSString *name = [NSString stringWithUTF8String:entry->key]; + // TODO(jcanizales): Verify in a C library test that it's converting header names to lower case + // automatically. + NSString *name = [NSString stringWithCString:entry->key encoding:NSASCIIStringEncoding]; if (!name) { + // log? continue; } + id value; + if ([name hasSuffix:@"-bin"]) { + name = [name substringToIndex:name.length - 4]; + value = [NSData grpc_dataFromMetadataValue:entry]; + } else { + value = [NSString grpc_stringFromMetadataValue:entry]; + } if (!metadata[name]) { metadata[name] = [NSMutableArray array]; } - // TODO(jcanizales): Should we use a non-copy constructor? - [metadata[name] addObject:[NSData dataWithBytes:entry->value - length:entry->value_length]]; + [metadata[name] addObject:value]; } return metadata; } @@ -60,11 +116,8 @@ for (id key in self) { id value = self[key]; grpc_metadata *current = &metadata[i]; - current->key = [key UTF8String]; - if ([value isKindOfClass:[NSData class]]) { - current->value = [value bytes]; - } else if ([value isKindOfClass:[NSString class]]) { - current->value = [value UTF8String]; + if ([value respondsToSelector:@selector(grpc_initMetadata:withKey:)]) { + [value grpc_initMetadata:current withKey:key]; } else { [NSException raise:NSInvalidArgumentException format:@"Metadata values must be NSString or NSData."]; From c9516d4e28b2742b8953efaff4252e1346115723 Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Tue, 2 Jun 2015 13:28:46 -0700 Subject: [PATCH 48/52] Fixed memory leak in server_async --- include/grpc++/server_context.h | 4 ++++ test/cpp/qps/server_async.cc | 33 ++++++++++++++++++--------------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/include/grpc++/server_context.h b/include/grpc++/server_context.h index a62babd9316..d88a3ae2627 100644 --- a/include/grpc++/server_context.h +++ b/include/grpc++/server_context.h @@ -106,6 +106,10 @@ class ServerContext { template friend class ::grpc::ServerReaderWriter; + // Prevent copying. + ServerContext(const ServerContext&); + ServerContext& operator=(const ServerContext&); + class CompletionOp; void BeginCompletionOp(Call* call); diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc index b9998405f69..977dfc2372d 100644 --- a/test/cpp/qps/server_async.cc +++ b/test/cpp/qps/server_async.cc @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -158,11 +159,12 @@ class AsyncQpsServerTest : public Server { void *)> request_method, std::function invoke_method) - : next_state_(&ServerRpcContextUnaryImpl::invoker), + : srv_ctx_(new ServerContext), + next_state_(&ServerRpcContextUnaryImpl::invoker), request_method_(request_method), invoke_method_(invoke_method), - response_writer_(&srv_ctx_) { - request_method_(&srv_ctx_, &req_, &response_writer_, + response_writer_(srv_ctx_.get()) { + request_method_(srv_ctx_.get(), &req_, &response_writer_, AsyncQpsServerTest::tag(this)); } ~ServerRpcContextUnaryImpl() GRPC_OVERRIDE {} @@ -170,14 +172,14 @@ class AsyncQpsServerTest : public Server { return (this->*next_state_)(ok); } void Reset() GRPC_OVERRIDE { - srv_ctx_ = ServerContext(); + srv_ctx_.reset(new ServerContext); req_ = RequestType(); response_writer_ = - grpc::ServerAsyncResponseWriter(&srv_ctx_); + grpc::ServerAsyncResponseWriter(srv_ctx_.get()); // Then request the method next_state_ = &ServerRpcContextUnaryImpl::invoker; - request_method_(&srv_ctx_, &req_, &response_writer_, + request_method_(srv_ctx_.get(), &req_, &response_writer_, AsyncQpsServerTest::tag(this)); } @@ -198,7 +200,7 @@ class AsyncQpsServerTest : public Server { response_writer_.Finish(response, status, AsyncQpsServerTest::tag(this)); return true; } - ServerContext srv_ctx_; + std::unique_ptr srv_ctx_; RequestType req_; bool (ServerRpcContextUnaryImpl::*next_state_)(bool); std::function request_method, std::function invoke_method) - : next_state_(&ServerRpcContextStreamingImpl::request_done), + : srv_ctx_(new ServerContext), + next_state_(&ServerRpcContextStreamingImpl::request_done), request_method_(request_method), invoke_method_(invoke_method), - stream_(&srv_ctx_) { - request_method_(&srv_ctx_, &stream_, AsyncQpsServerTest::tag(this)); + stream_(srv_ctx_.get()) { + request_method_(srv_ctx_.get(), &stream_, AsyncQpsServerTest::tag(this)); } ~ServerRpcContextStreamingImpl() GRPC_OVERRIDE {} bool RunNextState(bool ok) GRPC_OVERRIDE { return (this->*next_state_)(ok); } void Reset() GRPC_OVERRIDE { - srv_ctx_ = ServerContext(); + srv_ctx_.reset(new ServerContext); req_ = RequestType(); - stream_ = - grpc::ServerAsyncReaderWriter(&srv_ctx_); + stream_ = grpc::ServerAsyncReaderWriter( + srv_ctx_.get()); // Then request the method next_state_ = &ServerRpcContextStreamingImpl::request_done; - request_method_(&srv_ctx_, &stream_, AsyncQpsServerTest::tag(this)); + request_method_(srv_ctx_.get(), &stream_, AsyncQpsServerTest::tag(this)); } private: @@ -278,7 +281,7 @@ class AsyncQpsServerTest : public Server { } bool finish_done(bool ok) { return false; /* reset the context */ } - ServerContext srv_ctx_; + std::unique_ptr srv_ctx_; RequestType req_; bool (ServerRpcContextStreamingImpl::*next_state_)(bool); std::function Date: Tue, 2 Jun 2015 00:33:06 +0200 Subject: [PATCH 49/52] Avoid polluting our compilation with previously installed grpc. --- Makefile | 2 ++ templates/Makefile.template | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Makefile b/Makefile index dfdce1d83d8..644691969e8 100644 --- a/Makefile +++ b/Makefile @@ -262,6 +262,8 @@ LDFLAGS += -fPIC endif INCLUDES = . include $(GENDIR) +LDFLAGS += -Llibs/$(CONFIG) + ifeq ($(SYSTEM),Darwin) ifneq ($(wildcard /usr/local/ssl/include),) INCLUDES += /usr/local/ssl/include diff --git a/templates/Makefile.template b/templates/Makefile.template index bc8f1bb1d07..1422150d0d9 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -276,6 +276,8 @@ LDFLAGS += -fPIC endif INCLUDES = . include $(GENDIR) +LDFLAGS += -Llibs/$(CONFIG) + ifeq ($(SYSTEM),Darwin) ifneq ($(wildcard /usr/local/ssl/include),) INCLUDES += /usr/local/ssl/include From d3a2d40b1095142c365d1236cf186958ac2f5007 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Tue, 2 Jun 2015 14:52:35 -0700 Subject: [PATCH 50/52] Disallow NSString headers with -bin suffix --- .../GRPCClient/private/NSDictionary+GRPC.m | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m index 7705aa46a10..e14e503ae0a 100644 --- a/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m +++ b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m @@ -75,6 +75,19 @@ } - (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key { + if ([key hasSuffix:@"-bin"]) { + // Disallow this, as at best it will confuse the server. If the app really needs to send a + // textual header with a name ending in "-bin", it can be done by removing the suffix and + // encoding the NSString as a NSData object. + // + // Why raise an exception: In the most common case, the developer knows this won't happen in + // their code, so the exception isn't triggered. In the rare cases when the developer can't + // tell, it's easy enough to add a sanitizing filter before the header is set. There, the + // developer can choose whether to drop such a header, or trim its name. Doing either ourselves, + // silently, would be very unintuitive for the user. + [NSException raise:NSInvalidArgumentException + format:@"Metadata keys ending in '-bin' are reserved for NSData values."]; + } // TODO(jcanizales): Encode Unicode chars as ASCII. metadata->key = key.UTF8String; metadata->value = self.UTF8String; From 043dc72f64f200739928805ff30f29d237c37e9f Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Tue, 2 Jun 2015 15:15:07 -0700 Subject: [PATCH 51/52] Fix version number of gRPC.podspec And solves a few linter issues that prevent it from being submitted to Cocoapods' repo. --- gRPC.podspec | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/gRPC.podspec b/gRPC.podspec index 8429357a9e1..217d5ca81e4 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -1,13 +1,13 @@ Pod::Spec.new do |s| s.name = 'gRPC' - s.version = '0.0.1' - s.summary = 'Generic gRPC client library for iOS/OSX' - s.homepage = 'https://www.grpc.io' + s.version = '0.5.1' + s.summary = 'gRPC client library for iOS/OSX' + s.homepage = 'http://www.grpc.io' s.license = 'New BSD' - s.authors = { 'Jorge Canizales' => 'jcanizales@google.com', - 'Michael Lumish' => 'mlumish@google.com' } + s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' } - # s.source = { :git => 'https://github.com/grpc/grpc.git', :tag => 'release-0_5_0' } + # s.source = { :git => 'https://github.com/grpc/grpc.git', + # :tag => 'release-0_9_1-objectivec-0.5.1' } s.ios.deployment_target = '6.0' s.osx.deployment_target = '10.8' @@ -15,7 +15,6 @@ Pod::Spec.new do |s| s.subspec 'RxLibrary' do |rs| rs.summary = 'Reactive Extensions library for iOS.' - rs.authors = { 'Jorge Canizales' => 'jcanizales@google.com' } rs.source_files = 'src/objective-c/RxLibrary/*.{h,m}', 'src/objective-c/RxLibrary/transformations/*.{h,m}', @@ -25,16 +24,13 @@ Pod::Spec.new do |s| s.subspec 'C-Core' do |cs| cs.summary = 'Core cross-platform gRPC library, written in C.' - cs.authors = { 'Craig Tiller' => 'ctiller@google.com', - 'David Klempner' => 'klempner@google.com', - 'Nicolas Noble' => 'nnoble@google.com', - 'Vijay Pai' => 'vpai@google.com', - 'Yang Gao' => 'yangg@google.com' } cs.source_files = 'src/core/**/*.{h,c}', 'include/grpc/*.h', 'include/grpc/**/*.h' cs.private_header_files = 'src/core/**/*.h' cs.header_mappings_dir = '.' - cs.xcconfig = { 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/Headers/Build/gRPC" "$(PODS_ROOT)/Headers/Build/gRPC/include"' } + cs.xcconfig = { 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/Headers/Build/gRPC" ' + '"$(PODS_ROOT)/Headers/Build/gRPC/include"' } + cs.compiler_flags = '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w' cs.requires_arc = false cs.libraries = 'z' @@ -67,8 +63,6 @@ Pod::Spec.new do |s| s.subspec 'GRPCClient' do |gs| gs.summary = 'Objective-C wrapper around the core gRPC library.' - gs.authors = { 'Jorge Canizales' => 'jcanizales@google.com', - 'Michael Lumish' => 'mlumish@google.com' } gs.source_files = 'src/objective-c/GRPCClient/*.{h,m}', 'src/objective-c/GRPCClient/private/*.{h,m}' @@ -85,7 +79,6 @@ Pod::Spec.new do |s| s.subspec 'ProtoRPC' do |ps| ps.summary = 'RPC library for ProtocolBuffers, based on gRPC' - ps.authors = { 'Jorge Canizales' => 'jcanizales@google.com' } ps.source_files = 'src/objective-c/ProtoRPC/*.{h,m}' From 06194dcde5d87e4d88c4b73cd196d3d6c1180a9b Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 2 Jun 2015 16:02:02 -0700 Subject: [PATCH 52/52] bump C# package versions --- src/csharp/Grpc.Auth/Grpc.Auth.nuspec | 6 +++--- src/csharp/Grpc.Core/Grpc.Core.nuspec | 6 +++--- src/csharp/Grpc.Tools.nuspec | 4 ++-- src/csharp/Grpc.nuspec | 6 +++--- vsprojects/nuget_package/grpc.native.csharp_ext.nuspec | 6 +++--- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/csharp/Grpc.Auth/Grpc.Auth.nuspec b/src/csharp/Grpc.Auth/Grpc.Auth.nuspec index 171259d18d1..e7a538b21b1 100644 --- a/src/csharp/Grpc.Auth/Grpc.Auth.nuspec +++ b/src/csharp/Grpc.Auth/Grpc.Auth.nuspec @@ -5,19 +5,19 @@ gRPC C# Auth Auth library for C# implementation of gRPC - an RPC library and framework Auth library for C# implementation of gRPC - an RPC library and framework. See project site for more info. - 0.5.0 + 0.5.1 Google Inc. grpc-packages https://github.com/grpc/grpc/blob/master/LICENSE https://github.com/grpc/grpc false - Release 0.5.0 of gRPC C# + Release 0.5.1 of gRPC C# Copyright 2015, Google Inc. gRPC RPC Protocol HTTP/2 Auth OAuth2 - + diff --git a/src/csharp/Grpc.Core/Grpc.Core.nuspec b/src/csharp/Grpc.Core/Grpc.Core.nuspec index 42eb90c9a3d..629b978fdfc 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.nuspec +++ b/src/csharp/Grpc.Core/Grpc.Core.nuspec @@ -5,19 +5,19 @@ gRPC C# Core Core C# implementation of gRPC - an RPC library and framework Core C# implementation of gRPC - an RPC library and framework. See project site for more info. - 0.5.0 + 0.5.1 Google Inc. grpc-packages https://github.com/grpc/grpc/blob/master/LICENSE https://github.com/grpc/grpc false - Release 0.5.0 of gRPC C# + Release 0.5.1 of gRPC C# Copyright 2015, Google Inc. gRPC RPC Protocol HTTP/2 - + diff --git a/src/csharp/Grpc.Tools.nuspec b/src/csharp/Grpc.Tools.nuspec index 155c2ef8c44..913d4c8f4bd 100644 --- a/src/csharp/Grpc.Tools.nuspec +++ b/src/csharp/Grpc.Tools.nuspec @@ -5,13 +5,13 @@ gRPC C# Tools Tools for C# implementation of gRPC - an RPC library and framework Precompiled Windows binaries for generating protocol buffer messages and gRPC client/server code - 0.5.0 + 0.5.1 Google Inc. grpc-packages https://github.com/grpc/grpc/blob/master/LICENSE https://github.com/grpc/grpc false - protoc.exe - protocol buffer compiler v3.0.0-alpha-3; grpc_csharp_plugin.exe - gRPC C# protoc plugin version 0.5.0 + protoc.exe - protocol buffer compiler v3.0.0-alpha-3; grpc_csharp_plugin.exe - gRPC C# protoc plugin version 0.5.1 Copyright 2015, Google Inc. gRPC RPC Protocol HTTP/2 diff --git a/src/csharp/Grpc.nuspec b/src/csharp/Grpc.nuspec index 263e016339e..cf4c74fa2d4 100644 --- a/src/csharp/Grpc.nuspec +++ b/src/csharp/Grpc.nuspec @@ -5,17 +5,17 @@ gRPC C# C# implementation of gRPC - an RPC library and framework C# implementation of gRPC - an RPC library and framework. See project site for more info. - 0.5.0.1 + 0.5.1 Google Inc. grpc-packages https://github.com/grpc/grpc/blob/master/LICENSE https://github.com/grpc/grpc false - Release 0.5.0 of gRPC C# + Release 0.5.1 of gRPC C# Copyright 2015, Google Inc. gRPC RPC Protocol HTTP/2 - + diff --git a/vsprojects/nuget_package/grpc.native.csharp_ext.nuspec b/vsprojects/nuget_package/grpc.native.csharp_ext.nuspec index 2527f4c415c..211d747e2d6 100644 --- a/vsprojects/nuget_package/grpc.native.csharp_ext.nuspec +++ b/vsprojects/nuget_package/grpc.native.csharp_ext.nuspec @@ -2,14 +2,14 @@ grpc.native.csharp_ext - 0.9.0.0 + 0.9.1 Google Inc. grpc-packages https://github.com/grpc/grpc/blob/master/LICENSE http://github.com/grpc/grpc false Native extension needed by gRPC C# library. This is not the package you are looking for, it is only meant to be used as a dependency. - Release of gRPC C core 0.9.0 libraries. + Release of gRPC C core 0.9.1 libraries. Copyright 2015 gRPC C# Native Extension Native library required by gRPC C# @@ -27,4 +27,4 @@ - \ No newline at end of file +