aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/channel/client_channel.c
diff options
context:
space:
mode:
authorGravatar ctiller <ctiller@google.com>2014-12-15 14:52:08 -0800
committerGravatar Nicolas Noble <nnoble@google.com>2014-12-15 15:39:03 -0800
commitc6d61c4dd6deb80477cb5977b79b00614b20b409 (patch)
tree649e913ff67706ee2c41a7cb3102c135424b8f35 /src/core/channel/client_channel.c
parent608254011d441b1e234fc5d6aa528cedccaddda3 (diff)
GOAWAY & Reconnection support.
Clients stay connected to a server after it shutdowns until all active calls have completed, and then they drop. After a GOAWAY or a disconnect, clients will attempt to re-resolve and reconnect to the server. Change on 2014/12/15 by ctiller <ctiller@google.com> ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=82178515
Diffstat (limited to 'src/core/channel/client_channel.c')
-rw-r--r--src/core/channel/client_channel.c46
1 files changed, 44 insertions, 2 deletions
diff --git a/src/core/channel/client_channel.c b/src/core/channel/client_channel.c
index 4bd294dc96..a146a7b6a0 100644
--- a/src/core/channel/client_channel.c
+++ b/src/core/channel/client_channel.c
@@ -39,6 +39,7 @@
#include "src/core/channel/child_channel.h"
#include "src/core/channel/connected_channel.h"
#include "src/core/channel/metadata_buffer.h"
+#include "src/core/iomgr/iomgr.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string.h>
@@ -290,6 +291,14 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
}
}
+static void finally_destroy_channel(void *arg, grpc_iomgr_cb_status status) {
+ grpc_child_channel_destroy(arg);
+}
+
+static void destroy_channel_later(grpc_child_channel *channel) {
+ grpc_iomgr_add_callback(finally_destroy_channel, channel);
+}
+
static void channel_op(grpc_channel_element *elem,
grpc_channel_element *from_elem, grpc_channel_op *op) {
channel_data *chand = elem->channel_data;
@@ -298,24 +307,57 @@ static void channel_op(grpc_channel_element *elem,
switch (op->type) {
case GRPC_CHANNEL_GOAWAY:
+ /* sending goaway: clear out the active child on the way through */
gpr_mu_lock(&chand->mu);
child_channel = chand->active_child;
chand->active_child = NULL;
gpr_mu_unlock(&chand->mu);
if (child_channel) {
grpc_child_channel_handle_op(child_channel, op);
- grpc_child_channel_destroy(child_channel);
+ destroy_channel_later(child_channel);
} else {
gpr_slice_unref(op->data.goaway.message);
}
break;
case GRPC_CHANNEL_DISCONNECT:
+ /* sending disconnect: clear out the active child on the way through */
gpr_mu_lock(&chand->mu);
child_channel = chand->active_child;
chand->active_child = NULL;
gpr_mu_unlock(&chand->mu);
if (child_channel) {
- grpc_child_channel_destroy(child_channel);
+ destroy_channel_later(child_channel);
+ }
+ break;
+ case GRPC_TRANSPORT_GOAWAY:
+ /* receiving goaway: if it's from our active child, drop the active child;
+ in all cases consume the event here */
+ gpr_mu_lock(&chand->mu);
+ child_channel = grpc_channel_stack_from_top_element(from_elem);
+ if (child_channel == chand->active_child) {
+ chand->active_child = NULL;
+ } else {
+ child_channel = NULL;
+ }
+ gpr_mu_unlock(&chand->mu);
+ if (child_channel) {
+ destroy_channel_later(child_channel);
+ }
+ gpr_slice_unref(op->data.goaway.message);
+ break;
+ case GRPC_TRANSPORT_CLOSED:
+ /* receiving disconnect: if it's from our active child, drop the active
+ child; in all cases consume the event here */
+ gpr_mu_lock(&chand->mu);
+ child_channel = grpc_channel_stack_from_top_element(from_elem);
+ if (child_channel == chand->active_child) {
+ chand->active_child = NULL;
+ } else {
+ child_channel = NULL;
+ }
+ gpr_mu_unlock(&chand->mu);
+ if (child_channel) {
+ destroy_channel_later(child_channel);
}
break;
default: