diff --git a/Makefile b/Makefile index f3b7b9756910b460fbfd47725b5bc3e04d77e111..dcfca65e2d860936366fa3540198fe711b742822 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/include/grpc++/channel_arguments.h b/include/grpc++/channel_arguments.h index 8d338c654ec5ae171e914ce36ddba04db561031d..68f24cde4af1e76ffc58ce1fc3ce24575df534f0 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 968a7570606fe3df899e8adde5f689f9daf4fe52..61bce05b5091355319787aa273f088ebfa08344c 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 27676632c138a47f1d5b3db1459e20f8e99f022d..9272673cabed0418d7feb937a8529826dcdcb1f9 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 1b0e33b1232f72e12d5b3a3055c8690ca0a9ff54..166d559a456b84487293530d4c618c40b725054a 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 eb5bf63986a6990118140cff9166d56840342ff3..bf747b26e645bad69731f379bdcd8c54382317fb 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/compression/algorithm.c b/src/core/compression/algorithm.c index 36ead843d26f666396691b01e21e22e8af57c0e9..4db48df6cbf14187c511b5fa38ad1fa937381d1f 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/cpp/client/channel_arguments.cc b/src/cpp/client/channel_arguments.cc index 87f8349eefd28278de0c0367a85687917bed6ca2..679c4f1503d7ad05f8ecd94e697739811ed272f8 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/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index d92a9d1b377fb77014541df9a015e1366a1eb80b..a9625a179973daba0816344ad708f2dd2b98054e 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/ruby/.rspec b/src/ruby/.rspec index dd579f7a1373cdf7f67110df61c8f3e8de4be97b..cd7c5fb5b2120f488382529ca86d220c985f5662 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 101165c146fb083075391843f04472a13129bc09..270d2e97d32b4fa5791f03abc59b5f584a202573 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 c155b20a722fb02109a09ab6c5193101e4570430..6347ad8440f7dad0c5b1f99a79cb906dab633171 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/tools/jenkins/grpc_jenkins_slave/Dockerfile b/tools/jenkins/grpc_jenkins_slave/Dockerfile index b12c309e876ca47f181f7331f3e6ed20c30befb5..a9226c63cc783e60264b19e0ecb2e80318b674fb 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 763a930dd8ca4ddef050d86e3ec200a3e14908a6..534ed306ef38d2a65e30384c37b11b4400468711 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