Add max age grace period

pull/10318/head
Yuchen Zeng 8 years ago
parent a809ea5c14
commit a1506c4e8f
  1. 6
      include/grpc/impl/codegen/grpc_types.h
  2. 95
      src/core/lib/channel/max_age_filter.c

@ -163,9 +163,11 @@ typedef struct {
/** Maximum message length that the channel can send. Int valued, bytes.
-1 means unlimited. */
#define GRPC_ARG_MAX_SEND_MESSAGE_LENGTH "grpc.max_send_message_length"
/** Maximum time that a channel may exist. Int valued, seconds. INT_MAX means
unlimited. */
#define GPRC_ARG_MAX_CONNECION_AGE_S "grpc.max_connection_age"
/** Grace period after the chennel reaches its max age. Int valued, seconds.
INT_MAX means unlimited. */
#define GPRC_ARG_MAX_CONNECION_AGE_GRACE_S "grpc.max_connection_age_grace"
/** Initial sequence number for http2 transports. Int valued. */
#define GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER \

@ -41,6 +41,7 @@
#include "src/core/lib/transport/service_config.h"
#define DEFAULT_MAX_CONNECTION_AGE_S INT_MAX
#define DEFAULT_MAX_CONNECTION_AGE_GRACE_S INT_MAX
typedef struct channel_data {
// We take a reference to the channel stack for the timer callback
@ -49,18 +50,30 @@ typedef struct channel_data {
gpr_mu max_age_timer_mu;
// True if the max_age timer callback is currently pending
bool max_age_timer_pending;
// True if the max_age timer callback is currently pending
bool max_age_grace_timer_pending;
// The timer for checking if the channel has reached its max age
grpc_timer max_age_timer;
// The timer for checking if the channel has reached its max age
grpc_timer max_age_grace_timer;
// Allowed max time a channel may exist
gpr_timespec max_connection_age;
// Allowed grace period after the channel reaches its max age
gpr_timespec max_connection_age_grace;
// Closure to run when the channel reaches its max age and should be closed
// gracefully
grpc_closure close_max_age_channel;
// Closure to run when the init fo channel stack is done and the timer should
// be started
grpc_closure start_timer_after_init;
// Closure to run the channel uses up its max age grace time and should be
// closed forcibly
grpc_closure force_close_max_age_channel;
// Closure to run when the init fo channel stack is done and the max_age timer
// should be started
grpc_closure start_max_age_timer_after_init;
// Closure to run when the goaway op is finished and the max_age_timer
grpc_closure start_max_age_grace_timer_after_goaway_op;
} channel_data;
static void start_timer_after_init(grpc_exec_ctx* exec_ctx, void* arg,
static void start_max_age_timer_after_init(grpc_exec_ctx* exec_ctx, void* arg,
grpc_error* error) {
channel_data* chand = arg;
gpr_mu_lock(&chand->max_age_timer_mu);
@ -71,7 +84,23 @@ static void start_timer_after_init(grpc_exec_ctx* exec_ctx, void* arg,
&chand->close_max_age_channel, gpr_now(GPR_CLOCK_MONOTONIC));
gpr_mu_unlock(&chand->max_age_timer_mu);
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack,
"max_age start_timer_after_init");
"max_age start_max_age_timer_after_init");
}
static void start_max_age_grace_timer_after_goaway_op(grpc_exec_ctx* exec_ctx,
void* arg,
grpc_error* error) {
channel_data* chand = arg;
gpr_mu_lock(&chand->max_age_timer_mu);
chand->max_age_grace_timer_pending = true;
grpc_timer_init(exec_ctx, &chand->max_age_grace_timer,
gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
chand->max_connection_age_grace),
&chand->force_close_max_age_channel,
gpr_now(GPR_CLOCK_MONOTONIC));
gpr_mu_unlock(&chand->max_age_timer_mu);
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack,
"max_age start_max_age_grace_timer_after_goaway_op");
}
static void close_max_age_channel(grpc_exec_ctx* exec_ctx, void* arg,
@ -81,7 +110,10 @@ static void close_max_age_channel(grpc_exec_ctx* exec_ctx, void* arg,
chand->max_age_timer_pending = false;
gpr_mu_unlock(&chand->max_age_timer_mu);
if (error == GRPC_ERROR_NONE) {
grpc_transport_op* op = grpc_make_transport_op(NULL);
GRPC_CHANNEL_STACK_REF(chand->channel_stack,
"max_age start_max_age_grace_timer_after_goaway_op");
grpc_transport_op* op = grpc_make_transport_op(
&chand->start_max_age_grace_timer_after_goaway_op);
op->goaway_error =
grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("max_age"),
GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_NO_ERROR);
@ -93,6 +125,24 @@ static void close_max_age_channel(grpc_exec_ctx* exec_ctx, void* arg,
}
}
static void force_close_max_age_channel(grpc_exec_ctx* exec_ctx, void* arg,
grpc_error* error) {
channel_data* chand = arg;
gpr_mu_lock(&chand->max_age_timer_mu);
chand->max_age_grace_timer_pending = false;
gpr_mu_unlock(&chand->max_age_timer_mu);
if (error == GRPC_ERROR_NONE) {
grpc_transport_op* op = grpc_make_transport_op(NULL);
op->disconnect_with_error =
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel reaches max age");
grpc_channel_element* elem =
grpc_channel_stack_element(chand->channel_stack, 0);
elem->filter->start_transport_op(exec_ctx, elem, op);
} else if (error != GRPC_ERROR_CANCELLED) {
GRPC_LOG_IF_ERROR("force_close_max_age_channel", error);
}
}
// Constructor for call_data.
static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
grpc_call_element* elem,
@ -115,11 +165,17 @@ static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
channel_data* chand = elem->channel_data;
gpr_mu_init(&chand->max_age_timer_mu);
chand->max_age_timer_pending = false;
chand->max_age_grace_timer_pending = false;
chand->channel_stack = args->channel_stack;
chand->max_connection_age =
DEFAULT_MAX_CONNECTION_AGE_S == INT_MAX
? gpr_inf_future(GPR_TIMESPAN)
: gpr_time_from_seconds(DEFAULT_MAX_CONNECTION_AGE_S, GPR_TIMESPAN);
chand->max_connection_age =
DEFAULT_MAX_CONNECTION_AGE_GRACE_S == INT_MAX
? gpr_inf_future(GPR_TIMESPAN)
: gpr_time_from_seconds(DEFAULT_MAX_CONNECTION_AGE_GRACE_S,
GPR_TIMESPAN);
for (size_t i = 0; i < args->channel_args->num_args; ++i) {
if (0 ==
strcmp(args->channel_args->args[i].key, GPRC_ARG_MAX_CONNECION_AGE_S)) {
@ -129,10 +185,28 @@ static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
chand->max_connection_age =
value == INT_MAX ? gpr_inf_future(GPR_TIMESPAN)
: gpr_time_from_seconds(value, GPR_TIMESPAN);
} else if (0 == strcmp(args->channel_args->args[i].key,
GPRC_ARG_MAX_CONNECION_AGE_GRACE_S)) {
const int value = grpc_channel_arg_get_integer(
&args->channel_args->args[i],
(grpc_integer_options){DEFAULT_MAX_CONNECTION_AGE_GRACE_S, 1,
INT_MAX});
chand->max_connection_age_grace =
value == INT_MAX ? gpr_inf_future(GPR_TIMESPAN)
: gpr_time_from_seconds(value, GPR_TIMESPAN);
}
}
grpc_closure_init(&chand->close_max_age_channel, close_max_age_channel, chand,
grpc_schedule_on_exec_ctx);
grpc_closure_init(&chand->force_close_max_age_channel,
force_close_max_age_channel, chand,
grpc_schedule_on_exec_ctx);
grpc_closure_init(&chand->start_max_age_timer_after_init,
start_max_age_timer_after_init, chand,
grpc_schedule_on_exec_ctx);
grpc_closure_init(&chand->start_max_age_grace_timer_after_goaway_op,
start_max_age_grace_timer_after_goaway_op, chand,
grpc_schedule_on_exec_ctx);
if (gpr_time_cmp(chand->max_connection_age, gpr_inf_future(GPR_TIMESPAN)) !=
0) {
@ -144,10 +218,8 @@ static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
// timer, and we schedule that closure to be run after call stack
// initialization is done.
GRPC_CHANNEL_STACK_REF(chand->channel_stack,
"max_age start_timer_after_init");
grpc_closure_init(&chand->start_timer_after_init, start_timer_after_init,
chand, grpc_schedule_on_exec_ctx);
grpc_closure_sched(exec_ctx, &chand->start_timer_after_init,
"max_age start_max_age_timer_after_init");
grpc_closure_sched(exec_ctx, &chand->start_max_age_timer_after_init,
GRPC_ERROR_NONE);
}
@ -162,6 +234,9 @@ static void destroy_channel_elem(grpc_exec_ctx* exec_ctx,
if (chand->max_age_timer_pending) {
grpc_timer_cancel(exec_ctx, &chand->max_age_timer);
}
if (chand->max_age_grace_timer_pending) {
grpc_timer_cancel(exec_ctx, &chand->max_age_grace_timer);
}
gpr_mu_unlock(&chand->max_age_timer_mu);
}

Loading…
Cancel
Save