aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/channel
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/channel')
-rw-r--r--src/core/channel/channel_stack.c6
-rw-r--r--src/core/channel/child_channel.c7
-rw-r--r--src/core/channel/client_channel.c45
-rw-r--r--src/core/channel/client_setup.c95
-rw-r--r--src/core/channel/client_setup.h12
5 files changed, 115 insertions, 50 deletions
diff --git a/src/core/channel/channel_stack.c b/src/core/channel/channel_stack.c
index 311f4f08ce..9eec8163f5 100644
--- a/src/core/channel/channel_stack.c
+++ b/src/core/channel/channel_stack.c
@@ -211,9 +211,3 @@ void grpc_call_element_send_cancel(grpc_call_element *cur_elem) {
op.cancel_with_status = GRPC_STATUS_CANCELLED;
grpc_call_next_op(cur_elem, &op);
}
-
-void grpc_call_element_recv_status(grpc_call_element *cur_elem,
- grpc_status_code status,
- const char *message) {
- abort();
-}
diff --git a/src/core/channel/child_channel.c b/src/core/channel/child_channel.c
index 600f7df1bf..6690265d75 100644
--- a/src/core/channel/child_channel.c
+++ b/src/core/channel/child_channel.c
@@ -157,9 +157,10 @@ static void lb_destroy_channel_elem(grpc_channel_element *elem) {
}
const grpc_channel_filter grpc_child_channel_top_filter = {
- lb_start_transport_op, lb_channel_op, sizeof(lb_call_data),
- lb_init_call_elem, lb_destroy_call_elem, sizeof(lb_channel_data),
- lb_init_channel_elem, lb_destroy_channel_elem, "child-channel",
+ lb_start_transport_op, lb_channel_op,
+ sizeof(lb_call_data), lb_init_call_elem, lb_destroy_call_elem,
+ sizeof(lb_channel_data), lb_init_channel_elem, lb_destroy_channel_elem,
+ "child-channel",
};
/* grpc_child_channel proper */
diff --git a/src/core/channel/client_channel.c b/src/core/channel/client_channel.c
index 42e242ae81..726196e996 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/iomgr/iomgr.h"
+#include "src/core/iomgr/pollset_set.h"
#include "src/core/support/string.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@@ -101,10 +102,17 @@ struct call_data {
static int prepare_activate(grpc_call_element *elem,
grpc_child_channel *on_child) {
call_data *calld = elem->call_data;
+ channel_data *chand = elem->channel_data;
if (calld->state == CALL_CANCELLED) return 0;
/* no more access to calld->s.waiting allowed */
GPR_ASSERT(calld->state == CALL_WAITING);
+
+ if (calld->s.waiting_op.bind_pollset) {
+ grpc_transport_setup_del_interested_party(chand->transport_setup,
+ calld->s.waiting_op.bind_pollset);
+ }
+
calld->state = CALL_ACTIVE;
/* create a child call */
@@ -131,7 +139,11 @@ static void remove_waiting_child(channel_data *chand, call_data *calld) {
size_t new_count;
size_t i;
for (i = 0, new_count = 0; i < chand->waiting_child_count; i++) {
- if (chand->waiting_children[i] == calld) continue;
+ if (chand->waiting_children[i] == calld) {
+ grpc_transport_setup_del_interested_party(
+ chand->transport_setup, calld->s.waiting_op.bind_pollset);
+ continue;
+ }
chand->waiting_children[new_count++] = chand->waiting_children[i];
}
GPR_ASSERT(new_count == chand->waiting_child_count - 1 ||
@@ -166,6 +178,9 @@ static void handle_op_after_cancellation(grpc_call_element *elem,
*op->recv_state = GRPC_STREAM_CLOSED;
op->on_done_recv(op->recv_user_data, 1);
}
+ if (op->on_consumed) {
+ op->on_consumed(op->on_consumed_user_data, 0);
+ }
}
static void cc_start_transport_op(grpc_call_element *elem,
@@ -191,6 +206,7 @@ static void cc_start_transport_op(grpc_call_element *elem,
handle_op_after_cancellation(elem, op);
} else {
calld->state = CALL_WAITING;
+ calld->s.waiting_op.bind_pollset = NULL;
if (chand->active_child) {
/* channel is connected - use the connected stack */
if (prepare_activate(elem, chand->active_child)) {
@@ -222,6 +238,8 @@ static void cc_start_transport_op(grpc_call_element *elem,
}
calld->s.waiting_op = *op;
chand->waiting_children[chand->waiting_child_count++] = calld;
+ grpc_transport_setup_add_interested_party(chand->transport_setup,
+ op->bind_pollset);
gpr_mu_unlock(&chand->mu);
/* finally initiate transport setup if needed */
@@ -257,6 +275,9 @@ static void cc_start_transport_op(grpc_call_element *elem,
calld->s.waiting_op.recv_user_data = op->recv_user_data;
}
gpr_mu_unlock(&chand->mu);
+ if (op->on_consumed) {
+ op->on_consumed(op->on_consumed_user_data, 0);
+ }
}
break;
case CALL_CANCELLED:
@@ -365,12 +386,24 @@ static void init_call_elem(grpc_call_element *elem,
/* Destructor for call_data */
static void destroy_call_elem(grpc_call_element *elem) {
call_data *calld = elem->call_data;
+ channel_data *chand = elem->channel_data;
/* if the call got activated, we need to destroy the child stack also, and
remove it from the in-flight requests tracked by the child_entry we
picked */
- if (calld->state == CALL_ACTIVE) {
- grpc_child_call_destroy(calld->s.active.child_call);
+ gpr_mu_lock(&chand->mu);
+ switch (calld->state) {
+ case CALL_ACTIVE:
+ gpr_mu_unlock(&chand->mu);
+ grpc_child_call_destroy(calld->s.active.child_call);
+ break;
+ case CALL_WAITING:
+ remove_waiting_child(chand, calld);
+ gpr_mu_unlock(&chand->mu);
+ break;
+ default:
+ gpr_mu_unlock(&chand->mu);
+ break;
}
GPR_ASSERT(calld->state != CALL_WAITING);
}
@@ -416,9 +449,9 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
}
const grpc_channel_filter grpc_client_channel_filter = {
- cc_start_transport_op, channel_op, sizeof(call_data), init_call_elem,
- destroy_call_elem, sizeof(channel_data), init_channel_elem,
- destroy_channel_elem, "client-channel",
+ cc_start_transport_op, channel_op, sizeof(call_data),
+ init_call_elem, destroy_call_elem, sizeof(channel_data),
+ init_channel_elem, destroy_channel_elem, "client-channel",
};
grpc_transport_setup_result grpc_client_channel_transport_setup_complete(
diff --git a/src/core/channel/client_setup.c b/src/core/channel/client_setup.c
index 6d892d6c92..5be8fa66e9 100644
--- a/src/core/channel/client_setup.c
+++ b/src/core/channel/client_setup.c
@@ -56,6 +56,9 @@ struct grpc_client_setup {
gpr_cv cv;
grpc_client_setup_request *active_request;
int refs;
+ /** The set of pollsets that are currently interested in this
+ connection being established */
+ grpc_pollset_set interested_parties;
};
struct grpc_client_setup_request {
@@ -68,14 +71,22 @@ gpr_timespec grpc_client_setup_request_deadline(grpc_client_setup_request *r) {
return r->deadline;
}
+grpc_pollset_set *grpc_client_setup_get_interested_parties(
+ grpc_client_setup_request *r) {
+ return &r->setup->interested_parties;
+}
+
static void destroy_setup(grpc_client_setup *s) {
gpr_mu_destroy(&s->mu);
gpr_cv_destroy(&s->cv);
s->done(s->user_data);
grpc_channel_args_destroy(s->args);
+ grpc_pollset_set_destroy(&s->interested_parties);
gpr_free(s);
}
+static void destroy_request(grpc_client_setup_request *r) { gpr_free(r); }
+
/* initiate handshaking */
static void setup_initiate(grpc_transport_setup *sp) {
grpc_client_setup *s = (grpc_client_setup *)sp;
@@ -83,8 +94,7 @@ static void setup_initiate(grpc_transport_setup *sp) {
int in_alarm = 0;
r->setup = s;
- /* TODO(klempner): Actually set a deadline */
- r->deadline = gpr_inf_future;
+ r->deadline = gpr_time_add(gpr_now(), gpr_time_from_seconds(60));
gpr_mu_lock(&s->mu);
GPR_ASSERT(s->refs > 0);
@@ -104,10 +114,30 @@ static void setup_initiate(grpc_transport_setup *sp) {
if (!in_alarm) {
s->initiate(s->user_data, r);
} else {
- gpr_free(r);
+ destroy_request(r);
}
}
+/** implementation of add_interested_party for setup vtable */
+static void setup_add_interested_party(grpc_transport_setup *sp,
+ grpc_pollset *pollset) {
+ grpc_client_setup *s = (grpc_client_setup *)sp;
+
+ gpr_mu_lock(&s->mu);
+ grpc_pollset_set_add_pollset(&s->interested_parties, pollset);
+ gpr_mu_unlock(&s->mu);
+}
+
+/** implementation of del_interested_party for setup vtable */
+static void setup_del_interested_party(grpc_transport_setup *sp,
+ grpc_pollset *pollset) {
+ grpc_client_setup *s = (grpc_client_setup *)sp;
+
+ gpr_mu_lock(&s->mu);
+ grpc_pollset_set_del_pollset(&s->interested_parties, pollset);
+ gpr_mu_unlock(&s->mu);
+}
+
/* cancel handshaking: cancel all requests, and shutdown (the caller promises
not to initiate again) */
static void setup_cancel(grpc_transport_setup *sp) {
@@ -137,7 +167,8 @@ static void setup_cancel(grpc_transport_setup *sp) {
}
}
-int grpc_client_setup_cb_begin(grpc_client_setup_request *r) {
+int grpc_client_setup_cb_begin(grpc_client_setup_request *r,
+ const char *reason) {
gpr_mu_lock(&r->setup->mu);
if (r->setup->cancelled) {
gpr_mu_unlock(&r->setup->mu);
@@ -148,7 +179,8 @@ int grpc_client_setup_cb_begin(grpc_client_setup_request *r) {
return 1;
}
-void grpc_client_setup_cb_end(grpc_client_setup_request *r) {
+void grpc_client_setup_cb_end(grpc_client_setup_request *r,
+ const char *reason) {
gpr_mu_lock(&r->setup->mu);
r->setup->in_cb--;
if (r->setup->cancelled) gpr_cv_signal(&r->setup->cv);
@@ -156,8 +188,9 @@ void grpc_client_setup_cb_end(grpc_client_setup_request *r) {
}
/* vtable for transport setup */
-static const grpc_transport_setup_vtable setup_vtable = {setup_initiate,
- setup_cancel};
+static const grpc_transport_setup_vtable setup_vtable = {
+ setup_initiate, setup_add_interested_party, setup_del_interested_party,
+ setup_cancel};
void grpc_client_setup_create_and_attach(
grpc_channel_stack *newly_minted_channel, const grpc_channel_args *args,
@@ -180,42 +213,44 @@ void grpc_client_setup_create_and_attach(
s->in_alarm = 0;
s->in_cb = 0;
s->cancelled = 0;
+ grpc_pollset_set_init(&s->interested_parties);
grpc_client_channel_set_transport_setup(newly_minted_channel, &s->base);
}
-int grpc_client_setup_request_should_continue(grpc_client_setup_request *r) {
+int grpc_client_setup_request_should_continue(grpc_client_setup_request *r,
+ const char *reason) {
int result;
if (gpr_time_cmp(gpr_now(), r->deadline) > 0) {
- return 0;
+ result = 0;
+ } else {
+ gpr_mu_lock(&r->setup->mu);
+ result = r->setup->active_request == r;
+ gpr_mu_unlock(&r->setup->mu);
}
- gpr_mu_lock(&r->setup->mu);
- result = r->setup->active_request == r;
- gpr_mu_unlock(&r->setup->mu);
return result;
}
-static void backoff_alarm_done(void *arg /* grpc_client_setup */, int success) {
- grpc_client_setup *s = arg;
- grpc_client_setup_request *r = gpr_malloc(sizeof(grpc_client_setup_request));
- r->setup = s;
- /* TODO(klempner): Set this to something useful */
- r->deadline = gpr_inf_future;
+static void backoff_alarm_done(void *arg /* grpc_client_setup_request */,
+ int success) {
+ grpc_client_setup_request *r = arg;
+ grpc_client_setup *s = r->setup;
/* Handle status cancelled? */
gpr_mu_lock(&s->mu);
- s->active_request = r;
s->in_alarm = 0;
- if (!success) {
+ if (s->active_request != NULL || !success) {
if (0 == --s->refs) {
gpr_mu_unlock(&s->mu);
destroy_setup(s);
- gpr_free(r);
+ destroy_request(r);
return;
} else {
gpr_mu_unlock(&s->mu);
+ destroy_request(r);
return;
}
}
+ s->active_request = r;
gpr_mu_unlock(&s->mu);
s->initiate(s->user_data, r);
}
@@ -231,16 +266,12 @@ void grpc_client_setup_request_finish(grpc_client_setup_request *r,
} else {
retry = 0;
}
+
if (!retry && 0 == --s->refs) {
gpr_mu_unlock(&s->mu);
destroy_setup(s);
- gpr_free(r);
- return;
- }
-
- gpr_free(r);
-
- if (retry) {
+ destroy_request(r);
+ } else if (retry) {
/* TODO(klempner): Replace these values with further consideration. 2x is
probably too aggressive of a backoff. */
gpr_timespec max_backoff = gpr_time_from_minutes(2);
@@ -248,15 +279,17 @@ void grpc_client_setup_request_finish(grpc_client_setup_request *r,
gpr_timespec deadline = gpr_time_add(s->current_backoff_interval, now);
GPR_ASSERT(!s->in_alarm);
s->in_alarm = 1;
- grpc_alarm_init(&s->backoff_alarm, deadline, backoff_alarm_done, s, now);
+ grpc_alarm_init(&s->backoff_alarm, deadline, backoff_alarm_done, r, now);
s->current_backoff_interval =
gpr_time_add(s->current_backoff_interval, s->current_backoff_interval);
if (gpr_time_cmp(s->current_backoff_interval, max_backoff) > 0) {
s->current_backoff_interval = max_backoff;
}
+ gpr_mu_unlock(&s->mu);
+ } else {
+ gpr_mu_unlock(&s->mu);
+ destroy_request(r);
}
-
- gpr_mu_unlock(&s->mu);
}
const grpc_channel_args *grpc_client_setup_get_channel_args(
diff --git a/src/core/channel/client_setup.h b/src/core/channel/client_setup.h
index 70137e1365..7d40338840 100644
--- a/src/core/channel/client_setup.h
+++ b/src/core/channel/client_setup.h
@@ -52,7 +52,8 @@ void grpc_client_setup_create_and_attach(
/* Check that r is the active request: needs to be performed at each callback.
If this races, we'll have two connection attempts running at once and the
old one will get cleaned up in due course, which is fine. */
-int grpc_client_setup_request_should_continue(grpc_client_setup_request *r);
+int grpc_client_setup_request_should_continue(grpc_client_setup_request *r,
+ const char *reason);
void grpc_client_setup_request_finish(grpc_client_setup_request *r,
int was_successful);
const grpc_channel_args *grpc_client_setup_get_channel_args(
@@ -61,13 +62,16 @@ const grpc_channel_args *grpc_client_setup_get_channel_args(
/* Call before calling back into the setup listener, and call only if
this function returns 1. If it returns 1, also promise to call
grpc_client_setup_cb_end */
-int grpc_client_setup_cb_begin(grpc_client_setup_request *r);
-void grpc_client_setup_cb_end(grpc_client_setup_request *r);
+int grpc_client_setup_cb_begin(grpc_client_setup_request *r,
+ const char *reason);
+void grpc_client_setup_cb_end(grpc_client_setup_request *r, const char *reason);
/* Get the deadline for a request passed in to initiate. Implementations should
make a best effort to honor this deadline. */
gpr_timespec grpc_client_setup_request_deadline(grpc_client_setup_request *r);
+grpc_pollset_set *grpc_client_setup_get_interested_parties(
+ grpc_client_setup_request *r);
grpc_mdctx *grpc_client_setup_get_mdctx(grpc_client_setup_request *r);
-#endif /* GRPC_INTERNAL_CORE_CHANNEL_CLIENT_SETUP_H */
+#endif /* GRPC_INTERNAL_CORE_CHANNEL_CLIENT_SETUP_H */