|
|
|
@ -49,34 +49,37 @@ static gpr_avl g_subchannel_index; |
|
|
|
|
static gpr_mu g_mu; |
|
|
|
|
|
|
|
|
|
struct grpc_subchannel_key { |
|
|
|
|
grpc_connector *connector; |
|
|
|
|
grpc_subchannel_args args; |
|
|
|
|
grpc_connector *connector; |
|
|
|
|
grpc_subchannel_args args; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
GPR_TLS_DECL(subchannel_index_exec_ctx); |
|
|
|
|
|
|
|
|
|
static void enter_ctx(grpc_exec_ctx *exec_ctx) { |
|
|
|
|
GPR_ASSERT(gpr_tls_get(&subchannel_index_exec_ctx) == 0); |
|
|
|
|
gpr_tls_set(&subchannel_index_exec_ctx, (intptr_t)exec_ctx); |
|
|
|
|
GPR_ASSERT(gpr_tls_get(&subchannel_index_exec_ctx) == 0); |
|
|
|
|
gpr_tls_set(&subchannel_index_exec_ctx, (intptr_t)exec_ctx); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void leave_ctx(grpc_exec_ctx *exec_ctx) { |
|
|
|
|
GPR_ASSERT(gpr_tls_get(&subchannel_index_exec_ctx) == (intptr_t)exec_ctx); |
|
|
|
|
gpr_tls_set(&subchannel_index_exec_ctx, 0); |
|
|
|
|
GPR_ASSERT(gpr_tls_get(&subchannel_index_exec_ctx) == (intptr_t)exec_ctx); |
|
|
|
|
gpr_tls_set(&subchannel_index_exec_ctx, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static grpc_exec_ctx *current_ctx() { |
|
|
|
|
grpc_exec_ctx *c = (grpc_exec_ctx *)gpr_tls_get(&subchannel_index_exec_ctx); |
|
|
|
|
GPR_ASSERT(c != NULL); |
|
|
|
|
return c; |
|
|
|
|
grpc_exec_ctx *c = (grpc_exec_ctx *)gpr_tls_get(&subchannel_index_exec_ctx); |
|
|
|
|
GPR_ASSERT(c != NULL); |
|
|
|
|
return c; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static grpc_subchannel_key *create_key(grpc_connector *connector, grpc_subchannel_args *args, grpc_channel_args *(*copy_channel_args)(const grpc_channel_args *args)) { |
|
|
|
|
static grpc_subchannel_key *create_key( |
|
|
|
|
grpc_connector *connector, grpc_subchannel_args *args, |
|
|
|
|
grpc_channel_args *(*copy_channel_args)(const grpc_channel_args *args)) { |
|
|
|
|
grpc_subchannel_key *k = gpr_malloc(sizeof(*k)); |
|
|
|
|
k->connector = grpc_connector_ref(connector); |
|
|
|
|
k->args.filter_count = args->filter_count; |
|
|
|
|
k->args.filters = gpr_malloc(sizeof(*k->args.filters) * k->args.filter_count); |
|
|
|
|
memcpy(k->args.filters, args->filters, sizeof(*k->args.filters) * k->args.filter_count); |
|
|
|
|
memcpy(k->args.filters, args->filters, |
|
|
|
|
sizeof(*k->args.filters) * k->args.filter_count); |
|
|
|
|
k->args.addr_len = args->addr_len; |
|
|
|
|
k->args.addr = gpr_malloc(args->addr_len); |
|
|
|
|
memcpy(k->args.addr, args->addr, k->args.addr_len); |
|
|
|
@ -84,15 +87,17 @@ static grpc_subchannel_key *create_key(grpc_connector *connector, grpc_subchanne |
|
|
|
|
return k; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_subchannel_key *grpc_subchannel_key_create(grpc_connector *connector, grpc_subchannel_args *args) { |
|
|
|
|
return create_key(connector, args, grpc_channel_args_normalize); |
|
|
|
|
grpc_subchannel_key *grpc_subchannel_key_create(grpc_connector *connector, |
|
|
|
|
grpc_subchannel_args *args) { |
|
|
|
|
return create_key(connector, args, grpc_channel_args_normalize); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static grpc_subchannel_key *subchannel_key_copy(grpc_subchannel_key *k) { |
|
|
|
|
return create_key(k->connector, &k->args, grpc_channel_args_copy); |
|
|
|
|
return create_key(k->connector, &k->args, grpc_channel_args_copy); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int subchannel_key_compare(grpc_subchannel_key *a, grpc_subchannel_key *b) { |
|
|
|
|
static int subchannel_key_compare(grpc_subchannel_key *a, |
|
|
|
|
grpc_subchannel_key *b) { |
|
|
|
|
int c = GPR_ICMP(a->connector, b->connector); |
|
|
|
|
if (c != 0) return c; |
|
|
|
|
c = GPR_ICMP(a->args.addr_len, b->args.addr_len); |
|
|
|
@ -101,137 +106,131 @@ static int subchannel_key_compare(grpc_subchannel_key *a, grpc_subchannel_key *b |
|
|
|
|
if (c != 0) return c; |
|
|
|
|
c = memcmp(a->args.addr, b->args.addr, a->args.addr_len); |
|
|
|
|
if (c != 0) return c; |
|
|
|
|
c = memcmp(a->args.filters, b->args.filters, a->args.filter_count * sizeof(*a->args.filters)); |
|
|
|
|
c = memcmp(a->args.filters, b->args.filters, |
|
|
|
|
a->args.filter_count * sizeof(*a->args.filters)); |
|
|
|
|
return grpc_channel_args_compare(a->args.args, b->args.args); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_subchannel_key_destroy(grpc_subchannel_key *k) { |
|
|
|
|
gpr_free(k->args.addr); |
|
|
|
|
gpr_free(k->args.filters); |
|
|
|
|
grpc_channel_args_destroy((grpc_channel_args*)k->args.args); |
|
|
|
|
grpc_channel_args_destroy((grpc_channel_args *)k->args.args); |
|
|
|
|
gpr_free(k); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void sck_avl_destroy(void *p) { |
|
|
|
|
grpc_subchannel_key_destroy(p); |
|
|
|
|
} |
|
|
|
|
static void sck_avl_destroy(void *p) { grpc_subchannel_key_destroy(p); } |
|
|
|
|
|
|
|
|
|
static void *sck_avl_copy(void *p) { |
|
|
|
|
return subchannel_key_copy(p); |
|
|
|
|
} |
|
|
|
|
static void *sck_avl_copy(void *p) { return subchannel_key_copy(p); } |
|
|
|
|
|
|
|
|
|
static long sck_avl_compare(void *a, void *b) { |
|
|
|
|
return subchannel_key_compare(a, b); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void scv_avl_destroy(void *p) { |
|
|
|
|
grpc_exec_ctx *exec_ctx = current_ctx(); |
|
|
|
|
grpc_exec_ctx *exec_ctx = current_ctx(); |
|
|
|
|
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, p, "subchannel_index"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void *scv_avl_copy(void *p) {
|
|
|
|
|
static void *scv_avl_copy(void *p) { |
|
|
|
|
GRPC_SUBCHANNEL_WEAK_REF(p, "subchannel_index"); |
|
|
|
|
return p;
|
|
|
|
|
return p; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static const gpr_avl_vtable subchannel_avl_vtable = { |
|
|
|
|
.destroy_key = sck_avl_destroy, |
|
|
|
|
.copy_key = sck_avl_copy, |
|
|
|
|
.compare_keys = sck_avl_compare, |
|
|
|
|
.destroy_value = scv_avl_destroy, |
|
|
|
|
.copy_value = scv_avl_copy
|
|
|
|
|
}; |
|
|
|
|
.destroy_key = sck_avl_destroy, |
|
|
|
|
.copy_key = sck_avl_copy, |
|
|
|
|
.compare_keys = sck_avl_compare, |
|
|
|
|
.destroy_value = scv_avl_destroy, |
|
|
|
|
.copy_value = scv_avl_copy}; |
|
|
|
|
|
|
|
|
|
void grpc_subchannel_index_init(void) { |
|
|
|
|
g_subchannel_index = gpr_avl_create(&subchannel_avl_vtable); |
|
|
|
|
gpr_mu_init(&g_mu); |
|
|
|
|
g_subchannel_index = gpr_avl_create(&subchannel_avl_vtable); |
|
|
|
|
gpr_mu_init(&g_mu); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_subchannel_index_shutdown(void) { |
|
|
|
|
gpr_mu_destroy(&g_mu); |
|
|
|
|
gpr_avl_unref(g_subchannel_index); |
|
|
|
|
gpr_mu_destroy(&g_mu); |
|
|
|
|
gpr_avl_unref(g_subchannel_index); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_subchannel *grpc_subchannel_index_find( |
|
|
|
|
grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_subchannel_key *key) { |
|
|
|
|
enter_ctx(exec_ctx); |
|
|
|
|
grpc_subchannel *grpc_subchannel_index_find(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_subchannel_key *key) { |
|
|
|
|
enter_ctx(exec_ctx); |
|
|
|
|
|
|
|
|
|
gpr_mu_lock(&g_mu); |
|
|
|
|
gpr_avl index = gpr_avl_ref(g_subchannel_index); |
|
|
|
|
gpr_mu_unlock(&g_mu); |
|
|
|
|
gpr_mu_lock(&g_mu); |
|
|
|
|
gpr_avl index = gpr_avl_ref(g_subchannel_index); |
|
|
|
|
gpr_mu_unlock(&g_mu); |
|
|
|
|
|
|
|
|
|
grpc_subchannel *c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(gpr_avl_get(index, key), "index_find"); |
|
|
|
|
gpr_avl_unref(index); |
|
|
|
|
grpc_subchannel *c = |
|
|
|
|
GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(gpr_avl_get(index, key), "index_find"); |
|
|
|
|
gpr_avl_unref(index); |
|
|
|
|
|
|
|
|
|
leave_ctx(exec_ctx); |
|
|
|
|
return c; |
|
|
|
|
leave_ctx(exec_ctx); |
|
|
|
|
return c; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_subchannel *grpc_subchannel_index_register( |
|
|
|
|
grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_subchannel_key *key,
|
|
|
|
|
grpc_subchannel *constructed) { |
|
|
|
|
enter_ctx(exec_ctx); |
|
|
|
|
grpc_subchannel *grpc_subchannel_index_register(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_subchannel_key *key, |
|
|
|
|
grpc_subchannel *constructed) { |
|
|
|
|
enter_ctx(exec_ctx); |
|
|
|
|
|
|
|
|
|
grpc_subchannel *c = NULL; |
|
|
|
|
grpc_subchannel *c = NULL; |
|
|
|
|
|
|
|
|
|
while (c == NULL) { |
|
|
|
|
gpr_mu_lock(&g_mu); |
|
|
|
|
gpr_avl index = gpr_avl_ref(g_subchannel_index); |
|
|
|
|
gpr_mu_unlock(&g_mu); |
|
|
|
|
while (c == NULL) { |
|
|
|
|
gpr_mu_lock(&g_mu); |
|
|
|
|
gpr_avl index = gpr_avl_ref(g_subchannel_index); |
|
|
|
|
gpr_mu_unlock(&g_mu); |
|
|
|
|
|
|
|
|
|
c = gpr_avl_get(index, key); |
|
|
|
|
if (c != NULL) { |
|
|
|
|
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, constructed, "index_register"); |
|
|
|
|
} else { |
|
|
|
|
gpr_avl updated = gpr_avl_add(index, key, constructed); |
|
|
|
|
c = gpr_avl_get(index, key); |
|
|
|
|
if (c != NULL) { |
|
|
|
|
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, constructed, "index_register"); |
|
|
|
|
} else { |
|
|
|
|
gpr_avl updated = gpr_avl_add(index, key, constructed); |
|
|
|
|
|
|
|
|
|
gpr_mu_lock(&g_mu); |
|
|
|
|
if (index.root == g_subchannel_index.root) { |
|
|
|
|
GPR_SWAP(gpr_avl, updated, g_subchannel_index); |
|
|
|
|
c = constructed; |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&g_mu); |
|
|
|
|
} |
|
|
|
|
gpr_avl_unref(index); |
|
|
|
|
} |
|
|
|
|
gpr_mu_lock(&g_mu); |
|
|
|
|
if (index.root == g_subchannel_index.root) { |
|
|
|
|
GPR_SWAP(gpr_avl, updated, g_subchannel_index); |
|
|
|
|
c = constructed; |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&g_mu); |
|
|
|
|
} |
|
|
|
|
gpr_avl_unref(index); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
leave_ctx(exec_ctx); |
|
|
|
|
leave_ctx(exec_ctx); |
|
|
|
|
|
|
|
|
|
return c; |
|
|
|
|
return c; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_subchannel_index_unregister( |
|
|
|
|
grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_subchannel_key *key, |
|
|
|
|
grpc_subchannel *constructed) { |
|
|
|
|
enter_ctx(exec_ctx); |
|
|
|
|
void grpc_subchannel_index_unregister(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_subchannel_key *key, |
|
|
|
|
grpc_subchannel *constructed) { |
|
|
|
|
enter_ctx(exec_ctx); |
|
|
|
|
|
|
|
|
|
bool done = false; |
|
|
|
|
while (!done) { |
|
|
|
|
gpr_mu_lock(&g_mu); |
|
|
|
|
gpr_avl index = gpr_avl_ref(g_subchannel_index); |
|
|
|
|
gpr_mu_unlock(&g_mu); |
|
|
|
|
bool done = false; |
|
|
|
|
while (!done) { |
|
|
|
|
gpr_mu_lock(&g_mu); |
|
|
|
|
gpr_avl index = gpr_avl_ref(g_subchannel_index); |
|
|
|
|
gpr_mu_unlock(&g_mu); |
|
|
|
|
|
|
|
|
|
grpc_subchannel *c = gpr_avl_get(index, key); |
|
|
|
|
if (c != constructed) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
grpc_subchannel *c = gpr_avl_get(index, key); |
|
|
|
|
if (c != constructed) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
gpr_avl updated = gpr_avl_remove(index, key); |
|
|
|
|
gpr_avl updated = gpr_avl_remove(index, key); |
|
|
|
|
|
|
|
|
|
gpr_mu_lock(&g_mu); |
|
|
|
|
if (index.root == g_subchannel_index.root) { |
|
|
|
|
GPR_SWAP(gpr_avl, updated, g_subchannel_index); |
|
|
|
|
done = true; |
|
|
|
|
} else { |
|
|
|
|
GPR_SWAP(gpr_avl, updated, index); |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&g_mu); |
|
|
|
|
gpr_mu_lock(&g_mu); |
|
|
|
|
if (index.root == g_subchannel_index.root) { |
|
|
|
|
GPR_SWAP(gpr_avl, updated, g_subchannel_index); |
|
|
|
|
done = true; |
|
|
|
|
} else { |
|
|
|
|
GPR_SWAP(gpr_avl, updated, index); |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&g_mu); |
|
|
|
|
|
|
|
|
|
gpr_avl_unref(index); |
|
|
|
|
} |
|
|
|
|
gpr_avl_unref(index); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
leave_ctx(exec_ctx); |
|
|
|
|
leave_ctx(exec_ctx); |
|
|
|
|
} |
|
|
|
|