Added connectivity tests, fixed bugs
diff --git a/src/core/channel/client_channel.c b/src/core/channel/client_channel.c
index b68954b..1234758 100644
--- a/src/core/channel/client_channel.c
+++ b/src/core/channel/client_channel.c
@@ -40,7 +40,6 @@
#include "src/core/channel/connected_channel.h"
#include "src/core/surface/channel.h"
#include "src/core/iomgr/iomgr.h"
-#include "src/core/iomgr/pollset_set.h"
#include "src/core/support/string.h"
#include "src/core/transport/connectivity_state.h"
#include <grpc/support/alloc.h>
@@ -79,8 +78,20 @@
grpc_connectivity_state_tracker state_tracker;
/** when an lb_policy arrives, should we try to exit idle */
int exit_idle_when_lb_policy_arrives;
+ /** pollset_set of interested parties in a new connection */
+ grpc_pollset_set pollset_set;
} channel_data;
+/** We create one watcher for each new lb_policy that is returned from a resolver,
+ to watch for state changes from the lb_policy. When a state change is seen, we
+ update the channel, and create a new watcher */
+typedef struct {
+ channel_data *chand;
+ grpc_iomgr_closure on_changed;
+ grpc_connectivity_state state;
+ grpc_lb_policy *lb_policy;
+} lb_policy_connectivity_watcher;
+
typedef enum {
CALL_CREATED,
CALL_WAITING_FOR_SEND,
@@ -394,17 +405,61 @@
perform_transport_stream_op(elem, op, 0);
}
+static void watch_lb_policy(channel_data *chand, grpc_lb_policy *lb_policy, grpc_connectivity_state current_state);
+
+static void on_lb_policy_state_changed(void *arg, int iomgr_success) {
+ lb_policy_connectivity_watcher *w = arg;
+ int start_new = 0;
+
+ gpr_log(GPR_DEBUG, "on_lb_policy_state_changed: %p %d", w->lb_policy, w->state);
+
+ gpr_mu_lock(&w->chand->mu_config);
+ /* check if the notification is for a stale policy */
+ if (w->lb_policy == w->chand->lb_policy) {
+ grpc_connectivity_state_set(&w->chand->state_tracker, w->state);
+ start_new = 1;
+ } else {
+ gpr_log(GPR_DEBUG, "stale state change: %p vs %p", w->lb_policy, w->chand->lb_policy);
+ }
+ gpr_mu_unlock(&w->chand->mu_config);
+
+ if (start_new) {
+ watch_lb_policy(w->chand, w->lb_policy, w->state);
+ }
+
+ GRPC_CHANNEL_INTERNAL_UNREF(w->chand->master, "watch_lb_policy");
+ gpr_free(w);
+}
+
+static void watch_lb_policy(channel_data *chand, grpc_lb_policy *lb_policy, grpc_connectivity_state current_state) {
+ lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
+ GRPC_CHANNEL_INTERNAL_REF(chand->master, "watch_lb_policy");
+
+ gpr_log(GPR_DEBUG, "watch_lb_policy: %p %d", lb_policy, current_state);
+
+ w->chand = chand;
+ grpc_iomgr_closure_init(&w->on_changed, on_lb_policy_state_changed, w);
+ w->state = current_state;
+ w->lb_policy = lb_policy;
+ grpc_lb_policy_notify_on_state_change(lb_policy, &w->state, &w->on_changed);
+}
+
static void cc_on_config_changed(void *arg, int iomgr_success) {
channel_data *chand = arg;
grpc_lb_policy *lb_policy = NULL;
grpc_lb_policy *old_lb_policy;
grpc_resolver *old_resolver;
grpc_iomgr_closure *wakeup_closures = NULL;
+ grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
int exit_idle = 0;
if (chand->incoming_configuration != NULL) {
lb_policy = grpc_client_config_get_lb_policy(chand->incoming_configuration);
- GRPC_LB_POLICY_REF(lb_policy, "channel");
+ if (lb_policy != NULL) {
+ GRPC_LB_POLICY_REF(lb_policy, "channel");
+ GRPC_LB_POLICY_REF(lb_policy, "config_change");
+ state = grpc_lb_policy_check_connectivity(lb_policy);
+ }
grpc_client_config_unref(chand->incoming_configuration);
}
@@ -423,18 +478,7 @@
exit_idle = 1;
chand->exit_idle_when_lb_policy_arrives = 0;
}
- gpr_mu_unlock(&chand->mu_config);
- if (exit_idle) {
- grpc_lb_policy_exit_idle(lb_policy);
- GRPC_LB_POLICY_UNREF(lb_policy, "exit_idle");
- }
-
- if (old_lb_policy) {
- GRPC_LB_POLICY_UNREF(old_lb_policy, "channel");
- }
-
- gpr_mu_lock(&chand->mu_config);
if (iomgr_success && chand->resolver) {
grpc_resolver *resolver = chand->resolver;
GRPC_RESOLVER_REF(resolver, "channel-next");
@@ -443,6 +487,10 @@
grpc_resolver_next(resolver, &chand->incoming_configuration,
&chand->on_config_changed);
GRPC_RESOLVER_UNREF(resolver, "channel-next");
+ grpc_connectivity_state_set(&chand->state_tracker, state);
+ if (lb_policy != NULL) {
+ watch_lb_policy(chand, lb_policy, state);
+ }
} else {
old_resolver = chand->resolver;
chand->resolver = NULL;
@@ -455,12 +503,24 @@
}
}
+ if (exit_idle) {
+ grpc_lb_policy_exit_idle(lb_policy);
+ GRPC_LB_POLICY_UNREF(lb_policy, "exit_idle");
+ }
+
+ if (old_lb_policy != NULL) {
+ GRPC_LB_POLICY_UNREF(old_lb_policy, "channel");
+ }
+
while (wakeup_closures) {
grpc_iomgr_closure *next = wakeup_closures->next;
grpc_iomgr_add_callback(wakeup_closures);
wakeup_closures = next;
}
+ if (lb_policy != NULL) {
+ GRPC_LB_POLICY_UNREF(lb_policy, "config_change");
+ }
GRPC_CHANNEL_INTERNAL_UNREF(chand->master, "resolver");
}
@@ -491,6 +551,8 @@
chand->resolver = NULL;
if (chand->lb_policy != NULL) {
grpc_lb_policy_shutdown(chand->lb_policy);
+ GRPC_LB_POLICY_UNREF(chand->lb_policy, "channel");
+ chand->lb_policy = NULL;
}
}
@@ -578,10 +640,11 @@
gpr_mu_init(&chand->mu_config);
chand->mdctx = metadata_context;
chand->master = master;
+ grpc_pollset_set_init(&chand->pollset_set);
grpc_iomgr_closure_init(&chand->on_config_changed, cc_on_config_changed,
chand);
- grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE);
+ grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE, "client_channel");
}
/* Destructor for channel_data */
@@ -595,6 +658,8 @@
if (chand->lb_policy != NULL) {
GRPC_LB_POLICY_UNREF(chand->lb_policy, "channel");
}
+ grpc_connectivity_state_destroy(&chand->state_tracker);
+ grpc_pollset_set_destroy(&chand->pollset_set);
gpr_mu_destroy(&chand->mu_config);
}
@@ -649,3 +714,20 @@
on_complete);
gpr_mu_unlock(&chand->mu_config);
}
+
+grpc_pollset_set *grpc_client_channel_get_connecting_pollset_set(grpc_channel_element *elem) {
+ channel_data *chand = elem->channel_data;
+ return &chand->pollset_set;
+}
+
+void grpc_client_channel_add_interested_party(grpc_channel_element *elem,
+ grpc_pollset *pollset) {
+ channel_data *chand = elem->channel_data;
+ grpc_pollset_set_add_pollset(&chand->pollset_set, pollset);
+}
+
+void grpc_client_channel_del_interested_party(grpc_channel_element *elem,
+ grpc_pollset *pollset) {
+ channel_data *chand = elem->channel_data;
+ grpc_pollset_set_del_pollset(&chand->pollset_set, pollset);
+}