aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Craig Tiller <craig.tiller@gmail.com>2015-06-18 08:19:17 -0700
committerGravatar Craig Tiller <craig.tiller@gmail.com>2015-06-18 08:19:17 -0700
commitac45370a137d733c7fcd61cafbff02f2fadfa55b (patch)
tree68bca88d21896d43f81c6900b7acf3122922f6b4
parentcec9eb9ed727dc7321380d63a9e48c8fc94f2fbe (diff)
parent6174b9a4d092c145d6cd3c90ab59bf5a0939329e (diff)
Merge branch 'we-dont-need-no-backup' into oops-i-split-it-again
-rw-r--r--Makefile2
-rw-r--r--gRPC.podspec6
-rw-r--r--include/grpc++/channel_arguments.h4
-rw-r--r--include/grpc/compression.h13
-rw-r--r--include/grpc/grpc.h16
-rw-r--r--src/core/channel/channel_args.c24
-rw-r--r--src/core/channel/channel_args.h18
-rw-r--r--src/core/channel/child_channel.c3
-rw-r--r--src/core/channel/client_setup.c12
-rw-r--r--src/core/compression/algorithm.c18
-rw-r--r--src/core/httpcli/httpcli.h18
-rw-r--r--src/core/iomgr/pollset.h2
-rw-r--r--src/core/iomgr/pollset_kick_posix.h8
-rw-r--r--src/core/iomgr/pollset_multipoller_with_epoll.c10
-rw-r--r--src/core/iomgr/pollset_multipoller_with_poll_posix.c10
-rw-r--r--src/core/iomgr/pollset_posix.c26
-rw-r--r--src/core/iomgr/pollset_posix.h9
-rw-r--r--src/core/iomgr/pollset_set.h2
-rw-r--r--src/core/iomgr/tcp_client.h4
-rw-r--r--src/core/iomgr/tcp_server_posix.c6
-rw-r--r--src/core/security/client_auth_filter.c4
-rw-r--r--src/cpp/client/channel_arguments.cc5
-rw-r--r--src/csharp/Grpc.Core.Tests/ClientServerTest.cs2
-rw-r--r--src/objective-c/GRPCClient/GRPCCall.m4
-rw-r--r--src/objective-c/README.md2
-rw-r--r--src/python/src/grpc/_adapter/_intermediary_low_test.py95
-rwxr-xr-xsrc/ruby/.rspec2
-rw-r--r--src/ruby/spec/spec_helper.rb2
-rw-r--r--templates/Makefile.template2
-rw-r--r--templates/gRPC.podspec.template127
-rw-r--r--test/cpp/util/cli_call.cc24
-rw-r--r--test/cpp/util/cli_call.h12
-rw-r--r--test/cpp/util/cli_call_test.cc20
-rw-r--r--test/cpp/util/grpc_cli.cc74
-rw-r--r--tools/jenkins/grpc_jenkins_slave/Dockerfile3
-rwxr-xr-xtools/jenkins/run_jenkins.sh11
36 files changed, 480 insertions, 120 deletions
diff --git a/Makefile b/Makefile
index cddc8c7c6d..33ecbf328c 100644
--- a/Makefile
+++ b/Makefile
@@ -1216,7 +1216,7 @@ else
endif
endif
$(Q)$(MAKE) -C third_party/openssl clean
- $(Q)$(MAKE) -C third_party/openssl build_crypto build_ssl
+ $(Q)(unset CPPFLAGS; $(MAKE) -C third_party/openssl build_crypto build_ssl)
$(Q)mkdir -p $(LIBDIR)/$(CONFIG)/openssl
$(Q)cp third_party/openssl/libssl.a third_party/openssl/libcrypto.a $(LIBDIR)/$(CONFIG)/openssl
diff --git a/gRPC.podspec b/gRPC.podspec
index ad621cd2e8..704b623cab 100644
--- a/gRPC.podspec
+++ b/gRPC.podspec
@@ -1,3 +1,5 @@
+
+
Pod::Spec.new do |s|
s.name = 'gRPC'
s.version = '0.6.0'
@@ -23,8 +25,8 @@ Pod::Spec.new do |s|
# Core cross-platform gRPC library, written in C.
s.subspec 'C-Core' do |cs|
- cs.source_files = 'src/core/**/*.{h,c}', 'include/grpc/*.h', 'include/grpc/**/*.h'
- cs.private_header_files = 'src/core/**/*.h'
+ cs.source_files = 'src/core/support/env.h', 'src/core/support/file.h', 'src/core/support/murmur_hash.h', 'src/core/support/grpc_string.h', 'src/core/support/string_win32.h', 'src/core/support/thd_internal.h', 'include/grpc/support/alloc.h', 'include/grpc/support/atm.h', 'include/grpc/support/atm_gcc_atomic.h', 'include/grpc/support/atm_gcc_sync.h', 'include/grpc/support/atm_win32.h', 'include/grpc/support/cancellable_platform.h', 'include/grpc/support/cmdline.h', 'include/grpc/support/cpu.h', 'include/grpc/support/histogram.h', 'include/grpc/support/host_port.h', 'include/grpc/support/log.h', 'include/grpc/support/log_win32.h', 'include/grpc/support/port_platform.h', 'include/grpc/support/slice.h', 'include/grpc/support/slice_buffer.h', 'include/grpc/support/string_util.h', 'include/grpc/support/subprocess.h', 'include/grpc/support/sync.h', 'include/grpc/support/sync_generic.h', 'include/grpc/support/sync_posix.h', 'include/grpc/support/sync_win32.h', 'include/grpc/support/thd.h', 'include/grpc/support/grpc_time.h', 'include/grpc/support/tls.h', 'include/grpc/support/tls_gcc.h', 'include/grpc/support/tls_msvc.h', 'include/grpc/support/tls_pthread.h', 'include/grpc/support/useful.h', 'src/core/support/alloc.c', 'src/core/support/cancellable.c', 'src/core/support/cmdline.c', 'src/core/support/cpu_iphone.c', 'src/core/support/cpu_linux.c', 'src/core/support/cpu_posix.c', 'src/core/support/cpu_windows.c', 'src/core/support/env_linux.c', 'src/core/support/env_posix.c', 'src/core/support/env_win32.c', 'src/core/support/file.c', 'src/core/support/file_posix.c', 'src/core/support/file_win32.c', 'src/core/support/histogram.c', 'src/core/support/host_port.c', 'src/core/support/log.c', 'src/core/support/log_android.c', 'src/core/support/log_linux.c', 'src/core/support/log_posix.c', 'src/core/support/log_win32.c', 'src/core/support/murmur_hash.c', 'src/core/support/slice.c', 'src/core/support/slice_buffer.c', 'src/core/support/string.c', 'src/core/support/string_posix.c', 'src/core/support/string_win32.c', 'src/core/support/subprocess_posix.c', 'src/core/support/sync.c', 'src/core/support/sync_posix.c', 'src/core/support/sync_win32.c', 'src/core/support/thd.c', 'src/core/support/thd_posix.c', 'src/core/support/thd_win32.c', 'src/core/support/time.c', 'src/core/support/time_posix.c', 'src/core/support/time_win32.c', 'src/core/support/tls_pthread.c', 'src/core/httpcli/format_request.h', 'src/core/httpcli/httpcli.h', 'src/core/httpcli/httpcli_security_connector.h', 'src/core/httpcli/parser.h', 'src/core/security/auth_filters.h', 'src/core/security/base64.h', 'src/core/security/credentials.h', 'src/core/security/json_token.h', 'src/core/security/secure_endpoint.h', 'src/core/security/secure_transport_setup.h', 'src/core/security/security_connector.h', 'src/core/security/security_context.h', 'src/core/tsi/fake_transport_security.h', 'src/core/tsi/ssl_transport_security.h', 'src/core/tsi/transport_security.h', 'src/core/tsi/transport_security_interface.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', 'src/core/channel/client_channel.h', 'src/core/channel/client_setup.h', 'src/core/channel/connected_channel.h', 'src/core/channel/http_client_filter.h', 'src/core/channel/http_server_filter.h', 'src/core/channel/noop_filter.h', 'src/core/compression/message_compress.h', 'src/core/debug/trace.h', 'src/core/iomgr/alarm.h', 'src/core/iomgr/alarm_heap.h', 'src/core/iomgr/alarm_internal.h', 'src/core/iomgr/endpoint.h', 'src/core/iomgr/endpoint_pair.h', 'src/core/iomgr/fd_posix.h', 'src/core/iomgr/iocp_windows.h', 'src/core/iomgr/iomgr.h', 'src/core/iomgr/iomgr_internal.h', 'src/core/iomgr/iomgr_posix.h', 'src/core/iomgr/pollset.h', 'src/core/iomgr/pollset_kick_posix.h', 'src/core/iomgr/pollset_posix.h', 'src/core/iomgr/pollset_set_posix.h', 'src/core/iomgr/pollset_set_windows.h', 'src/core/iomgr/pollset_windows.h', 'src/core/iomgr/resolve_address.h', 'src/core/iomgr/sockaddr.h', 'src/core/iomgr/sockaddr_posix.h', 'src/core/iomgr/sockaddr_utils.h', 'src/core/iomgr/sockaddr_win32.h', 'src/core/iomgr/socket_utils_posix.h', 'src/core/iomgr/socket_windows.h', 'src/core/iomgr/tcp_client.h', 'src/core/iomgr/tcp_posix.h', 'src/core/iomgr/tcp_server.h', 'src/core/iomgr/tcp_windows.h', 'src/core/iomgr/time_averaged_stats.h', 'src/core/iomgr/wakeup_fd_pipe.h', 'src/core/iomgr/wakeup_fd_posix.h', 'src/core/json/json.h', 'src/core/json/json_common.h', 'src/core/json/json_reader.h', 'src/core/json/json_writer.h', 'src/core/profiling/timers.h', 'src/core/profiling/timers_preciseclock.h', 'src/core/surface/byte_buffer_queue.h', 'src/core/surface/call.h', 'src/core/surface/channel.h', 'src/core/surface/client.h', 'src/core/surface/completion_queue.h', 'src/core/surface/event_string.h', 'src/core/surface/init.h', 'src/core/surface/server.h', 'src/core/surface/surface_trace.h', 'src/core/transport/chttp2/alpn.h', 'src/core/transport/chttp2/bin_encoder.h', 'src/core/transport/chttp2/frame.h', 'src/core/transport/chttp2/frame_data.h', 'src/core/transport/chttp2/frame_goaway.h', 'src/core/transport/chttp2/frame_ping.h', 'src/core/transport/chttp2/frame_rst_stream.h', 'src/core/transport/chttp2/frame_settings.h', 'src/core/transport/chttp2/frame_window_update.h', 'src/core/transport/chttp2/hpack_parser.h', 'src/core/transport/chttp2/hpack_table.h', 'src/core/transport/chttp2/http2_errors.h', 'src/core/transport/chttp2/huffsyms.h', 'src/core/transport/chttp2/status_conversion.h', 'src/core/transport/chttp2/stream_encoder.h', 'src/core/transport/chttp2/stream_map.h', 'src/core/transport/chttp2/timeout_encoding.h', 'src/core/transport/chttp2/varint.h', 'src/core/transport/chttp2_transport.h', 'src/core/transport/metadata.h', 'src/core/transport/stream_op.h', 'src/core/transport/transport.h', 'src/core/transport/transport_impl.h', 'src/core/census/context.h', 'include/grpc/grpc_security.h', 'include/grpc/byte_buffer.h', 'include/grpc/byte_buffer_reader.h', 'include/grpc/compression.h', 'include/grpc/grpc.h', 'include/grpc/status.h', 'include/grpc/census.h', 'src/core/httpcli/format_request.c', 'src/core/httpcli/httpcli.c', 'src/core/httpcli/httpcli_security_connector.c', 'src/core/httpcli/parser.c', 'src/core/security/base64.c', 'src/core/security/client_auth_filter.c', 'src/core/security/credentials.c', 'src/core/security/credentials_metadata.c', 'src/core/security/credentials_posix.c', 'src/core/security/credentials_win32.c', 'src/core/security/google_default_credentials.c', 'src/core/security/json_token.c', 'src/core/security/secure_endpoint.c', 'src/core/security/secure_transport_setup.c', 'src/core/security/security_connector.c', 'src/core/security/security_context.c', 'src/core/security/server_auth_filter.c', 'src/core/security/server_secure_chttp2.c', 'src/core/surface/init_secure.c', 'src/core/surface/secure_channel_create.c', 'src/core/tsi/fake_transport_security.c', 'src/core/tsi/ssl_transport_security.c', 'src/core/tsi/transport_security.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', 'src/core/channel/client_channel.c', 'src/core/channel/client_setup.c', 'src/core/channel/connected_channel.c', 'src/core/channel/http_client_filter.c', 'src/core/channel/http_server_filter.c', 'src/core/channel/noop_filter.c', 'src/core/compression/algorithm.c', 'src/core/compression/message_compress.c', 'src/core/debug/trace.c', 'src/core/iomgr/alarm.c', 'src/core/iomgr/alarm_heap.c', 'src/core/iomgr/endpoint.c', 'src/core/iomgr/endpoint_pair_posix.c', 'src/core/iomgr/endpoint_pair_windows.c', 'src/core/iomgr/fd_posix.c', 'src/core/iomgr/iocp_windows.c', 'src/core/iomgr/iomgr.c', 'src/core/iomgr/iomgr_posix.c', 'src/core/iomgr/iomgr_windows.c', 'src/core/iomgr/pollset_kick_posix.c', 'src/core/iomgr/pollset_multipoller_with_epoll.c', 'src/core/iomgr/pollset_multipoller_with_poll_posix.c', 'src/core/iomgr/pollset_posix.c', 'src/core/iomgr/pollset_set_posix.c', 'src/core/iomgr/pollset_set_windows.c', 'src/core/iomgr/pollset_windows.c', 'src/core/iomgr/resolve_address_posix.c', 'src/core/iomgr/resolve_address_windows.c', 'src/core/iomgr/sockaddr_utils.c', 'src/core/iomgr/socket_utils_common_posix.c', 'src/core/iomgr/socket_utils_linux.c', 'src/core/iomgr/socket_utils_posix.c', 'src/core/iomgr/socket_windows.c', 'src/core/iomgr/tcp_client_posix.c', 'src/core/iomgr/tcp_client_windows.c', 'src/core/iomgr/tcp_posix.c', 'src/core/iomgr/tcp_server_posix.c', 'src/core/iomgr/tcp_server_windows.c', 'src/core/iomgr/tcp_windows.c', 'src/core/iomgr/time_averaged_stats.c', 'src/core/iomgr/wakeup_fd_eventfd.c', 'src/core/iomgr/wakeup_fd_nospecial.c', 'src/core/iomgr/wakeup_fd_pipe.c', 'src/core/iomgr/wakeup_fd_posix.c', 'src/core/json/json.c', 'src/core/json/json_reader.c', 'src/core/json/json_string.c', 'src/core/json/json_writer.c', 'src/core/profiling/basic_timers.c', 'src/core/profiling/stap_timers.c', 'src/core/surface/byte_buffer.c', 'src/core/surface/byte_buffer_queue.c', 'src/core/surface/byte_buffer_reader.c', 'src/core/surface/call.c', 'src/core/surface/call_details.c', 'src/core/surface/call_log_batch.c', 'src/core/surface/channel.c', 'src/core/surface/channel_create.c', 'src/core/surface/client.c', 'src/core/surface/completion_queue.c', 'src/core/surface/event_string.c', 'src/core/surface/init.c', 'src/core/surface/lame_client.c', 'src/core/surface/metadata_array.c', 'src/core/surface/server.c', 'src/core/surface/server_chttp2.c', 'src/core/surface/server_create.c', 'src/core/surface/surface_trace.c', 'src/core/transport/chttp2/alpn.c', 'src/core/transport/chttp2/bin_encoder.c', 'src/core/transport/chttp2/frame_data.c', 'src/core/transport/chttp2/frame_goaway.c', 'src/core/transport/chttp2/frame_ping.c', 'src/core/transport/chttp2/frame_rst_stream.c', 'src/core/transport/chttp2/frame_settings.c', 'src/core/transport/chttp2/frame_window_update.c', 'src/core/transport/chttp2/hpack_parser.c', 'src/core/transport/chttp2/hpack_table.c', 'src/core/transport/chttp2/huffsyms.c', 'src/core/transport/chttp2/status_conversion.c', 'src/core/transport/chttp2/stream_encoder.c', 'src/core/transport/chttp2/stream_map.c', 'src/core/transport/chttp2/timeout_encoding.c', 'src/core/transport/chttp2/varint.c', 'src/core/transport/chttp2_transport.c', 'src/core/transport/metadata.c', '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',
+ cs.private_header_files = 'src/core/support/env.h', 'src/core/support/file.h', 'src/core/support/murmur_hash.h', 'src/core/support/string.h', 'src/core/support/string_win32.h', 'src/core/support/thd_internal.h', 'src/core/httpcli/format_request.h', 'src/core/httpcli/httpcli.h', 'src/core/httpcli/httpcli_security_connector.h', 'src/core/httpcli/parser.h', 'src/core/security/auth_filters.h', 'src/core/security/base64.h', 'src/core/security/credentials.h', 'src/core/security/json_token.h', 'src/core/security/secure_endpoint.h', 'src/core/security/secure_transport_setup.h', 'src/core/security/security_connector.h', 'src/core/security/security_context.h', 'src/core/tsi/fake_transport_security.h', 'src/core/tsi/ssl_transport_security.h', 'src/core/tsi/transport_security.h', 'src/core/tsi/transport_security_interface.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', 'src/core/channel/client_channel.h', 'src/core/channel/client_setup.h', 'src/core/channel/connected_channel.h', 'src/core/channel/http_client_filter.h', 'src/core/channel/http_server_filter.h', 'src/core/channel/noop_filter.h', 'src/core/compression/message_compress.h', 'src/core/debug/trace.h', 'src/core/iomgr/alarm.h', 'src/core/iomgr/alarm_heap.h', 'src/core/iomgr/alarm_internal.h', 'src/core/iomgr/endpoint.h', 'src/core/iomgr/endpoint_pair.h', 'src/core/iomgr/fd_posix.h', 'src/core/iomgr/iocp_windows.h', 'src/core/iomgr/iomgr.h', 'src/core/iomgr/iomgr_internal.h', 'src/core/iomgr/iomgr_posix.h', 'src/core/iomgr/pollset.h', 'src/core/iomgr/pollset_kick_posix.h', 'src/core/iomgr/pollset_posix.h', 'src/core/iomgr/pollset_set_posix.h', 'src/core/iomgr/pollset_set_windows.h', 'src/core/iomgr/pollset_windows.h', 'src/core/iomgr/resolve_address.h', 'src/core/iomgr/sockaddr.h', 'src/core/iomgr/sockaddr_posix.h', 'src/core/iomgr/sockaddr_utils.h', 'src/core/iomgr/sockaddr_win32.h', 'src/core/iomgr/socket_utils_posix.h', 'src/core/iomgr/socket_windows.h', 'src/core/iomgr/tcp_client.h', 'src/core/iomgr/tcp_posix.h', 'src/core/iomgr/tcp_server.h', 'src/core/iomgr/tcp_windows.h', 'src/core/iomgr/time_averaged_stats.h', 'src/core/iomgr/wakeup_fd_pipe.h', 'src/core/iomgr/wakeup_fd_posix.h', 'src/core/json/json.h', 'src/core/json/json_common.h', 'src/core/json/json_reader.h', 'src/core/json/json_writer.h', 'src/core/profiling/timers.h', 'src/core/profiling/timers_preciseclock.h', 'src/core/surface/byte_buffer_queue.h', 'src/core/surface/call.h', 'src/core/surface/channel.h', 'src/core/surface/client.h', 'src/core/surface/completion_queue.h', 'src/core/surface/event_string.h', 'src/core/surface/init.h', 'src/core/surface/server.h', 'src/core/surface/surface_trace.h', 'src/core/transport/chttp2/alpn.h', 'src/core/transport/chttp2/bin_encoder.h', 'src/core/transport/chttp2/frame.h', 'src/core/transport/chttp2/frame_data.h', 'src/core/transport/chttp2/frame_goaway.h', 'src/core/transport/chttp2/frame_ping.h', 'src/core/transport/chttp2/frame_rst_stream.h', 'src/core/transport/chttp2/frame_settings.h', 'src/core/transport/chttp2/frame_window_update.h', 'src/core/transport/chttp2/hpack_parser.h', 'src/core/transport/chttp2/hpack_table.h', 'src/core/transport/chttp2/http2_errors.h', 'src/core/transport/chttp2/huffsyms.h', 'src/core/transport/chttp2/status_conversion.h', 'src/core/transport/chttp2/stream_encoder.h', 'src/core/transport/chttp2/stream_map.h', 'src/core/transport/chttp2/timeout_encoding.h', 'src/core/transport/chttp2/varint.h', 'src/core/transport/chttp2_transport.h', 'src/core/transport/metadata.h', 'src/core/transport/stream_op.h', 'src/core/transport/transport.h', 'src/core/transport/transport_impl.h', 'src/core/census/context.h',
cs.header_mappings_dir = '.'
# The core library includes its headers as either "src/core/..." or "grpc/...", meaning we have
# to tell XCode to look for headers under the "include" subdirectory too.
diff --git a/include/grpc++/channel_arguments.h b/include/grpc++/channel_arguments.h
index 8d338c654e..68f24cde4a 100644
--- a/include/grpc++/channel_arguments.h
+++ b/include/grpc++/channel_arguments.h
@@ -38,6 +38,7 @@
#include <list>
#include <grpc++/config.h>
+#include <grpc/compression.h>
#include <grpc/grpc.h>
namespace grpc {
@@ -58,6 +59,9 @@ class ChannelArguments {
void SetSslTargetNameOverride(const grpc::string& name);
// TODO(yangg) add flow control options
+ // Set the compression level for the channel.
+ void SetCompressionLevel(grpc_compression_level level);
+
// Generic channel argument setters. Only for advanced use cases.
void SetInt(const grpc::string& key, int value);
void SetString(const grpc::string& key, const grpc::string& value);
diff --git a/include/grpc/compression.h b/include/grpc/compression.h
index 968a757060..61bce05b50 100644
--- a/include/grpc/compression.h
+++ b/include/grpc/compression.h
@@ -34,6 +34,9 @@
#ifndef GRPC_COMPRESSION_H
#define GRPC_COMPRESSION_H
+/** To be used in channel arguments */
+#define GRPC_COMPRESSION_LEVEL_ARG "grpc.compression_level"
+
/* The various compression algorithms supported by GRPC */
typedef enum {
GRPC_COMPRESS_NONE = 0,
@@ -43,7 +46,17 @@ typedef enum {
GRPC_COMPRESS_ALGORITHMS_COUNT
} grpc_compression_algorithm;
+typedef enum {
+ GRPC_COMPRESS_LEVEL_NONE = 0,
+ GRPC_COMPRESS_LEVEL_LOW,
+ GRPC_COMPRESS_LEVEL_MED,
+ GRPC_COMPRESS_LEVEL_HIGH
+} grpc_compression_level;
+
const char *grpc_compression_algorithm_name(
grpc_compression_algorithm algorithm);
+grpc_compression_algorithm grpc_compression_algorithm_for_level(
+ grpc_compression_level level);
+
#endif /* GRPC_COMPRESSION_H */
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index 27676632c1..9272673cab 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -99,7 +99,8 @@ typedef struct {
These configuration options are modelled as key-value pairs as defined
by grpc_arg; keys are strings to allow easy backwards-compatible extension
by arbitrary parties.
- All evaluation is performed at channel creation time. */
+ All evaluation is performed at channel creation time (i.e. the values in
+ this structure need only live through the creation invocation). */
typedef struct {
size_t num_args;
grpc_arg *args;
@@ -274,6 +275,8 @@ typedef struct grpc_op {
After the operation completes, call grpc_metadata_array_destroy on this
value, or reuse it in a future op. */
grpc_metadata_array *recv_initial_metadata;
+ /* ownership of the byte buffer is moved to the caller; the caller must call
+ grpc_byte_buffer_destroy on this value, or reuse it in a future op. */
grpc_byte_buffer **recv_message;
struct {
/* ownership of the array is with the caller, but ownership of the
@@ -374,7 +377,8 @@ void grpc_completion_queue_destroy(grpc_completion_queue *cq);
/* Create a call given a grpc_channel, in order to call 'method'. The request
is not sent until grpc_call_invoke is called. All completions are sent to
- 'completion_queue'. */
+ 'completion_queue'. 'method' and 'host' need only live through the invocation
+ of this function. */
grpc_call *grpc_channel_create_call(grpc_channel *channel,
grpc_completion_queue *completion_queue,
const char *method, const char *host,
@@ -399,8 +403,9 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
/* Create a client channel to 'target'. Additional channel level configuration
MAY be provided by grpc_channel_args, though the expectation is that most
- clients will want to simply pass NULL. See grpc_channel_args definition
- for more on this. */
+ clients will want to simply pass NULL. See grpc_channel_args definition for
+ more on this. The data in 'args' need only live through the invocation of
+ this function. */
grpc_channel *grpc_channel_create(const char *target,
const grpc_channel_args *args);
@@ -471,7 +476,8 @@ grpc_call_error grpc_server_request_registered_call(
/* Create a server. Additional configuration for each incoming channel can
be specified with args. If no additional configuration is needed, args can
- be NULL. See grpc_channel_args for more. */
+ be NULL. See grpc_channel_args for more. The data in 'args' need only live
+ through the invocation of this function. */
grpc_server *grpc_server_create(const grpc_channel_args *args);
/* Register a completion queue with the server. Must be done for any completion
diff --git a/src/core/channel/channel_args.c b/src/core/channel/channel_args.c
index 1b0e33b123..166d559a45 100644
--- a/src/core/channel/channel_args.c
+++ b/src/core/channel/channel_args.c
@@ -115,3 +115,27 @@ int grpc_channel_args_is_census_enabled(const grpc_channel_args *a) {
}
return 0;
}
+
+grpc_compression_level grpc_channel_args_get_compression_level(
+ const grpc_channel_args *a) {
+ size_t i;
+ if (a) {
+ for (i = 0; a && i < a->num_args; ++i) {
+ if (a->args[i].type == GRPC_ARG_INTEGER &&
+ !strcmp(GRPC_COMPRESSION_LEVEL_ARG, a->args[i].key)) {
+ return a->args[i].value.integer;
+ break;
+ }
+ }
+ }
+ return GRPC_COMPRESS_LEVEL_NONE;
+}
+
+void grpc_channel_args_set_compression_level(
+ grpc_channel_args **a, grpc_compression_level level) {
+ grpc_arg tmp;
+ tmp.type = GRPC_ARG_INTEGER;
+ tmp.key = GRPC_COMPRESSION_LEVEL_ARG;
+ tmp.value.integer = level;
+ *a = grpc_channel_args_copy_and_add(*a, &tmp);
+}
diff --git a/src/core/channel/channel_args.h b/src/core/channel/channel_args.h
index eb5bf63986..bf747b26e6 100644
--- a/src/core/channel/channel_args.h
+++ b/src/core/channel/channel_args.h
@@ -34,21 +34,31 @@
#ifndef GRPC_INTERNAL_CORE_CHANNEL_CHANNEL_ARGS_H
#define GRPC_INTERNAL_CORE_CHANNEL_CHANNEL_ARGS_H
+#include <grpc/compression.h>
#include <grpc/grpc.h>
/* Copy some arguments */
grpc_channel_args *grpc_channel_args_copy(const grpc_channel_args *src);
-/* Copy some arguments and add the to_add parameter in the end.
+/** Copy some arguments and add the to_add parameter in the end.
If to_add is NULL, it is equivalent to call grpc_channel_args_copy. */
grpc_channel_args *grpc_channel_args_copy_and_add(const grpc_channel_args *src,
const grpc_arg *to_add);
-/* Destroy arguments created by grpc_channel_args_copy */
+/** Destroy arguments created by grpc_channel_args_copy */
void grpc_channel_args_destroy(grpc_channel_args *a);
-/* Reads census_enabled settings from channel args. Returns 1 if census_enabled
- is specified in channel args, otherwise returns 0. */
+/** Reads census_enabled settings from channel args. Returns 1 if census_enabled
+ * is specified in channel args, otherwise returns 0. */
int grpc_channel_args_is_census_enabled(const grpc_channel_args *a);
+/** Returns the compression level set in \a a. */
+grpc_compression_level grpc_channel_args_get_compression_level(
+ const grpc_channel_args *a);
+
+/** Sets the compression level in \a a to \a level. Setting it to
+ * GRPC_COMPRESS_LEVEL_NONE disables compression for the channel. */
+void grpc_channel_args_set_compression_level(
+ grpc_channel_args **a, grpc_compression_level level);
+
#endif /* GRPC_INTERNAL_CORE_CHANNEL_CHANNEL_ARGS_H */
diff --git a/src/core/channel/child_channel.c b/src/core/channel/child_channel.c
index d3e6af7287..6690265d75 100644
--- a/src/core/channel/child_channel.c
+++ b/src/core/channel/child_channel.c
@@ -158,11 +158,8 @@ static void lb_destroy_channel_elem(grpc_channel_element *elem) {
const grpc_channel_filter grpc_child_channel_top_filter = {
lb_start_transport_op, lb_channel_op,
-
sizeof(lb_call_data), lb_init_call_elem, lb_destroy_call_elem,
-
sizeof(lb_channel_data), lb_init_channel_elem, lb_destroy_channel_elem,
-
"child-channel",
};
diff --git a/src/core/channel/client_setup.c b/src/core/channel/client_setup.c
index a804a4712c..5be8fa66e9 100644
--- a/src/core/channel/client_setup.c
+++ b/src/core/channel/client_setup.c
@@ -56,6 +56,8 @@ struct grpc_client_setup {
gpr_cv cv;
grpc_client_setup_request *active_request;
int refs;
+ /** The set of pollsets that are currently interested in this
+ connection being established */
grpc_pollset_set interested_parties;
};
@@ -92,7 +94,6 @@ static void setup_initiate(grpc_transport_setup *sp) {
int in_alarm = 0;
r->setup = s;
- /* TODO(klempner): Actually set a deadline */
r->deadline = gpr_time_add(gpr_now(), gpr_time_from_seconds(60));
gpr_mu_lock(&s->mu);
@@ -117,25 +118,23 @@ static void setup_initiate(grpc_transport_setup *sp) {
}
}
+/** implementation of add_interested_party for setup vtable */
static void setup_add_interested_party(grpc_transport_setup *sp,
grpc_pollset *pollset) {
grpc_client_setup *s = (grpc_client_setup *)sp;
gpr_mu_lock(&s->mu);
-
grpc_pollset_set_add_pollset(&s->interested_parties, pollset);
-
gpr_mu_unlock(&s->mu);
}
+/** implementation of del_interested_party for setup vtable */
static void setup_del_interested_party(grpc_transport_setup *sp,
grpc_pollset *pollset) {
grpc_client_setup *s = (grpc_client_setup *)sp;
gpr_mu_lock(&s->mu);
-
grpc_pollset_set_del_pollset(&s->interested_parties, pollset);
-
gpr_mu_unlock(&s->mu);
}
@@ -232,7 +231,8 @@ int grpc_client_setup_request_should_continue(grpc_client_setup_request *r,
return result;
}
-static void backoff_alarm_done(void *arg /* grpc_client_setup */, int success) {
+static void backoff_alarm_done(void *arg /* grpc_client_setup_request */,
+ int success) {
grpc_client_setup_request *r = arg;
grpc_client_setup *s = r->setup;
/* Handle status cancelled? */
diff --git a/src/core/compression/algorithm.c b/src/core/compression/algorithm.c
index 36ead843d2..4db48df6cb 100644
--- a/src/core/compression/algorithm.c
+++ b/src/core/compression/algorithm.c
@@ -31,6 +31,7 @@
*
*/
+#include <stdlib.h>
#include <grpc/compression.h>
const char *grpc_compression_algorithm_name(
@@ -47,3 +48,20 @@ const char *grpc_compression_algorithm_name(
}
return "error";
}
+
+/* TODO(dgq): Add the ability to specify parameters to the individual
+ * compression algorithms */
+grpc_compression_algorithm grpc_compression_algorithm_for_level(
+ grpc_compression_level level) {
+ switch (level) {
+ case GRPC_COMPRESS_LEVEL_NONE:
+ return GRPC_COMPRESS_NONE;
+ case GRPC_COMPRESS_LEVEL_LOW:
+ case GRPC_COMPRESS_LEVEL_MED:
+ case GRPC_COMPRESS_LEVEL_HIGH:
+ return GRPC_COMPRESS_DEFLATE;
+ default:
+ /* we shouldn't be making it here */
+ abort();
+ }
+}
diff --git a/src/core/httpcli/httpcli.h b/src/core/httpcli/httpcli.h
index cee374fe8e..06699e88c2 100644
--- a/src/core/httpcli/httpcli.h
+++ b/src/core/httpcli/httpcli.h
@@ -93,6 +93,10 @@ void grpc_httpcli_context_init(grpc_httpcli_context *context);
void grpc_httpcli_context_destroy(grpc_httpcli_context *context);
/* Asynchronously perform a HTTP GET.
+ 'context' specifies the http context under which to do the get
+ 'pollset' indicates a grpc_pollset that is interested in the result
+ of the get - work on this pollset may be used to progress the get
+ operation
'request' contains request parameters - these are caller owned and can be
destroyed once the call returns
'deadline' contains a deadline for the request (or gpr_inf_future)
@@ -106,7 +110,19 @@ void grpc_httpcli_get(grpc_httpcli_context *context, grpc_pollset *pollset,
grpc_httpcli_response_cb on_response, void *user_data);
/* Asynchronously perform a HTTP POST.
- When there is no body, pass in NULL as body_bytes.
+ 'context' specifies the http context under which to do the post
+ 'pollset' indicates a grpc_pollset that is interested in the result
+ of the post - work on this pollset may be used to progress the post
+ operation
+ 'request' contains request parameters - these are caller owned and can be
+ destroyed once the call returns
+ 'body_bytes' and 'body_size' specify the payload for the post.
+ When there is no body, pass in NULL as body_bytes.
+ 'deadline' contains a deadline for the request (or gpr_inf_future)
+ 'em' points to a caller owned event manager that must be alive for the
+ lifetime of the request
+ 'on_response' is a callback to report results to (and 'user_data' is a user
+ supplied pointer to pass to said call)
Does not support ?var1=val1&var2=val2 in the path. */
void grpc_httpcli_post(grpc_httpcli_context *context, grpc_pollset *pollset,
const grpc_httpcli_request *request,
diff --git a/src/core/iomgr/pollset.h b/src/core/iomgr/pollset.h
index da3c94ec11..7472b6144f 100644
--- a/src/core/iomgr/pollset.h
+++ b/src/core/iomgr/pollset.h
@@ -65,7 +65,7 @@ void grpc_pollset_destroy(grpc_pollset *pollset);
May unlock GRPC_POLLSET_MU(pollset) during its execution. */
int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline);
-/* Break a pollset out of polling work
+/* Break one polling thread out of polling work for this pollset.
Requires GRPC_POLLSET_MU(pollset) locked. */
void grpc_pollset_kick(grpc_pollset *pollset);
diff --git a/src/core/iomgr/pollset_kick_posix.h b/src/core/iomgr/pollset_kick_posix.h
index 0a404b601b..77e32a8d51 100644
--- a/src/core/iomgr/pollset_kick_posix.h
+++ b/src/core/iomgr/pollset_kick_posix.h
@@ -37,6 +37,11 @@
#include "src/core/iomgr/wakeup_fd_posix.h"
#include <grpc/support/sync.h>
+/* pollset kicking allows breaking a thread out of polling work for
+ a given pollset.
+ writing a byte to a pipe is used as a posix-ly portable base
+ mechanism, and eventfds are utilized on Linux for better performance. */
+
typedef struct grpc_kick_fd_info {
grpc_wakeup_fd_info wakeup_fd;
/* used for polling list and free list */
@@ -67,7 +72,7 @@ void grpc_pollset_kick_destroy(grpc_pollset_kick_state *kick_state);
* applicable. Intended for testing. */
void grpc_pollset_kick_global_init_fallback_fd(void);
-/* Must be called before entering poll(). If return value is -1, this consumed
+/* Must be called before entering poll(). If return value is NULL, this consumed
an existing kick. Otherwise the return value is an FD to add to the poll set.
*/
grpc_kick_fd_info *grpc_pollset_kick_pre_poll(
@@ -82,6 +87,7 @@ void grpc_pollset_kick_consume(grpc_pollset_kick_state *kick_state,
void grpc_pollset_kick_post_poll(grpc_pollset_kick_state *kick_state,
grpc_kick_fd_info *fd_info);
+/* Actually kick */
void grpc_pollset_kick_kick(grpc_pollset_kick_state *kick_state);
#endif /* GRPC_INTERNAL_CORE_IOMGR_POLLSET_KICK_POSIX_H */
diff --git a/src/core/iomgr/pollset_multipoller_with_epoll.c b/src/core/iomgr/pollset_multipoller_with_epoll.c
index e5e3435feb..b4a526b9e7 100644
--- a/src/core/iomgr/pollset_multipoller_with_epoll.c
+++ b/src/core/iomgr/pollset_multipoller_with_epoll.c
@@ -97,15 +97,7 @@ static int multipoll_with_epoll_pollset_maybe_work(
* here.
*/
- if (gpr_time_cmp(deadline, gpr_inf_future) == 0) {
- timeout_ms = -1;
- } else {
- timeout_ms = gpr_time_to_millis(
- gpr_time_add(gpr_time_sub(deadline, now), gpr_time_from_micros(500)));
- if (timeout_ms < 0) {
- return 1;
- }
- }
+ timeout_ms = grpc_poll_deadline_to_millis_timeout(deadline, now);
pollset->counter += 1;
gpr_mu_unlock(&pollset->mu);
diff --git a/src/core/iomgr/pollset_multipoller_with_poll_posix.c b/src/core/iomgr/pollset_multipoller_with_poll_posix.c
index d21c52c0f0..2f108da66a 100644
--- a/src/core/iomgr/pollset_multipoller_with_poll_posix.c
+++ b/src/core/iomgr/pollset_multipoller_with_poll_posix.c
@@ -113,15 +113,7 @@ static int multipoll_with_poll_pollset_maybe_work(
grpc_kick_fd_info *kfd;
h = pollset->data.ptr;
- if (gpr_time_cmp(deadline, gpr_inf_future) == 0) {
- timeout = -1;
- } else {
- timeout = gpr_time_to_millis(
- gpr_time_add(gpr_time_sub(deadline, now), gpr_time_from_micros(500)));
- if (timeout < 0) {
- return 1;
- }
- }
+ timeout = grpc_poll_deadline_to_millis_timeout(deadline, now);
if (h->pfd_capacity < h->fd_count + 1) {
h->pfd_capacity = GPR_MAX(h->pfd_capacity * 3 / 2, h->fd_count + 1);
gpr_free(h->pfds);
diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c
index 83ff1f26a5..46d3d132ce 100644
--- a/src/core/iomgr/pollset_posix.c
+++ b/src/core/iomgr/pollset_posix.c
@@ -188,6 +188,22 @@ void grpc_pollset_destroy(grpc_pollset *pollset) {
gpr_mu_destroy(&pollset->mu);
}
+int grpc_poll_deadline_to_millis_timeout(gpr_timespec deadline, gpr_timespec now) {
+ gpr_timespec timeout;
+ static const int max_spin_polling_us = 10;
+ if (gpr_time_cmp(deadline, gpr_inf_future) == 0) {
+ return -1;
+ }
+ if (gpr_time_cmp(
+ deadline,
+ gpr_time_add(now, gpr_time_from_micros(max_spin_polling_us))) <= 0) {
+ return 0;
+ }
+ timeout = gpr_time_sub(deadline, now);
+ return gpr_time_to_millis(
+ gpr_time_add(timeout, gpr_time_from_nanos(GPR_NS_PER_SEC - 1)));
+}
+
/*
* basic_pollset - a vtable that provides polling for zero or one file
* descriptor via poll()
@@ -344,15 +360,7 @@ static int basic_pollset_maybe_work(grpc_pollset *pollset,
GRPC_FD_UNREF(fd, "basicpoll");
fd = pollset->data.ptr = NULL;
}
- if (gpr_time_cmp(deadline, gpr_inf_future) == 0) {
- timeout = -1;
- } else {
- timeout = gpr_time_to_millis(
- gpr_time_add(gpr_time_sub(deadline, now), gpr_time_from_micros(500)));
- if (timeout < 0) {
- return 1;
- }
- }
+ timeout = grpc_poll_deadline_to_millis_timeout(deadline, now);
kfd = grpc_pollset_kick_pre_poll(&pollset->kick_state);
if (kfd == NULL) {
/* Already kicked */
diff --git a/src/core/iomgr/pollset_posix.h b/src/core/iomgr/pollset_posix.h
index 92c258e0cd..ba3d638d41 100644
--- a/src/core/iomgr/pollset_posix.h
+++ b/src/core/iomgr/pollset_posix.h
@@ -94,6 +94,15 @@ int grpc_kick_read_fd(grpc_pollset *p);
/* Call after polling has been kicked to leave the kicked state */
void grpc_kick_drain(grpc_pollset *p);
+/* Convert a timespec to milliseconds:
+ - very small or negative poll times are clamped to zero to do a
+ non-blocking poll (which becomes spin polling)
+ - other small values are rounded up to one millisecond
+ - longer than a millisecond polls are rounded up to the next nearest
+ millisecond to avoid spinning
+ - infinite timeouts are converted to -1 */
+int grpc_poll_deadline_to_millis_timeout(gpr_timespec deadline, gpr_timespec now);
+
/* turn a pollset into a multipoller: platform specific */
typedef void (*grpc_platform_become_multipoller_type)(grpc_pollset *pollset,
struct grpc_fd **fds,
diff --git a/src/core/iomgr/pollset_set.h b/src/core/iomgr/pollset_set.h
index 335ffb21b9..98e3b552a7 100644
--- a/src/core/iomgr/pollset_set.h
+++ b/src/core/iomgr/pollset_set.h
@@ -39,7 +39,7 @@
/* A grpc_pollset_set is a set of pollsets that are interested in an
action. Adding a pollset to a pollset_set automatically adds any
fd's (etc) that have been registered with the set_set with that pollset.
- Registering fd's automatically iterates all current pollsets. */
+ Registering fd's automatically adds them to all current pollsets. */
#ifdef GPR_POSIX_SOCKET
#include "src/core/iomgr/pollset_set_posix.h"
diff --git a/src/core/iomgr/tcp_client.h b/src/core/iomgr/tcp_client.h
index f40a5043c8..0fa08b52b0 100644
--- a/src/core/iomgr/tcp_client.h
+++ b/src/core/iomgr/tcp_client.h
@@ -41,7 +41,9 @@
/* Asynchronously connect to an address (specified as (addr, len)), and call
cb with arg and the completed connection when done (or call cb with arg and
- NULL on failure) */
+ NULL on failure).
+ interested_parties points to a set of pollsets that would be interested
+ in this connection being established (in order to continue their work) */
void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *tcp),
void *arg, grpc_pollset_set *interested_parties,
const struct sockaddr *addr, int addr_len,
diff --git a/src/core/iomgr/tcp_server_posix.c b/src/core/iomgr/tcp_server_posix.c
index 2ac35f863a..5854031c9b 100644
--- a/src/core/iomgr/tcp_server_posix.c
+++ b/src/core/iomgr/tcp_server_posix.c
@@ -108,6 +108,7 @@ struct grpc_tcp_server {
/* destroyed port count: how many ports are completely destroyed */
size_t destroyed_ports;
+ /* is this server shutting down? (boolean) */
int shutdown;
/* all listening ports */
@@ -119,7 +120,9 @@ struct grpc_tcp_server {
void (*shutdown_complete)(void *);
void *shutdown_complete_arg;
+ /* all pollsets interested in new connections */
grpc_pollset **pollsets;
+ /* number of pollsets in the pollsets array */
size_t pollset_count;
};
@@ -160,6 +163,9 @@ static void destroyed_port(void *server, int success) {
static void dont_care_about_shutdown_completion(void *ignored) {}
+/* called when all listening endpoints have been shutdown, so no further
+ events will be received on them - at this point it's safe to destroy
+ things */
static void deactivated_all_ports(grpc_tcp_server *s) {
size_t i;
diff --git a/src/core/security/client_auth_filter.c b/src/core/security/client_auth_filter.c
index d11706ece0..e9bd45db68 100644
--- a/src/core/security/client_auth_filter.c
+++ b/src/core/security/client_auth_filter.c
@@ -53,6 +53,10 @@ typedef struct {
grpc_credentials *creds;
grpc_mdstr *host;
grpc_mdstr *method;
+ /* pollset bound to this call; if we need to make external
+ network requests, they should be done under this pollset
+ so that work can progress when this call wants work to
+ progress */
grpc_pollset *pollset;
grpc_transport_op op;
size_t op_md_idx;
diff --git a/src/cpp/client/channel_arguments.cc b/src/cpp/client/channel_arguments.cc
index 87f8349eef..679c4f1503 100644
--- a/src/cpp/client/channel_arguments.cc
+++ b/src/cpp/client/channel_arguments.cc
@@ -34,6 +34,7 @@
#include <grpc++/channel_arguments.h>
#include <grpc/grpc_security.h>
+#include "src/core/channel/channel_args.h"
namespace grpc {
@@ -41,6 +42,10 @@ void ChannelArguments::SetSslTargetNameOverride(const grpc::string& name) {
SetString(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, name);
}
+void ChannelArguments::SetCompressionLevel(grpc_compression_level level) {
+ SetInt(GRPC_COMPRESSION_LEVEL_ARG, level);
+}
+
grpc::string ChannelArguments::GetSslTargetNameOverride() const {
for (unsigned int i = 0; i < args_.size(); i++) {
if (grpc::string(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == args_[i].key) {
diff --git a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
index 82ded5cc7a..21f94d3cf5 100644
--- a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
@@ -204,7 +204,7 @@ namespace Grpc.Core.Tests
BenchmarkUtil.RunBenchmark(100, 100,
() => { Calls.BlockingUnaryCall(call, "ABC", default(CancellationToken)); });
}
-
+
[Test]
public void UnknownMethodHandler()
{
diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m
index d92a9d1b37..a9625a1799 100644
--- a/src/objective-c/GRPCClient/GRPCCall.m
+++ b/src/objective-c/GRPCClient/GRPCCall.m
@@ -100,7 +100,9 @@ NSString * const kGRPCStatusMetadataKey = @"io.grpc.StatusMetadataKey";
if (!host || !method) {
[NSException raise:NSInvalidArgumentException format:@"Neither host nor method can be nil."];
}
- // TODO(jcanizales): Throw if the requestWriter was already started.
+ if (requestWriter.state != GRXWriterStateNotStarted) {
+ [NSException raise:NSInvalidArgumentException format:@"The requests writer can't be already started."];
+ }
if ((self = [super init])) {
static dispatch_once_t initialization;
dispatch_once(&initialization, ^{
diff --git a/src/objective-c/README.md b/src/objective-c/README.md
index 0e5eb9a25f..e997b76d14 100644
--- a/src/objective-c/README.md
+++ b/src/objective-c/README.md
@@ -163,7 +163,7 @@ files:
* [Podspec](https://github.com/grpc/grpc/blob/master/gRPC.podspec) for the Objective-C gRPC runtime
library. This can be tedious to configure manually.
-* [Podspec](https://github.com/jcanizales/protobuf/blob/add-podspec/Protobuf.podspec) for the
+* [Podspec](https://github.com/google/protobuf/blob/master/Protobuf.podspec) for the
Objective-C Protobuf runtime library.
[Protocol Buffers]:https://developers.google.com/protocol-buffers/
diff --git a/src/python/src/grpc/_adapter/_intermediary_low_test.py b/src/python/src/grpc/_adapter/_intermediary_low_test.py
index 478346341b..1a9b0c69f3 100644
--- a/src/python/src/grpc/_adapter/_intermediary_low_test.py
+++ b/src/python/src/grpc/_adapter/_intermediary_low_test.py
@@ -29,6 +29,8 @@
"""Tests for the old '_low'."""
+import Queue
+import threading
import time
import unittest
@@ -43,6 +45,7 @@ _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):
@@ -79,6 +82,14 @@ class LonelyClientTest(unittest.TestCase):
del completion_queue
+def _drive_completion_queue(completion_queue, event_queue):
+ while True:
+ event = completion_queue.get(_FUTURE)
+ if event.kind is _low.Event.Kind.STOP:
+ break
+ event_queue.put(event)
+
+
class EchoTest(unittest.TestCase):
def setUp(self):
@@ -88,24 +99,26 @@ class EchoTest(unittest.TestCase):
self.server = _low.Server(self.server_completion_queue)
port = self.server.add_http2_addr('[::]:0')
self.server.start()
+ self.server_events = Queue.Queue()
+ self.server_completion_queue_thread = threading.Thread(
+ target=_drive_completion_queue,
+ args=(self.server_completion_queue, self.server_events))
+ self.server_completion_queue_thread.start()
self.client_completion_queue = _low.CompletionQueue()
self.channel = _low.Channel('%s:%d' % (self.host, port), None)
+ self.client_events = Queue.Queue()
+ self.client_completion_queue_thread = threading.Thread(
+ target=_drive_completion_queue,
+ args=(self.client_completion_queue, self.client_events))
+ self.client_completion_queue_thread.start()
def tearDown(self):
self.server.stop()
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
+ self.server_completion_queue_thread.join()
+ self.client_completion_queue_thread.join()
del self.server
def _perform_echo_test(self, test_data):
@@ -144,7 +157,7 @@ class EchoTest(unittest.TestCase):
client_call.invoke(self.client_completion_queue, metadata_tag, finish_tag)
self.server.service(service_tag)
- service_accepted = self.server_completion_queue.get(_FUTURE)
+ service_accepted = self.server_events.get()
self.assertIsNotNone(service_accepted)
self.assertIs(service_accepted.kind, _low.Event.Kind.SERVICE_ACCEPTED)
self.assertIs(service_accepted.tag, service_tag)
@@ -165,7 +178,7 @@ class EchoTest(unittest.TestCase):
server_leading_binary_metadata_value)
server_call.premetadata()
- metadata_accepted = self.client_completion_queue.get(_FUTURE)
+ metadata_accepted = self.client_events.get()
self.assertIsNotNone(metadata_accepted)
self.assertEqual(_low.Event.Kind.METADATA_ACCEPTED, metadata_accepted.kind)
self.assertEqual(metadata_tag, metadata_accepted.tag)
@@ -179,14 +192,14 @@ class EchoTest(unittest.TestCase):
for datum in test_data:
client_call.write(datum, write_tag)
- write_accepted = self.client_completion_queue.get(_FUTURE)
+ write_accepted = self.client_events.get()
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)
+ read_accepted = self.server_events.get()
self.assertIsNotNone(read_accepted)
self.assertEqual(_low.Event.Kind.READ_ACCEPTED, read_accepted.kind)
self.assertEqual(read_tag, read_accepted.tag)
@@ -194,14 +207,14 @@ class EchoTest(unittest.TestCase):
server_data.append(read_accepted.bytes)
server_call.write(read_accepted.bytes, write_tag)
- write_accepted = self.server_completion_queue.get(_FUTURE)
+ write_accepted = self.server_events.get()
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)
+ read_accepted = self.client_events.get()
self.assertIsNotNone(read_accepted)
self.assertEqual(_low.Event.Kind.READ_ACCEPTED, read_accepted.kind)
self.assertEqual(read_tag, read_accepted.tag)
@@ -209,14 +222,14 @@ class EchoTest(unittest.TestCase):
client_data.append(read_accepted.bytes)
client_call.complete(complete_tag)
- complete_accepted = self.client_completion_queue.get(_FUTURE)
+ complete_accepted = self.client_events.get()
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)
+ read_accepted = self.server_events.get()
self.assertIsNotNone(read_accepted)
self.assertEqual(_low.Event.Kind.READ_ACCEPTED, read_accepted.kind)
self.assertEqual(read_tag, read_accepted.tag)
@@ -228,8 +241,8 @@ class EchoTest(unittest.TestCase):
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)
+ server_terminal_event_one = self.server_events.get()
+ server_terminal_event_two = self.server_events.get()
if server_terminal_event_one.kind == _low.Event.Kind.COMPLETE_ACCEPTED:
status_accepted = server_terminal_event_one
rpc_accepted = server_terminal_event_two
@@ -246,8 +259,8 @@ class EchoTest(unittest.TestCase):
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)
+ client_terminal_event_one = self.client_events.get()
+ client_terminal_event_two = self.client_events.get()
if client_terminal_event_one.kind == _low.Event.Kind.READ_ACCEPTED:
read_accepted = client_terminal_event_one
finish_accepted = client_terminal_event_two
@@ -303,22 +316,26 @@ class CancellationTest(unittest.TestCase):
self.server = _low.Server(self.server_completion_queue)
port = self.server.add_http2_addr('[::]:0')
self.server.start()
+ self.server_events = Queue.Queue()
+ self.server_completion_queue_thread = threading.Thread(
+ target=_drive_completion_queue,
+ args=(self.server_completion_queue, self.server_events))
+ self.server_completion_queue_thread.start()
self.client_completion_queue = _low.CompletionQueue()
self.channel = _low.Channel('%s:%d' % (self.host, port), None)
+ self.client_events = Queue.Queue()
+ self.client_completion_queue_thread = threading.Thread(
+ target=_drive_completion_queue,
+ args=(self.client_completion_queue, self.client_events))
+ self.client_completion_queue_thread.start()
def tearDown(self):
self.server.stop()
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
+ self.server_completion_queue_thread.join()
+ self.client_completion_queue_thread.join()
del self.server
def testCancellation(self):
@@ -340,29 +357,29 @@ class CancellationTest(unittest.TestCase):
client_call.invoke(self.client_completion_queue, metadata_tag, finish_tag)
self.server.service(service_tag)
- service_accepted = self.server_completion_queue.get(_FUTURE)
+ service_accepted = self.server_events.get()
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)
+ metadata_accepted = self.client_events.get()
self.assertIsNotNone(metadata_accepted)
for datum in test_data:
client_call.write(datum, write_tag)
- write_accepted = self.client_completion_queue.get(_FUTURE)
+ write_accepted = self.client_events.get()
server_call.read(read_tag)
- read_accepted = self.server_completion_queue.get(_FUTURE)
+ read_accepted = self.server_events.get()
server_data.append(read_accepted.bytes)
server_call.write(read_accepted.bytes, write_tag)
- write_accepted = self.server_completion_queue.get(_FUTURE)
+ write_accepted = self.server_events.get()
self.assertIsNotNone(write_accepted)
client_call.read(read_tag)
- read_accepted = self.client_completion_queue.get(_FUTURE)
+ read_accepted = self.client_events.get()
client_data.append(read_accepted.bytes)
client_call.cancel()
@@ -373,8 +390,8 @@ class CancellationTest(unittest.TestCase):
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)
+ server_terminal_event_one = self.server_events.get()
+ server_terminal_event_two = self.server_events.get()
if server_terminal_event_one.kind == _low.Event.Kind.READ_ACCEPTED:
read_accepted = server_terminal_event_one
rpc_accepted = server_terminal_event_two
@@ -388,7 +405,7 @@ class CancellationTest(unittest.TestCase):
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)
+ finish_event = self.client_events.get()
self.assertEqual(_low.Event.Kind.FINISH, finish_event.kind)
self.assertEqual(_low.Status(_low.Code.CANCELLED, 'Cancelled'),
finish_event.status)
diff --git a/src/ruby/.rspec b/src/ruby/.rspec
index dd579f7a13..cd7c5fb5b2 100755
--- a/src/ruby/.rspec
+++ b/src/ruby/.rspec
@@ -1,2 +1,4 @@
-I.
--require spec_helper
+--format documentation
+--color
diff --git a/src/ruby/spec/spec_helper.rb b/src/ruby/spec/spec_helper.rb
index 101165c146..270d2e97d3 100644
--- a/src/ruby/spec/spec_helper.rb
+++ b/src/ruby/spec/spec_helper.rb
@@ -53,3 +53,5 @@ RSpec.configure do |config|
include RSpec::LoggingHelper
config.capture_log_messages
end
+
+RSpec::Expectations.configuration.warn_about_potential_false_positives = false
diff --git a/templates/Makefile.template b/templates/Makefile.template
index c155b20a72..6347ad8440 100644
--- a/templates/Makefile.template
+++ b/templates/Makefile.template
@@ -665,7 +665,7 @@ else
endif
endif
$(Q)$(MAKE) -C third_party/openssl clean
- $(Q)$(MAKE) -C third_party/openssl build_crypto build_ssl
+ $(Q)(unset CPPFLAGS; $(MAKE) -C third_party/openssl build_crypto build_ssl)
$(Q)mkdir -p $(LIBDIR)/$(CONFIG)/openssl
$(Q)cp third_party/openssl/libssl.a third_party/openssl/libcrypto.a $(LIBDIR)/$(CONFIG)/openssl
diff --git a/templates/gRPC.podspec.template b/templates/gRPC.podspec.template
new file mode 100644
index 0000000000..84716c81e1
--- /dev/null
+++ b/templates/gRPC.podspec.template
@@ -0,0 +1,127 @@
+<%!
+bad_header_names = ('time.h', 'string.h')
+def fix_header_name(name):
+ split_name = name.split('/')
+ if split_name[-1] in bad_header_names:
+ return '/'.join(split_name[:-1] + ['grpc_' + split_name[-1]])
+ else:
+ return name
+%>
+
+Pod::Spec.new do |s|
+ s.name = 'gRPC'
+ s.version = '0.6.0'
+ s.summary = 'gRPC client library for iOS/OSX'
+ s.homepage = 'http://www.grpc.io'
+ s.license = 'New BSD'
+ s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' }
+
+ # 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'
+ s.requires_arc = true
+
+ # Reactive Extensions library for iOS.
+ s.subspec 'RxLibrary' do |rs|
+ rs.source_files = 'src/objective-c/RxLibrary/*.{h,m}',
+ 'src/objective-c/RxLibrary/transformations/*.{h,m}',
+ 'src/objective-c/RxLibrary/private/*.{h,m}'
+ rs.private_header_files = 'src/objective-c/RxLibrary/private/*.h'
+ end
+
+ # Core cross-platform gRPC library, written in C.
+ s.subspec 'C-Core' do |cs|
+ cs.source_files = \
+% for lib in libs:
+% if lib.name in ("grpc", "gpr"):
+% for hdr in lib.get("headers", []):
+'${fix_header_name(hdr)}', \
+% endfor
+% for hdr in lib.get("public_headers", []):
+'${fix_header_name(hdr)}', \
+% endfor
+% for src in lib.src:
+'${src}', \
+% endfor
+% endif
+% endfor
+
+ cs.private_header_files = \
+% for lib in libs:
+% if lib.name in ("grpc", "gpr"):
+% for hdr in lib.get("headers", []):
+'${hdr}', \
+% endfor
+% endif
+% endfor
+
+ cs.header_mappings_dir = '.'
+ # The core library includes its headers as either "src/core/..." or "grpc/...", meaning we have
+ # to tell XCode to look for headers under the "include" subdirectory too.
+ #
+ # TODO(jcanizales): Instead of doing this, during installation move everything under
+ # "include/grpc" one directory up. The directory names under PODS_ROOT are implementation
+ # details of Cocoapods, and have changed in the past, breaking this podspec.
+ cs.xcconfig = { 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/Headers/Private/gRPC" ' +
+ '"$(PODS_ROOT)/Headers/Private/gRPC/include"' }
+ cs.compiler_flags = '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w'
+
+ cs.requires_arc = false
+ cs.libraries = 'z'
+ cs.dependency 'OpenSSL', '~> 1.0.200'
+ end
+
+ # This is a workaround for Cocoapods Issue #1437.
+ # It renames time.h and string.h to grpc_time.h and grpc_string.h.
+ # It needs to be here (top-level) instead of in the C-Core subspec because Cocoapods doesn't run
+ # prepare_command's of subspecs.
+ #
+ # TODO(jcanizales): Try out Todd Reed's solution at Issue #1437.
+ s.prepare_command = <<-CMD
+ DIR_TIME="grpc/support"
+ BAD_TIME="$DIR_TIME/time.h"
+ GOOD_TIME="$DIR_TIME/grpc_time.h"
+ grep -rl "$BAD_TIME" include/grpc src/core | xargs sed -i '' -e s@$BAD_TIME@$GOOD_TIME@g
+ if [ -f "include/$BAD_TIME" ];
+ then
+ mv -f "include/$BAD_TIME" "include/$GOOD_TIME"
+ fi
+
+ DIR_STRING="src/core/support"
+ BAD_STRING="$DIR_STRING/string.h"
+ GOOD_STRING="$DIR_STRING/grpc_string.h"
+ grep -rl "$BAD_STRING" include/grpc src/core | xargs sed -i '' -e s@$BAD_STRING@$GOOD_STRING@g
+ if [ -f "$BAD_STRING" ];
+ then
+ mv -f "$BAD_STRING" "$GOOD_STRING"
+ fi
+ CMD
+
+ # Objective-C wrapper around the core gRPC library.
+ s.subspec 'GRPCClient' do |gs|
+ gs.source_files = 'src/objective-c/GRPCClient/*.{h,m}',
+ 'src/objective-c/GRPCClient/private/*.{h,m}'
+ gs.private_header_files = 'src/objective-c/GRPCClient/private/*.h'
+ gs.compiler_flags = '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w'
+
+ gs.dependency 'gRPC/C-Core'
+ # TODO(jcanizales): Remove this when the prepare_command moves everything under "include/grpc"
+ # one directory up.
+ gs.xcconfig = { 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/Headers/Public/gRPC/include"' }
+ gs.dependency 'gRPC/RxLibrary'
+
+ # Certificates, to be able to establish TLS connections:
+ gs.resource_bundles = { 'gRPC' => ['etc/roots.pem'] }
+ end
+
+ # RPC library for ProtocolBuffers, based on gRPC
+ s.subspec 'ProtoRPC' do |ps|
+ ps.source_files = 'src/objective-c/ProtoRPC/*.{h,m}'
+
+ ps.dependency 'gRPC/GRPCClient'
+ ps.dependency 'gRPC/RxLibrary'
+ ps.dependency 'Protobuf', '~> 3.0.0-alpha-3'
+ end
+end
diff --git a/test/cpp/util/cli_call.cc b/test/cpp/util/cli_call.cc
index fa952e8349..83a7a1744a 100644
--- a/test/cpp/util/cli_call.cc
+++ b/test/cpp/util/cli_call.cc
@@ -52,11 +52,20 @@ namespace {
void* tag(int i) { return (void*)(gpr_intptr) i; }
} // namespace
-void CliCall::Call(std::shared_ptr<grpc::ChannelInterface> channel,
- const grpc::string& method, const grpc::string& request,
- grpc::string* response) {
+Status CliCall::Call(std::shared_ptr<grpc::ChannelInterface> channel,
+ const grpc::string& method, const grpc::string& request,
+ grpc::string* response, const MetadataContainer& metadata,
+ MetadataContainer* server_initial_metadata,
+ MetadataContainer* server_trailing_metadata) {
std::unique_ptr<grpc::GenericStub> stub(new grpc::GenericStub(channel));
grpc::ClientContext ctx;
+ if (!metadata.empty()) {
+ for (std::multimap<grpc::string, grpc::string>::const_iterator iter =
+ metadata.begin();
+ iter != metadata.end(); ++iter) {
+ ctx.AddMetadata(iter->first, iter->second);
+ }
+ }
grpc::CompletionQueue cq;
std::unique_ptr<grpc::GenericClientAsyncReaderWriter> call(
stub->Call(&ctx, method, &cq, tag(1)));
@@ -79,7 +88,7 @@ void CliCall::Call(std::shared_ptr<grpc::ChannelInterface> channel,
cq.Next(&got_tag, &ok);
if (!ok) {
std::cout << "Failed to read response." << std::endl;
- return;
+ return Status(StatusCode::INTERNAL, "Failed to read response");
}
grpc::Status status;
call->Finish(&status, tag(5));
@@ -87,7 +96,6 @@ void CliCall::Call(std::shared_ptr<grpc::ChannelInterface> channel,
GPR_ASSERT(ok);
if (status.ok()) {
- std::cout << "RPC finished with OK status." << std::endl;
std::vector<grpc::Slice> slices;
recv_buffer.Dump(&slices);
@@ -96,10 +104,10 @@ void CliCall::Call(std::shared_ptr<grpc::ChannelInterface> channel,
response->append(reinterpret_cast<const char*>(slices[i].begin()),
slices[i].size());
}
- } else {
- std::cout << "RPC finished with status code " << status.error_code()
- << " details: " << status.error_message() << std::endl;
}
+ *server_initial_metadata = ctx.GetServerInitialMetadata();
+ *server_trailing_metadata = ctx.GetServerTrailingMetadata();
+ return status;
}
} // namespace testing
diff --git a/test/cpp/util/cli_call.h b/test/cpp/util/cli_call.h
index 7be8bb63c4..8d114c9cb5 100644
--- a/test/cpp/util/cli_call.h
+++ b/test/cpp/util/cli_call.h
@@ -34,17 +34,23 @@
#ifndef GRPC_TEST_CPP_UTIL_CLI_CALL_H
#define GRPC_TEST_CPP_UTIL_CLI_CALL_H
+#include <map>
+
#include <grpc++/channel_interface.h>
#include <grpc++/config.h>
+#include <grpc++/status.h>
namespace grpc {
namespace testing {
class CliCall GRPC_FINAL {
public:
- static void Call(std::shared_ptr<grpc::ChannelInterface> channel,
- const grpc::string& method, const grpc::string& request,
- grpc::string* response);
+ typedef std::multimap<grpc::string, grpc::string> MetadataContainer;
+ static Status Call(std::shared_ptr<grpc::ChannelInterface> channel,
+ const grpc::string& method, const grpc::string& request,
+ grpc::string* response, const MetadataContainer& metadata,
+ MetadataContainer* server_initial_metadata,
+ MetadataContainer* server_trailing_metadata);
};
} // namespace testing
diff --git a/test/cpp/util/cli_call_test.cc b/test/cpp/util/cli_call_test.cc
index 12539c7479..6cf86ea89b 100644
--- a/test/cpp/util/cli_call_test.cc
+++ b/test/cpp/util/cli_call_test.cc
@@ -60,6 +60,14 @@ class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service {
public:
Status Echo(ServerContext* context, const EchoRequest* request,
EchoResponse* response) GRPC_OVERRIDE {
+ if (!context->client_metadata().empty()) {
+ for (std::multimap<grpc::string, grpc::string>::const_iterator iter =
+ context->client_metadata().begin();
+ iter != context->client_metadata().end(); ++iter) {
+ context->AddInitialMetadata(iter->first, iter->second);
+ }
+ }
+ context->AddTrailingMetadata("trailing_key", "trailing_value");
response->set_message(request->message());
return Status::OK;
}
@@ -106,6 +114,7 @@ TEST_F(CliCallTest, SimpleRpc) {
request.set_message("Hello");
ClientContext context;
+ context.AddMetadata("key1", "val1");
Status s = stub_->Echo(&context, request, &response);
EXPECT_EQ(response.message(), request.message());
EXPECT_TRUE(s.ok());
@@ -114,8 +123,17 @@ TEST_F(CliCallTest, SimpleRpc) {
grpc::string request_bin, response_bin, expected_response_bin;
EXPECT_TRUE(request.SerializeToString(&request_bin));
EXPECT_TRUE(response.SerializeToString(&expected_response_bin));
- CliCall::Call(channel_, kMethod, request_bin, &response_bin);
+ std::multimap<grpc::string, grpc::string> client_metadata,
+ server_initial_metadata, server_trailing_metadata;
+ client_metadata.insert(std::pair<grpc::string, grpc::string>("key1", "val1"));
+ Status s2 = CliCall::Call(channel_, kMethod, request_bin, &response_bin,
+ client_metadata, &server_initial_metadata,
+ &server_trailing_metadata);
+ EXPECT_TRUE(s2.ok());
+
EXPECT_EQ(expected_response_bin, response_bin);
+ EXPECT_EQ(context.GetServerInitialMetadata(), server_initial_metadata);
+ EXPECT_EQ(context.GetServerTrailingMetadata(), server_trailing_metadata);
}
} // namespace testing
diff --git a/test/cpp/util/grpc_cli.cc b/test/cpp/util/grpc_cli.cc
index ad3c0af877..32d61b0307 100644
--- a/test/cpp/util/grpc_cli.cc
+++ b/test/cpp/util/grpc_cli.cc
@@ -41,8 +41,8 @@
body: "hello world"
}
b. under grpc/ run
- protoc --proto_path=test/cpp/interop/ \
- --encode=grpc.testing.SimpleRequest test/cpp/interop/messages.proto \
+ protoc --proto_path=test/proto/ \
+ --encode=grpc.testing.SimpleRequest test/proto/messages.proto \
< input.txt > input.bin
2. Start a server
make interop_server && bins/opt/interop_server --port=50051
@@ -51,10 +51,12 @@
/grpc.testing.TestService/UnaryCall --enable_ssl=false \
--input_binary_file=input.bin --output_binary_file=output.bin
4. Decode response
- protoc --proto_path=test/cpp/interop/ \
- --decode=grpc.testing.SimpleResponse test/cpp/interop/messages.proto \
+ protoc --proto_path=test/proto/ \
+ --decode=grpc.testing.SimpleResponse test/proto/messages.proto \
< output.bin > output.txt
5. Now the text form of response should be in output.txt
+ Optionally, metadata can be passed to server via flag --metadata, e.g.
+ --metadata="MyHeaderKey1:Value1:MyHeaderKey2:Value2"
*/
#include <fstream>
@@ -77,6 +79,44 @@ DEFINE_string(input_binary_file, "",
"Path to input file containing serialized request.");
DEFINE_string(output_binary_file, "output.bin",
"Path to output file to write serialized response.");
+DEFINE_string(metadata, "",
+ "Metadata to send to server, in the form of key1:val1:key2:val2");
+
+void ParseMetadataFlag(
+ std::multimap<grpc::string, grpc::string>* client_metadata) {
+ if (FLAGS_metadata.empty()) {
+ return;
+ }
+ std::vector<grpc::string> fields;
+ grpc::string delim(":");
+ size_t cur, next = -1;
+ do {
+ cur = next + 1;
+ next = FLAGS_metadata.find_first_of(delim, cur);
+ fields.push_back(FLAGS_metadata.substr(cur, next - cur));
+ } while (next != grpc::string::npos);
+ if (fields.size() % 2) {
+ std::cout << "Failed to parse metadata flag" << std::endl;
+ exit(1);
+ }
+ for (size_t i = 0; i < fields.size(); i += 2) {
+ client_metadata->insert(
+ std::pair<grpc::string, grpc::string>(fields[i], fields[i + 1]));
+ }
+}
+
+void PrintMetadata(const std::multimap<grpc::string, grpc::string>& m,
+ const grpc::string& message) {
+ if (m.empty()) {
+ return;
+ }
+ std::cout << message << std::endl;
+ for (std::multimap<grpc::string, grpc::string>::const_iterator iter =
+ m.begin();
+ iter != m.end(); ++iter) {
+ std::cout << iter->first << " : " << iter->second << std::endl;
+ }
+}
int main(int argc, char** argv) {
grpc::testing::InitTest(&argc, &argv, true);
@@ -118,11 +158,27 @@ int main(int argc, char** argv) {
grpc::CreateChannel(server_address, creds, grpc::ChannelArguments());
grpc::string response;
- grpc::testing::CliCall::Call(channel, method, input_stream.str(), &response);
- if (!response.empty()) {
- std::ofstream output_file(FLAGS_output_binary_file,
- std::ios::trunc | std::ios::binary);
- output_file << response;
+ std::multimap<grpc::string, grpc::string> client_metadata,
+ server_initial_metadata, server_trailing_metadata;
+ ParseMetadataFlag(&client_metadata);
+ PrintMetadata(client_metadata, "Sending client initial metadata:");
+ grpc::Status s = grpc::testing::CliCall::Call(
+ channel, method, input_stream.str(), &response, client_metadata,
+ &server_initial_metadata, &server_trailing_metadata);
+ PrintMetadata(server_initial_metadata,
+ "Received initial metadata from server:");
+ PrintMetadata(server_trailing_metadata,
+ "Received trailing metadata from server:");
+ if (s.ok()) {
+ std::cout << "Rpc succeeded with OK status" << std::endl;
+ if (!response.empty()) {
+ std::ofstream output_file(FLAGS_output_binary_file,
+ std::ios::trunc | std::ios::binary);
+ output_file << response;
+ }
+ } else {
+ std::cout << "Rpc failed with status code " << s.error_code()
+ << " error message " << s.error_message() << std::endl;
}
return 0;
diff --git a/tools/jenkins/grpc_jenkins_slave/Dockerfile b/tools/jenkins/grpc_jenkins_slave/Dockerfile
index b12c309e87..a9226c63cc 100644
--- a/tools/jenkins/grpc_jenkins_slave/Dockerfile
+++ b/tools/jenkins/grpc_jenkins_slave/Dockerfile
@@ -116,6 +116,9 @@ RUN apt-get update && apt-get install -y \
# Install Python packages from PyPI
RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.0.0a2
+# For sanity test
+RUN pip install simplejson mako
+
##################
# PHP dependencies
diff --git a/tools/jenkins/run_jenkins.sh b/tools/jenkins/run_jenkins.sh
index 763a930dd8..534ed306ef 100755
--- a/tools/jenkins/run_jenkins.sh
+++ b/tools/jenkins/run_jenkins.sh
@@ -41,6 +41,12 @@ if [ "$platform" == "linux" ]
then
echo "building $language on Linux"
+ # Use image name based on Dockerfile checksum
+ DOCKER_IMAGE_NAME=grpc_jenkins_slave_`sha1sum tools/jenkins/grpc_jenkins_slave/Dockerfile | cut -f1 -d\ `
+
+ # Make sure docker image has been built. Should be instantaneous if so.
+ docker build -t $DOCKER_IMAGE_NAME tools/jenkins/grpc_jenkins_slave
+
if [ "$ghprbPullId" != "" ]
then
# if we are building a pull request, grab corresponding refs.
@@ -51,12 +57,11 @@ then
rm -f docker.cid
# Run tests inside docker
- docker run --cidfile=docker.cid grpc/grpc_jenkins_slave bash -c -l "git clone --recursive $GIT_URL /var/local/git/grpc \
+ docker run --cidfile=docker.cid $DOCKER_IMAGE_NAME bash -c -l "git clone --recursive $GIT_URL /var/local/git/grpc \
&& cd /var/local/git/grpc \
$FETCH_PULL_REQUEST_CMD \
&& git checkout -f $GIT_COMMIT \
&& git submodule update \
- && pip install simplejson mako \
&& nvm use 0.12 \
&& rvm use ruby-2.1 \
&& CONFIG=$config tools/run_tests/prepare_travis.sh \
@@ -69,7 +74,7 @@ then
docker rm $DOCKER_CID
else
echo "Docker exited with failure, keeping container $DOCKER_CID."
- echo "You can SSH to the worker and use 'docker start CID' and 'docker exec -i -t CID bash' to debug the problem."
+ echo "You can SSH to the worker and use 'docker commit CID YOUR_IMAGE_NAME' and 'docker run -i -t YOUR_IMAGE_NAME bash' to debug the problem."
exit 1
fi