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