aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2016-03-18 15:57:49 -0700
committerGravatar Craig Tiller <ctiller@google.com>2016-03-18 15:57:49 -0700
commit58270d546137c3e7335e34a44bf272c4a460f40a (patch)
tree6d41ba335211741ccfca6065c01d34c65fd581f6
parent80551afb6c8791ed6648e291731ee18e8e65c238 (diff)
Revert "Revert "Factor out backoff code into a separate library (to be re-used elsewhere)""
-rw-r--r--BUILD4
-rw-r--r--Makefile37
-rw-r--r--binding.gyp1
-rw-r--r--build.yaml12
-rw-r--r--config.m41
-rw-r--r--gRPC.podspec3
-rwxr-xr-xgrpc.gemspec2
-rw-r--r--package.json2
-rw-r--r--package.xml2
-rw-r--r--src/core/client_config/subchannel.c86
-rw-r--r--src/core/support/backoff.c71
-rw-r--r--src/core/support/backoff.h65
-rw-r--r--src/python/grpcio/grpc_core_dependencies.py1
-rw-r--r--test/core/support/backoff_test.c107
-rw-r--r--tools/doxygen/Doxyfile.core.internal2
-rw-r--r--tools/run_tests/sources_and_headers.json17
-rw-r--r--tools/run_tests/tests.json23
-rw-r--r--vsprojects/buildtests_c.sln25
-rw-r--r--vsprojects/vcxproj/gpr/gpr.vcxproj3
-rw-r--r--vsprojects/vcxproj/gpr/gpr.vcxproj.filters6
-rw-r--r--vsprojects/vcxproj/test/gpr_backoff_test/gpr_backoff_test.vcxproj193
-rw-r--r--vsprojects/vcxproj/test/gpr_backoff_test/gpr_backoff_test.vcxproj.filters21
22 files changed, 619 insertions, 65 deletions
diff --git a/BUILD b/BUILD
index 06c3f61e1d..659e79a1e0 100644
--- a/BUILD
+++ b/BUILD
@@ -45,6 +45,7 @@ cc_library(
name = "gpr",
srcs = [
"src/core/profiling/timers.h",
+ "src/core/support/backoff.h",
"src/core/support/block_annotate.h",
"src/core/support/env.h",
"src/core/support/load_file.h",
@@ -59,6 +60,7 @@ cc_library(
"src/core/profiling/stap_timers.c",
"src/core/support/alloc.c",
"src/core/support/avl.c",
+ "src/core/support/backoff.c",
"src/core/support/cmdline.c",
"src/core/support/cpu_iphone.c",
"src/core/support/cpu_linux.c",
@@ -1233,6 +1235,7 @@ objc_library(
"src/core/profiling/stap_timers.c",
"src/core/support/alloc.c",
"src/core/support/avl.c",
+ "src/core/support/backoff.c",
"src/core/support/cmdline.c",
"src/core/support/cpu_iphone.c",
"src/core/support/cpu_linux.c",
@@ -1317,6 +1320,7 @@ objc_library(
"include/grpc/impl/codegen/sync_win32.h",
"include/grpc/impl/codegen/time.h",
"src/core/profiling/timers.h",
+ "src/core/support/backoff.h",
"src/core/support/block_annotate.h",
"src/core/support/env.h",
"src/core/support/load_file.h",
diff --git a/Makefile b/Makefile
index 0659fb1466..44a4b12bac 100644
--- a/Makefile
+++ b/Makefile
@@ -893,6 +893,7 @@ fling_test: $(BINDIR)/$(CONFIG)/fling_test
gen_hpack_tables: $(BINDIR)/$(CONFIG)/gen_hpack_tables
gen_legal_metadata_characters: $(BINDIR)/$(CONFIG)/gen_legal_metadata_characters
gpr_avl_test: $(BINDIR)/$(CONFIG)/gpr_avl_test
+gpr_backoff_test: $(BINDIR)/$(CONFIG)/gpr_backoff_test
gpr_cmdline_test: $(BINDIR)/$(CONFIG)/gpr_cmdline_test
gpr_cpu_test: $(BINDIR)/$(CONFIG)/gpr_cpu_test
gpr_env_test: $(BINDIR)/$(CONFIG)/gpr_env_test
@@ -1204,6 +1205,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/fling_stream_test \
$(BINDIR)/$(CONFIG)/fling_test \
$(BINDIR)/$(CONFIG)/gpr_avl_test \
+ $(BINDIR)/$(CONFIG)/gpr_backoff_test \
$(BINDIR)/$(CONFIG)/gpr_cmdline_test \
$(BINDIR)/$(CONFIG)/gpr_cpu_test \
$(BINDIR)/$(CONFIG)/gpr_env_test \
@@ -1458,6 +1460,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/fling_test || ( echo test fling_test failed ; exit 1 )
$(E) "[RUN] Testing gpr_avl_test"
$(Q) $(BINDIR)/$(CONFIG)/gpr_avl_test || ( echo test gpr_avl_test failed ; exit 1 )
+ $(E) "[RUN] Testing gpr_backoff_test"
+ $(Q) $(BINDIR)/$(CONFIG)/gpr_backoff_test || ( echo test gpr_backoff_test failed ; exit 1 )
$(E) "[RUN] Testing gpr_cmdline_test"
$(Q) $(BINDIR)/$(CONFIG)/gpr_cmdline_test || ( echo test gpr_cmdline_test failed ; exit 1 )
$(E) "[RUN] Testing gpr_cpu_test"
@@ -2250,6 +2254,7 @@ LIBGPR_SRC = \
src/core/profiling/stap_timers.c \
src/core/support/alloc.c \
src/core/support/avl.c \
+ src/core/support/backoff.c \
src/core/support/cmdline.c \
src/core/support/cpu_iphone.c \
src/core/support/cpu_linux.c \
@@ -6619,6 +6624,38 @@ endif
endif
+GPR_BACKOFF_TEST_SRC = \
+ test/core/support/backoff_test.c \
+
+GPR_BACKOFF_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_BACKOFF_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/gpr_backoff_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/gpr_backoff_test: $(GPR_BACKOFF_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+ $(E) "[LD] Linking $@"
+ $(Q) mkdir -p `dirname $@`
+ $(Q) $(LD) $(LDFLAGS) $(GPR_BACKOFF_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_backoff_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/support/backoff_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_gpr_backoff_test: $(GPR_BACKOFF_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(GPR_BACKOFF_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
GPR_CMDLINE_TEST_SRC = \
test/core/support/cmdline_test.c \
diff --git a/binding.gyp b/binding.gyp
index d1e086cfa0..bb974d6ef8 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -496,6 +496,7 @@
'src/core/profiling/stap_timers.c',
'src/core/support/alloc.c',
'src/core/support/avl.c',
+ 'src/core/support/backoff.c',
'src/core/support/cmdline.c',
'src/core/support/cpu_iphone.c',
'src/core/support/cpu_linux.c',
diff --git a/build.yaml b/build.yaml
index 01495179f5..8a65511969 100644
--- a/build.yaml
+++ b/build.yaml
@@ -55,6 +55,7 @@ filegroups:
- include/grpc/support/useful.h
headers:
- src/core/profiling/timers.h
+ - src/core/support/backoff.h
- src/core/support/block_annotate.h
- src/core/support/env.h
- src/core/support/load_file.h
@@ -70,6 +71,7 @@ filegroups:
- src/core/profiling/stap_timers.c
- src/core/support/alloc.c
- src/core/support/avl.c
+ - src/core/support/backoff.c
- src/core/support/cmdline.c
- src/core/support/cpu_iphone.c
- src/core/support/cpu_linux.c
@@ -1237,6 +1239,14 @@ targets:
deps:
- gpr_test_util
- gpr
+- name: gpr_backoff_test
+ build: test
+ language: c
+ src:
+ - test/core/support/backoff_test.c
+ deps:
+ - gpr_test_util
+ - gpr
- name: gpr_cmdline_test
build: test
language: c
@@ -2436,7 +2446,7 @@ targets:
- linux
- posix
- name: qps_openloop_test
- cpu_cost: 10
+ cpu_cost: 0.5
build: test
language: c++
src:
diff --git a/config.m4 b/config.m4
index 8ab45e6603..013303838e 100644
--- a/config.m4
+++ b/config.m4
@@ -40,6 +40,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/profiling/stap_timers.c \
src/core/support/alloc.c \
src/core/support/avl.c \
+ src/core/support/backoff.c \
src/core/support/cmdline.c \
src/core/support/cpu_iphone.c \
src/core/support/cpu_linux.c \
diff --git a/gRPC.podspec b/gRPC.podspec
index 6f26db1ac1..8a83bd23e2 100644
--- a/gRPC.podspec
+++ b/gRPC.podspec
@@ -64,6 +64,7 @@ Pod::Spec.new do |s|
# Core cross-platform gRPC library, written in C.
s.subspec 'C-Core' do |ss|
ss.source_files = 'src/core/profiling/timers.h',
+ 'src/core/support/backoff.h',
'src/core/support/block_annotate.h',
'src/core/support/env.h',
'src/core/support/load_file.h',
@@ -120,6 +121,7 @@ Pod::Spec.new do |s|
'src/core/profiling/stap_timers.c',
'src/core/support/alloc.c',
'src/core/support/avl.c',
+ 'src/core/support/backoff.c',
'src/core/support/cmdline.c',
'src/core/support/cpu_iphone.c',
'src/core/support/cpu_linux.c',
@@ -470,6 +472,7 @@ Pod::Spec.new do |s|
'third_party/nanopb/pb_encode.c'
ss.private_header_files = 'src/core/profiling/timers.h',
+ 'src/core/support/backoff.h',
'src/core/support/block_annotate.h',
'src/core/support/env.h',
'src/core/support/load_file.h',
diff --git a/grpc.gemspec b/grpc.gemspec
index 0bc4fcfc0e..4480c6e5d1 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -89,6 +89,7 @@ Gem::Specification.new do |s|
s.files += %w( include/grpc/impl/codegen/sync_win32.h )
s.files += %w( include/grpc/impl/codegen/time.h )
s.files += %w( src/core/profiling/timers.h )
+ s.files += %w( src/core/support/backoff.h )
s.files += %w( src/core/support/block_annotate.h )
s.files += %w( src/core/support/env.h )
s.files += %w( src/core/support/load_file.h )
@@ -103,6 +104,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/profiling/stap_timers.c )
s.files += %w( src/core/support/alloc.c )
s.files += %w( src/core/support/avl.c )
+ s.files += %w( src/core/support/backoff.c )
s.files += %w( src/core/support/cmdline.c )
s.files += %w( src/core/support/cpu_iphone.c )
s.files += %w( src/core/support/cpu_linux.c )
diff --git a/package.json b/package.json
index e52a283d9d..cd9668a1b0 100644
--- a/package.json
+++ b/package.json
@@ -865,6 +865,7 @@
"include/grpc/impl/codegen/sync_win32.h",
"include/grpc/impl/codegen/time.h",
"src/core/profiling/timers.h",
+ "src/core/support/backoff.h",
"src/core/support/block_annotate.h",
"src/core/support/env.h",
"src/core/support/load_file.h",
@@ -879,6 +880,7 @@
"src/core/profiling/stap_timers.c",
"src/core/support/alloc.c",
"src/core/support/avl.c",
+ "src/core/support/backoff.c",
"src/core/support/cmdline.c",
"src/core/support/cpu_iphone.c",
"src/core/support/cpu_linux.c",
diff --git a/package.xml b/package.xml
index da06e90e3b..1e0bbc7e39 100644
--- a/package.xml
+++ b/package.xml
@@ -93,6 +93,7 @@
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_win32.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/time.h" role="src" />
<file baseinstalldir="/" name="src/core/profiling/timers.h" role="src" />
+ <file baseinstalldir="/" name="src/core/support/backoff.h" role="src" />
<file baseinstalldir="/" name="src/core/support/block_annotate.h" role="src" />
<file baseinstalldir="/" name="src/core/support/env.h" role="src" />
<file baseinstalldir="/" name="src/core/support/load_file.h" role="src" />
@@ -107,6 +108,7 @@
<file baseinstalldir="/" name="src/core/profiling/stap_timers.c" role="src" />
<file baseinstalldir="/" name="src/core/support/alloc.c" role="src" />
<file baseinstalldir="/" name="src/core/support/avl.c" role="src" />
+ <file baseinstalldir="/" name="src/core/support/backoff.c" role="src" />
<file baseinstalldir="/" name="src/core/support/cmdline.c" role="src" />
<file baseinstalldir="/" name="src/core/support/cpu_iphone.c" role="src" />
<file baseinstalldir="/" name="src/core/support/cpu_linux.c" role="src" />
diff --git a/src/core/client_config/subchannel.c b/src/core/client_config/subchannel.c
index ec9e47a6dd..5dea215668 100644
--- a/src/core/client_config/subchannel.c
+++ b/src/core/client_config/subchannel.c
@@ -45,6 +45,7 @@
#include "src/core/client_config/subchannel_index.h"
#include "src/core/iomgr/timer.h"
#include "src/core/profiling/timers.h"
+#include "src/core/support/backoff.h"
#include "src/core/surface/channel.h"
#include "src/core/transport/connectivity_state.h"
@@ -127,8 +128,8 @@ struct grpc_subchannel {
/** next connect attempt time */
gpr_timespec next_attempt;
- /** amount to backoff each failure */
- gpr_timespec backoff_delta;
+ /** backoff state */
+ gpr_backoff backoff_state;
/** do we have an active alarm? */
int have_alarm;
/** our alarm */
@@ -146,7 +147,6 @@ struct grpc_subchannel_call {
#define CALLSTACK_TO_SUBCHANNEL_CALL(callstack) \
(((grpc_subchannel_call *)(callstack)) - 1)
-static gpr_timespec compute_connect_deadline(grpc_subchannel *c);
static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *subchannel,
bool iomgr_success);
@@ -337,6 +337,22 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
grpc_closure_init(&c->connected, subchannel_connected, c);
grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE,
"subchannel");
+ gpr_backoff_init(&c->backoff_state,
+ GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER,
+ GRPC_SUBCHANNEL_RECONNECT_JITTER,
+ GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000,
+ GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS * 1000);
+ if (c->args) {
+ for (size_t i = 0; i < c->args->num_args; i++) {
+ if (0 == strcmp(c->args->args[i].key,
+ "grpc.testing.fixed_reconnect_backoff")) {
+ GPR_ASSERT(c->args->args[i].type == GRPC_ARG_INTEGER);
+ gpr_backoff_init(&c->backoff_state, 1.0, 0.0,
+ c->args->args[i].value.integer,
+ c->args->args[i].value.integer);
+ }
+ }
+ }
gpr_mu_init(&c->mu);
return grpc_subchannel_index_register(exec_ctx, key, c);
@@ -348,7 +364,7 @@ static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
args.interested_parties = c->pollset_set;
args.addr = c->addr;
args.addr_len = c->addr_len;
- args.deadline = compute_connect_deadline(c);
+ args.deadline = c->next_attempt;
args.channel_args = c->args;
args.initial_connect_string = c->initial_connect_string;
@@ -359,10 +375,8 @@ static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
}
static void start_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
- c->backoff_delta = gpr_time_from_seconds(
- GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS, GPR_TIMESPAN);
c->next_attempt =
- gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), c->backoff_delta);
+ gpr_backoff_begin(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
continue_connect(exec_ctx, c);
}
@@ -577,50 +591,6 @@ static void publish_transport_locked(grpc_exec_ctx *exec_ctx,
gpr_free((void *)filters);
}
-/* Generate a random number between 0 and 1. */
-static double generate_uniform_random_number(grpc_subchannel *c) {
- c->random = (1103515245 * c->random + 12345) % ((uint32_t)1 << 31);
- return c->random / (double)((uint32_t)1 << 31);
-}
-
-/* Update backoff_delta and next_attempt in subchannel */
-static void update_reconnect_parameters(grpc_subchannel *c) {
- size_t i;
- int32_t backoff_delta_millis, jitter;
- int32_t max_backoff_millis =
- GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS * 1000;
- double jitter_range;
-
- if (c->args) {
- for (i = 0; i < c->args->num_args; i++) {
- if (0 == strcmp(c->args->args[i].key,
- "grpc.testing.fixed_reconnect_backoff")) {
- GPR_ASSERT(c->args->args[i].type == GRPC_ARG_INTEGER);
- c->next_attempt = gpr_time_add(
- gpr_now(GPR_CLOCK_MONOTONIC),
- gpr_time_from_millis(c->args->args[i].value.integer, GPR_TIMESPAN));
- return;
- }
- }
- }
-
- backoff_delta_millis =
- (int32_t)(gpr_time_to_millis(c->backoff_delta) *
- GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER);
- if (backoff_delta_millis > max_backoff_millis) {
- backoff_delta_millis = max_backoff_millis;
- }
- c->backoff_delta = gpr_time_from_millis(backoff_delta_millis, GPR_TIMESPAN);
- c->next_attempt =
- gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), c->backoff_delta);
-
- jitter_range = GRPC_SUBCHANNEL_RECONNECT_JITTER * backoff_delta_millis;
- jitter =
- (int32_t)((2 * generate_uniform_random_number(c) - 1) * jitter_range);
- c->next_attempt =
- gpr_time_add(c->next_attempt, gpr_time_from_millis(jitter, GPR_TIMESPAN));
-}
-
static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, bool iomgr_success) {
grpc_subchannel *c = arg;
gpr_mu_lock(&c->mu);
@@ -629,7 +599,8 @@ static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, bool iomgr_success) {
iomgr_success = 0;
}
if (iomgr_success) {
- update_reconnect_parameters(c);
+ c->next_attempt =
+ gpr_backoff_step(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
continue_connect(exec_ctx, c);
gpr_mu_unlock(&c->mu);
} else {
@@ -661,17 +632,6 @@ static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
}
-static gpr_timespec compute_connect_deadline(grpc_subchannel *c) {
- gpr_timespec current_deadline =
- gpr_time_add(c->next_attempt, c->backoff_delta);
- gpr_timespec min_deadline = gpr_time_add(
- gpr_now(GPR_CLOCK_MONOTONIC),
- gpr_time_from_seconds(GRPC_SUBCHANNEL_MIN_CONNECT_TIMEOUT_SECONDS,
- GPR_TIMESPAN));
- return gpr_time_cmp(current_deadline, min_deadline) > 0 ? current_deadline
- : min_deadline;
-}
-
/*
* grpc_subchannel_call implementation
*/
diff --git a/src/core/support/backoff.c b/src/core/support/backoff.c
new file mode 100644
index 0000000000..7458219645
--- /dev/null
+++ b/src/core/support/backoff.c
@@ -0,0 +1,71 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/support/backoff.h"
+
+#include <grpc/support/useful.h>
+
+void gpr_backoff_init(gpr_backoff *backoff, double multiplier, double jitter,
+ int64_t min_timeout_millis, int64_t max_timeout_millis) {
+ backoff->multiplier = multiplier;
+ backoff->jitter = jitter;
+ backoff->min_timeout_millis = min_timeout_millis;
+ backoff->max_timeout_millis = max_timeout_millis;
+ backoff->rng_state = (uint32_t)gpr_now(GPR_CLOCK_REALTIME).tv_nsec;
+}
+
+gpr_timespec gpr_backoff_begin(gpr_backoff *backoff, gpr_timespec now) {
+ backoff->current_timeout_millis = backoff->min_timeout_millis;
+ return gpr_time_add(
+ now, gpr_time_from_millis(backoff->current_timeout_millis, GPR_TIMESPAN));
+}
+
+/* Generate a random number between 0 and 1. */
+static double generate_uniform_random_number(uint32_t *rng_state) {
+ *rng_state = (1103515245 * *rng_state + 12345) % ((uint32_t)1 << 31);
+ return *rng_state / (double)((uint32_t)1 << 31);
+}
+
+gpr_timespec gpr_backoff_step(gpr_backoff *backoff, gpr_timespec now) {
+ double new_timeout_millis =
+ backoff->multiplier * (double)backoff->current_timeout_millis;
+ double jitter_range = backoff->jitter * new_timeout_millis;
+ double jitter =
+ (2 * generate_uniform_random_number(&backoff->rng_state) - 1) *
+ jitter_range;
+ backoff->current_timeout_millis =
+ GPR_CLAMP((int64_t)(new_timeout_millis + jitter),
+ backoff->min_timeout_millis, backoff->max_timeout_millis);
+ return gpr_time_add(
+ now, gpr_time_from_millis(backoff->current_timeout_millis, GPR_TIMESPAN));
+}
diff --git a/src/core/support/backoff.h b/src/core/support/backoff.h
new file mode 100644
index 0000000000..3234aa214d
--- /dev/null
+++ b/src/core/support/backoff.h
@@ -0,0 +1,65 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_INTERNAL_CORE_SUPPORT_BACKOFF_H
+#define GRPC_INTERNAL_CORE_SUPPORT_BACKOFF_H
+
+#include <grpc/support/time.h>
+
+typedef struct {
+ /// const: multiplier between retry attempts
+ double multiplier;
+ /// const: amount to randomize backoffs
+ double jitter;
+ /// const: minimum time between retries in milliseconds
+ int64_t min_timeout_millis;
+ /// const: maximum time between retries in milliseconds
+ int64_t max_timeout_millis;
+
+ /// random number generator
+ uint32_t rng_state;
+
+ /// current retry timeout in milliseconds
+ int64_t current_timeout_millis;
+} gpr_backoff;
+
+/// Initialize backoff machinery - does not need to be destroyed
+void gpr_backoff_init(gpr_backoff *backoff, double multiplier, double jitter,
+ int64_t min_timeout_millis, int64_t max_timeout_millis);
+
+/// Begin retry loop: returns a timespec for the NEXT retry
+gpr_timespec gpr_backoff_begin(gpr_backoff *backoff, gpr_timespec now);
+/// Step a retry loop: returns a timespec for the NEXT retry
+gpr_timespec gpr_backoff_step(gpr_backoff *backoff, gpr_timespec now);
+
+#endif // GRPC_INTERNAL_CORE_SUPPORT_BACKOFF_H
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index a543791f5c..31e16e0491 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -34,6 +34,7 @@ CORE_SOURCE_FILES = [
'src/core/profiling/stap_timers.c',
'src/core/support/alloc.c',
'src/core/support/avl.c',
+ 'src/core/support/backoff.c',
'src/core/support/cmdline.c',
'src/core/support/cpu_iphone.c',
'src/core/support/cpu_linux.c',
diff --git a/test/core/support/backoff_test.c b/test/core/support/backoff_test.c
new file mode 100644
index 0000000000..870b60b2d5
--- /dev/null
+++ b/test/core/support/backoff_test.c
@@ -0,0 +1,107 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/support/backoff.h"
+
+#include <grpc/support/log.h>
+
+#include "test/core/util/test_config.h"
+
+static void test_constant_backoff(void) {
+ gpr_backoff backoff;
+ gpr_backoff_init(&backoff, 1.0, 0.0, 1000, 1000);
+
+ gpr_timespec now = gpr_time_0(GPR_TIMESPAN);
+ gpr_timespec next = gpr_backoff_begin(&backoff, now);
+ GPR_ASSERT(gpr_time_to_millis(gpr_time_sub(next, now)) == 1000);
+ for (int i = 0; i < 10000; i++) {
+ next = gpr_backoff_step(&backoff, now);
+ GPR_ASSERT(gpr_time_to_millis(gpr_time_sub(next, now)) == 1000);
+ now = next;
+ }
+}
+
+static void test_no_jitter_backoff(void) {
+ gpr_backoff backoff;
+ gpr_backoff_init(&backoff, 2.0, 0.0, 1, 513);
+
+ gpr_timespec now = gpr_time_0(GPR_TIMESPAN);
+ gpr_timespec next = gpr_backoff_begin(&backoff, now);
+ GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(1, GPR_TIMESPAN), next) == 0);
+ now = next;
+ next = gpr_backoff_step(&backoff, now);
+ GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(3, GPR_TIMESPAN), next) == 0);
+ now = next;
+ next = gpr_backoff_step(&backoff, now);
+ GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(7, GPR_TIMESPAN), next) == 0);
+ now = next;
+ next = gpr_backoff_step(&backoff, now);
+ GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(15, GPR_TIMESPAN), next) == 0);
+ now = next;
+ next = gpr_backoff_step(&backoff, now);
+ GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(31, GPR_TIMESPAN), next) == 0);
+ now = next;
+ next = gpr_backoff_step(&backoff, now);
+ GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(63, GPR_TIMESPAN), next) == 0);
+ now = next;
+ next = gpr_backoff_step(&backoff, now);
+ GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(127, GPR_TIMESPAN), next) == 0);
+ now = next;
+ next = gpr_backoff_step(&backoff, now);
+ GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(255, GPR_TIMESPAN), next) == 0);
+ now = next;
+ next = gpr_backoff_step(&backoff, now);
+ GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(511, GPR_TIMESPAN), next) == 0);
+ now = next;
+ next = gpr_backoff_step(&backoff, now);
+ GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(1023, GPR_TIMESPAN), next) == 0);
+ now = next;
+ next = gpr_backoff_step(&backoff, now);
+ GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(1536, GPR_TIMESPAN), next) == 0);
+ now = next;
+ next = gpr_backoff_step(&backoff, now);
+ GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(2049, GPR_TIMESPAN), next) == 0);
+ now = next;
+ next = gpr_backoff_step(&backoff, now);
+ GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(2562, GPR_TIMESPAN), next) == 0);
+}
+
+int main(int argc, char **argv) {
+ grpc_test_init(argc, argv);
+ gpr_time_init();
+
+ test_constant_backoff();
+ test_no_jitter_backoff();
+
+ return 0;
+}
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 71b7af2a22..a06d4ecb42 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -1112,6 +1112,7 @@ include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_win32.h \
include/grpc/impl/codegen/time.h \
src/core/profiling/timers.h \
+src/core/support/backoff.h \
src/core/support/block_annotate.h \
src/core/support/env.h \
src/core/support/load_file.h \
@@ -1126,6 +1127,7 @@ src/core/profiling/basic_timers.c \
src/core/profiling/stap_timers.c \
src/core/support/alloc.c \
src/core/support/avl.c \
+src/core/support/backoff.c \
src/core/support/cmdline.c \
src/core/support/cpu_iphone.c \
src/core/support/cpu_linux.c \
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index 783a353ca8..503adba2fb 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -411,6 +411,20 @@
],
"headers": [],
"language": "c",
+ "name": "gpr_backoff_test",
+ "src": [
+ "test/core/support/backoff_test.c"
+ ],
+ "third_party": false,
+ "type": "target"
+ },
+ {
+ "deps": [
+ "gpr",
+ "gpr_test_util"
+ ],
+ "headers": [],
+ "language": "c",
"name": "gpr_cmdline_test",
"src": [
"test/core/support/cmdline_test.c"
@@ -3746,6 +3760,7 @@
"include/grpc/support/tls_pthread.h",
"include/grpc/support/useful.h",
"src/core/profiling/timers.h",
+ "src/core/support/backoff.h",
"src/core/support/block_annotate.h",
"src/core/support/env.h",
"src/core/support/load_file.h",
@@ -3807,6 +3822,8 @@
"src/core/profiling/timers.h",
"src/core/support/alloc.c",
"src/core/support/avl.c",
+ "src/core/support/backoff.c",
+ "src/core/support/backoff.h",
"src/core/support/block_annotate.h",
"src/core/support/cmdline.c",
"src/core/support/cpu_iphone.c",
diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json
index 2be7d8a48a..784dfd865b 100644
--- a/tools/run_tests/tests.json
+++ b/tools/run_tests/tests.json
@@ -466,6 +466,27 @@
"flaky": false,
"gtest": false,
"language": "c",
+ "name": "gpr_backoff_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ]
+ },
+ {
+ "args": [],
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "flaky": false,
+ "gtest": false,
+ "language": "c",
"name": "gpr_cmdline_test",
"platforms": [
"linux",
@@ -2295,7 +2316,7 @@
"mac",
"posix"
],
- "cpu_cost": 10,
+ "cpu_cost": 0.5,
"exclude_configs": [],
"flaky": false,
"gtest": false,
diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln
index 2092162f61..752fac7483 100644
--- a/vsprojects/buildtests_c.sln
+++ b/vsprojects/buildtests_c.sln
@@ -334,6 +334,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_avl_test", "vcxproj\tes
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_backoff_test", "vcxproj\test\gpr_backoff_test\gpr_backoff_test.vcxproj", "{889F570D-E046-BD52-9E4C-B4CD13DFE2DB}"
+ ProjectSection(myProperties) = preProject
+ lib = "False"
+ EndProjectSection
+ ProjectSection(ProjectDependencies) = postProject
+ {EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+ {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+ EndProjectSection
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_cmdline_test", "vcxproj\test\gpr_cmdline_test\gpr_cmdline_test.vcxproj", "{10668A5D-65CD-F530-22D0-747B395B4C26}"
ProjectSection(myProperties) = preProject
lib = "False"
@@ -1868,6 +1877,22 @@ Global
{144D8CFF-2737-A18A-DCFD-01603533D63F}.Release-DLL|Win32.Build.0 = Release|Win32
{144D8CFF-2737-A18A-DCFD-01603533D63F}.Release-DLL|x64.ActiveCfg = Release|x64
{144D8CFF-2737-A18A-DCFD-01603533D63F}.Release-DLL|x64.Build.0 = Release|x64
+ {889F570D-E046-BD52-9E4C-B4CD13DFE2DB}.Debug|Win32.ActiveCfg = Debug|Win32
+ {889F570D-E046-BD52-9E4C-B4CD13DFE2DB}.Debug|x64.ActiveCfg = Debug|x64
+ {889F570D-E046-BD52-9E4C-B4CD13DFE2DB}.Release|Win32.ActiveCfg = Release|Win32
+ {889F570D-E046-BD52-9E4C-B4CD13DFE2DB}.Release|x64.ActiveCfg = Release|x64
+ {889F570D-E046-BD52-9E4C-B4CD13DFE2DB}.Debug|Win32.Build.0 = Debug|Win32
+ {889F570D-E046-BD52-9E4C-B4CD13DFE2DB}.Debug|x64.Build.0 = Debug|x64
+ {889F570D-E046-BD52-9E4C-B4CD13DFE2DB}.Release|Win32.Build.0 = Release|Win32
+ {889F570D-E046-BD52-9E4C-B4CD13DFE2DB}.Release|x64.Build.0 = Release|x64
+ {889F570D-E046-BD52-9E4C-B4CD13DFE2DB}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+ {889F570D-E046-BD52-9E4C-B4CD13DFE2DB}.Debug-DLL|Win32.Build.0 = Debug|Win32
+ {889F570D-E046-BD52-9E4C-B4CD13DFE2DB}.Debug-DLL|x64.ActiveCfg = Debug|x64
+ {889F570D-E046-BD52-9E4C-B4CD13DFE2DB}.Debug-DLL|x64.Build.0 = Debug|x64
+ {889F570D-E046-BD52-9E4C-B4CD13DFE2DB}.Release-DLL|Win32.ActiveCfg = Release|Win32
+ {889F570D-E046-BD52-9E4C-B4CD13DFE2DB}.Release-DLL|Win32.Build.0 = Release|Win32
+ {889F570D-E046-BD52-9E4C-B4CD13DFE2DB}.Release-DLL|x64.ActiveCfg = Release|x64
+ {889F570D-E046-BD52-9E4C-B4CD13DFE2DB}.Release-DLL|x64.Build.0 = Release|x64
{10668A5D-65CD-F530-22D0-747B395B4C26}.Debug|Win32.ActiveCfg = Debug|Win32
{10668A5D-65CD-F530-22D0-747B395B4C26}.Debug|x64.ActiveCfg = Debug|x64
{10668A5D-65CD-F530-22D0-747B395B4C26}.Release|Win32.ActiveCfg = Release|Win32
diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj b/vsprojects/vcxproj/gpr/gpr.vcxproj
index dae8e623d8..9281fa3995 100644
--- a/vsprojects/vcxproj/gpr/gpr.vcxproj
+++ b/vsprojects/vcxproj/gpr/gpr.vcxproj
@@ -192,6 +192,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(SolutionDir)\..\src\core\profiling\timers.h" />
+ <ClInclude Include="$(SolutionDir)\..\src\core\support\backoff.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\support\block_annotate.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\support\env.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\support\load_file.h" />
@@ -212,6 +213,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\support\avl.c">
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\support\backoff.c">
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\support\cmdline.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\support\cpu_iphone.c">
diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters
index 055b29f648..b85060f385 100644
--- a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters
+++ b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters
@@ -13,6 +13,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\support\avl.c">
<Filter>src\core\support</Filter>
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\support\backoff.c">
+ <Filter>src\core\support</Filter>
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\support\cmdline.c">
<Filter>src\core\support</Filter>
</ClCompile>
@@ -263,6 +266,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\profiling\timers.h">
<Filter>src\core\profiling</Filter>
</ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\src\core\support\backoff.h">
+ <Filter>src\core\support</Filter>
+ </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\support\block_annotate.h">
<Filter>src\core\support</Filter>
</ClInclude>
diff --git a/vsprojects/vcxproj/test/gpr_backoff_test/gpr_backoff_test.vcxproj b/vsprojects/vcxproj/test/gpr_backoff_test/gpr_backoff_test.vcxproj
new file mode 100644
index 0000000000..6aa292ef4f
--- /dev/null
+++ b/vsprojects/vcxproj/test/gpr_backoff_test/gpr_backoff_test.vcxproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{889F570D-E046-BD52-9E4C-B4CD13DFE2DB}</ProjectGuid>
+ <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+ <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+ <PlatformToolset>v110</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+ <TargetName>gpr_backoff_test</TargetName>
+ <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+ <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+ <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+ <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Release'">
+ <TargetName>gpr_backoff_test</TargetName>
+ <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+ <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+ <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+ <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)\..\test\core\support\backoff_test.c">
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+ <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+ </ProjectReference>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+ <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+ </ImportGroup>
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+ </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/gpr_backoff_test/gpr_backoff_test.vcxproj.filters b/vsprojects/vcxproj/test/gpr_backoff_test/gpr_backoff_test.vcxproj.filters
new file mode 100644
index 0000000000..eb3c1bbd8c
--- /dev/null
+++ b/vsprojects/vcxproj/test/gpr_backoff_test/gpr_backoff_test.vcxproj.filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)\..\test\core\support\backoff_test.c">
+ <Filter>test\core\support</Filter>
+ </ClCompile>
+ </ItemGroup>
+
+ <ItemGroup>
+ <Filter Include="test">
+ <UniqueIdentifier>{4b7f1d25-d344-0bcb-63d8-2ba959874ea8}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test\core">
+ <UniqueIdentifier>{2bd2fba5-8799-2c78-469f-ec3ba6b01da8}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test\core\support">
+ <UniqueIdentifier>{2ef0cfa7-fe3d-2b82-7d0e-f9e293e8f98c}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
+