Implemented compression level algorithms properly (as a function of the accepted algorithms by the call's peer.

pull/5819/head
David Garcia Quintas 9 years ago
parent 921f4b0a6e
commit 13c2f6e69d
  1. 6
      include/grpc/compression.h
  2. 46
      src/core/compression/compression_algorithm.c
  3. 6
      src/core/surface/call.c
  4. 9
      src/core/surface/call.h
  5. 3
      src/cpp/server/server_context.cc
  6. 102
      test/core/compression/compression_test.c

@ -55,11 +55,13 @@ GRPCAPI int grpc_compression_algorithm_parse(
GRPCAPI int grpc_compression_algorithm_name( GRPCAPI int grpc_compression_algorithm_name(
grpc_compression_algorithm algorithm, char **name); grpc_compression_algorithm algorithm, char **name);
/** Returns the compression algorithm corresponding to \a level. /** Returns the compression algorithm corresponding to \a level for the
* compression algorithms encoded in the \a accepted_encodings bitset.
* *
* It abort()s for unknown levels . */ * It abort()s for unknown levels . */
GRPCAPI grpc_compression_algorithm GRPCAPI grpc_compression_algorithm
grpc_compression_algorithm_for_level(grpc_compression_level level); grpc_compression_algorithm_for_level(grpc_compression_level level,
uint32_t accepted_encodings);
GRPCAPI void grpc_compression_options_init(grpc_compression_options *opts); GRPCAPI void grpc_compression_options_init(grpc_compression_options *opts);

@ -128,20 +128,56 @@ grpc_mdelem *grpc_compression_encoding_mdelem(
/* TODO(dgq): Add the ability to specify parameters to the individual /* TODO(dgq): Add the ability to specify parameters to the individual
* compression algorithms */ * compression algorithms */
grpc_compression_algorithm grpc_compression_algorithm_for_level( grpc_compression_algorithm grpc_compression_algorithm_for_level(
grpc_compression_level level) { grpc_compression_level level, uint32_t accepted_encodings) {
GRPC_API_TRACE("grpc_compression_algorithm_for_level(level=%d)", 1, GRPC_API_TRACE("grpc_compression_algorithm_for_level(level=%d)", 1,
((int)level)); ((int)level));
if (level > GRPC_COMPRESS_LEVEL_HIGH) {
gpr_log(GPR_ERROR, "Unknown compression level %d.", (int)level);
abort();
}
const size_t num_supported =
GPR_BITCOUNT(accepted_encodings) - 1; /* discard NONE */
if (level == GRPC_COMPRESS_LEVEL_NONE || num_supported == 0) {
return GRPC_COMPRESS_NONE;
}
GPR_ASSERT(level > 0);
/* Establish a "ranking" or compression algorithms in increasing order of
* compression.
* This is simplistic and we will probably want to introduce other dimensions
* in the future (cpu/memory cost, etc). */
const grpc_compression_algorithm algos_ranking[] = {GRPC_COMPRESS_GZIP,
GRPC_COMPRESS_DEFLATE};
/* intersect algos_ranking with the supported ones keeping the ranked order */
grpc_compression_algorithm sorted_supported_algos[num_supported];
size_t algos_supported_idx = 0;
for (size_t i = 0; i < GPR_ARRAY_SIZE(algos_ranking); i++) {
const grpc_compression_algorithm alg = algos_ranking[i];
for (size_t j = 0; j < num_supported; j++) {
if (GPR_BITGET(accepted_encodings, alg) == 1) {
/* if \a alg in supported */
sorted_supported_algos[algos_supported_idx++] = alg;
break;
}
}
if (algos_supported_idx == num_supported) break;
}
switch (level) { switch (level) {
case GRPC_COMPRESS_LEVEL_NONE: case GRPC_COMPRESS_LEVEL_NONE:
return GRPC_COMPRESS_NONE; abort(); /* should have been handled already */
case GRPC_COMPRESS_LEVEL_LOW: case GRPC_COMPRESS_LEVEL_LOW:
return sorted_supported_algos[0];
case GRPC_COMPRESS_LEVEL_MED: case GRPC_COMPRESS_LEVEL_MED:
return sorted_supported_algos[num_supported / 2];
case GRPC_COMPRESS_LEVEL_HIGH: case GRPC_COMPRESS_LEVEL_HIGH:
return GRPC_COMPRESS_DEFLATE; return sorted_supported_algos[num_supported - 1];
default: default:
gpr_log(GPR_ERROR, "Unknown compression level %d.", (int)level);
abort(); abort();
} };
} }
void grpc_compression_options_init(grpc_compression_options *opts) { void grpc_compression_options_init(grpc_compression_options *opts) {

@ -1481,3 +1481,9 @@ void *grpc_call_context_get(grpc_call *call, grpc_context_index elem) {
} }
uint8_t grpc_call_is_client(grpc_call *call) { return call->is_client; } uint8_t grpc_call_is_client(grpc_call *call) { return call->is_client; }
grpc_compression_algorithm grpc_call_compression_for_level(
grpc_call *call, grpc_compression_level level) {
return grpc_compression_algorithm_for_level(level,
call->encodings_accepted_by_peer);
}

@ -1,6 +1,6 @@
/* /*
* *
* Copyright 2015, Google Inc. * Copyright 2015-2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -38,7 +38,9 @@
#include "src/core/channel/context.h" #include "src/core/channel/context.h"
#include "src/core/surface/api_trace.h" #include "src/core/surface/api_trace.h"
#include "src/core/surface/surface_trace.h" #include "src/core/surface/surface_trace.h"
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/impl/codegen/compression_types.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -102,6 +104,11 @@ void *grpc_call_context_get(grpc_call *call, grpc_context_index elem);
uint8_t grpc_call_is_client(grpc_call *call); uint8_t grpc_call_is_client(grpc_call *call);
/* Return an appropriate compression algorithm for the requested compression \a
* level in the context of \a call. */
grpc_compression_algorithm grpc_call_compression_for_level(
grpc_call *call, grpc_compression_level level);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -43,6 +43,7 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include "src/core/channel/compress_filter.h" #include "src/core/channel/compress_filter.h"
#include "src/core/surface/call.h"
#include "src/cpp/common/create_auth_context.h" #include "src/cpp/common/create_auth_context.h"
namespace grpc { namespace grpc {
@ -197,7 +198,7 @@ bool ServerContext::IsCancelled() const {
void ServerContext::set_compression_level(grpc_compression_level level) { void ServerContext::set_compression_level(grpc_compression_level level) {
const grpc_compression_algorithm algorithm_for_level = const grpc_compression_algorithm algorithm_for_level =
grpc_compression_algorithm_for_level(level); grpc_call_compression_for_level(call_, level);
set_compression_algorithm(algorithm_for_level); set_compression_algorithm(algorithm_for_level);
} }

@ -1,6 +1,6 @@
/* /*
* *
* Copyright 2015, Google Inc. * Copyright 2015-2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -93,18 +93,98 @@ static void test_compression_algorithm_name(void) {
} }
static void test_compression_algorithm_for_level(void) { static void test_compression_algorithm_for_level(void) {
size_t i;
grpc_compression_level levels[] = {
GRPC_COMPRESS_LEVEL_NONE, GRPC_COMPRESS_LEVEL_LOW,
GRPC_COMPRESS_LEVEL_MED, GRPC_COMPRESS_LEVEL_HIGH};
grpc_compression_algorithm algorithms[] = {
GRPC_COMPRESS_NONE, GRPC_COMPRESS_DEFLATE, GRPC_COMPRESS_DEFLATE,
GRPC_COMPRESS_DEFLATE};
gpr_log(GPR_DEBUG, "test_compression_algorithm_for_level"); gpr_log(GPR_DEBUG, "test_compression_algorithm_for_level");
for (i = 0; i < GPR_ARRAY_SIZE(levels); i++) { {
GPR_ASSERT(algorithms[i] == /* accept only identity (aka none) */
grpc_compression_algorithm_for_level(levels[i])); uint32_t accepted_encodings = 0;
GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */
GPR_ASSERT(GRPC_COMPRESS_NONE ==
grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_NONE,
accepted_encodings));
GPR_ASSERT(GRPC_COMPRESS_NONE ==
grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_LOW,
accepted_encodings));
GPR_ASSERT(GRPC_COMPRESS_NONE ==
grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_MED,
accepted_encodings));
GPR_ASSERT(GRPC_COMPRESS_NONE ==
grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_HIGH,
accepted_encodings));
}
{
/* accept only gzip */
uint32_t accepted_encodings = 0;
GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */
GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_GZIP);
GPR_ASSERT(GRPC_COMPRESS_NONE ==
grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_NONE,
accepted_encodings));
GPR_ASSERT(GRPC_COMPRESS_GZIP ==
grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_LOW,
accepted_encodings));
GPR_ASSERT(GRPC_COMPRESS_GZIP ==
grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_MED,
accepted_encodings));
GPR_ASSERT(GRPC_COMPRESS_GZIP ==
grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_HIGH,
accepted_encodings));
}
{
/* accept only deflate */
uint32_t accepted_encodings = 0;
GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */
GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_DEFLATE);
GPR_ASSERT(GRPC_COMPRESS_NONE ==
grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_NONE,
accepted_encodings));
GPR_ASSERT(GRPC_COMPRESS_DEFLATE ==
grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_LOW,
accepted_encodings));
GPR_ASSERT(GRPC_COMPRESS_DEFLATE ==
grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_MED,
accepted_encodings));
GPR_ASSERT(GRPC_COMPRESS_DEFLATE ==
grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_HIGH,
accepted_encodings));
}
{
/* accept gzip and deflate */
uint32_t accepted_encodings = 0;
GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_NONE); /* always */
GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_GZIP);
GPR_BITSET(&accepted_encodings, GRPC_COMPRESS_DEFLATE);
GPR_ASSERT(GRPC_COMPRESS_NONE ==
grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_NONE,
accepted_encodings));
GPR_ASSERT(GRPC_COMPRESS_GZIP ==
grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_LOW,
accepted_encodings));
GPR_ASSERT(GRPC_COMPRESS_DEFLATE ==
grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_MED,
accepted_encodings));
GPR_ASSERT(GRPC_COMPRESS_DEFLATE ==
grpc_compression_algorithm_for_level(GRPC_COMPRESS_LEVEL_HIGH,
accepted_encodings));
} }
} }

Loading…
Cancel
Save