aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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/README.rst9
-rw-r--r--src/python/grpcio/grpc_core_dependencies.py1
5 files changed, 165 insertions, 67 deletions
diff --git a/src/core/client_config/subchannel.c b/src/core/client_config/subchannel.c
index de28437d0c..8f150a8d81 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/surface/channel_init.h"
#include "src/core/transport/connectivity_state.h"
@@ -128,8 +129,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 */
@@ -147,7 +148,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);
@@ -338,6 +338,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);
@@ -349,7 +365,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;
@@ -360,10 +376,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);
}
@@ -557,50 +571,6 @@ static void publish_transport_locked(grpc_exec_ctx *exec_ctx,
"connected");
}
-/* 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);
@@ -609,7 +579,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 {
@@ -641,17 +612,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/README.rst b/src/python/grpcio/README.rst
index 3dfae50b4b..3f4c6fad02 100644
--- a/src/python/grpcio/README.rst
+++ b/src/python/grpcio/README.rst
@@ -35,13 +35,14 @@ package named :code:`python-dev`).
::
- $ export REPO_ROOT=grpc
+ $ export REPO_ROOT=grpc # REPO_ROOT can be any directory of your choice
$ git clone https://github.com/grpc/grpc.git $REPO_ROOT
$ cd $REPO_ROOT
- $ pip install .
-Note that :code:`$REPO_ROOT` can be assigned to whatever directory name floats
-your fancy.
+ # For the next two commands do `sudo pip install` if you get permission-denied errors
+ $ pip install -rrequirements.txt
+ $ GRPC_PYTHON_BUILD_WITH_CYTHON=1 pip install .
+
Troubleshooting
~~~~~~~~~~~~~~~
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index ee375c42eb..b9e7d8c898 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',