From 694cf8b0d266f4fadcc5b52f1bfc6f2c0dd1ccb5 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 15 Jan 2016 21:13:25 -0800 Subject: Shared subchannel sketch --- src/core/client_config/subchannel.c | 1 + src/core/client_config/subchannel_index.c | 155 ++++++++++++++++++++++++++++++ src/core/client_config/subchannel_index.h | 39 ++++++++ src/core/surface/init.c | 3 + 4 files changed, 198 insertions(+) create mode 100644 src/core/client_config/subchannel_index.c create mode 100644 src/core/client_config/subchannel_index.h (limited to 'src/core') diff --git a/src/core/client_config/subchannel.c b/src/core/client_config/subchannel.c index 2992da8b79..9f287c4b03 100644 --- a/src/core/client_config/subchannel.c +++ b/src/core/client_config/subchannel.c @@ -36,6 +36,7 @@ #include #include +#include #include "src/core/channel/channel_args.h" #include "src/core/channel/client_channel.h" diff --git a/src/core/client_config/subchannel_index.c b/src/core/client_config/subchannel_index.c new file mode 100644 index 0000000000..ffe6c1fe93 --- /dev/null +++ b/src/core/client_config/subchannel_index.c @@ -0,0 +1,155 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* a map of subchannel_key --> subchannel, used for detecting connections + to the same destination in order to share them */ +static gpr_avl g_subchannel_index; + +static gpr_mu g_mu; + +struct subchannel_key { + size_t addr_len; + struct sockaddr *addr; + grpc_channel_args *normalized_args; +}; + +GPR_TLS_DECL(subchannel_index_exec_ctx); + +static subchannel_key *subchannel_key_create(struct sockaddr *sockaddr, size_t addr_len, grpc_channel_args *args) { + subchannel_key *k = gpr_malloc(sizeof(*k)); + k->addr_len = addr_len; + k->addr = gpr_malloc(addr_len); + memcpy(k->addr, addr, addr_len); + k->normalized_args = grpc_channel_args_normalize(args); + return k; +} + +static subchannel_key *subchannel_key_copy(subchannel_key *k) { + subchannel_key *k = gpr_malloc(sizeof(*k)); + k->addr_len = addr_len; + k->addr = gpr_malloc(addr_len); + memcpy(k->addr, addr, addr_len); + k->normalized_args = grpc_channel_args_copy(args); + return k; +} + +static int subchannel_key_compare(subchannel_key *a, subchannel_key *b) { + int c = GPR_ICMP(a->addr_len, b->addr_len); + if (c != 0) return c; + c = memcmp(a->addr, b->addr, a->addr_len); + if (c != 0) return c; + return grpc_channel_args_compare(a->normalized_args, b->normalized_args); +} + +static void subchannel_key_destroy(subchannel_key *k) { + gpr_free(k->addr); + grpc_channel_args_destroy(k->normalized_args); + gpr_free(k); +} + +static void sck_avl_destroy(void *p) { + subchannel_key_destroy(p); +} + +static void *sck_avl_copy(void *p) { + return subchannel_key_copy(p); +} + +static void *sck_avl_compare(void *a, void *b) { + return subchannel_key_compare(a, b); +} + +static void scv_avl_destroy(void *p) { + GRPC_SUBCHANNEL_UNREF(exec_ctx, p, "subchannel_index"); +} + +static void *scv_avl_copy(void *p) { + GRPC_SUBCHANNEL_REF(p, "subchannel_index"); + 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 +}; + +grpc_subchannel *grpc_subchannel_index_find( + grpc_exec_ctx *ctx, + grpc_connector *connector, + grpc_subchannel_args *args) { + gpr_mu_lock(&g_mu); + gpr_avl index = gpr_avl_ref(g_subchannel_index); + gpr_mu_unlock(&g_mu); + + subchannel_key *key = subchannel_key_create(connector, args); + grpc_subchannel *c = grpc_subchannel_ref(gpr_avl_get(index, key)); + subchannel_key_destroy(key); + gpr_avl_unref(index); + + return c; +} + +grpc_subchannel *grpc_subchannel_index_register( + grpc_exec_ctx *ctx, + grpc_connector *connector, + grpc_subchannel_args *args, + grpc_subchannel *constructed) { + subchannel_key *key = subchannel_key_create(connector, args); + 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); + + c = gpr_avl_get(index, key); + if (c != NULL) { + GRPC_SUBCHANNEL_UNREF(constructed); + } else { + gpr_avl updated = gpr_avl_add(index, key, constructed); + + gpr_mu_lock(&g_mu); + if (index.root == g_subchannel_index.root) { + GPR_SWAP(index, g_subchannel_index); + c = constructed; + } + gpr_mu_unlock(&g_mu); + } + gpr_avl_unref(index); + } + + return c; +} diff --git a/src/core/client_config/subchannel_index.h b/src/core/client_config/subchannel_index.h new file mode 100644 index 0000000000..d501e121f1 --- /dev/null +++ b/src/core/client_config/subchannel_index.h @@ -0,0 +1,39 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_INDEX_H +#define GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_INDEX_H + + + +#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_INDEX_H */ diff --git a/src/core/surface/init.c b/src/core/surface/init.c index 19cea4c4f6..8f1936227e 100644 --- a/src/core/surface/init.c +++ b/src/core/surface/init.c @@ -46,6 +46,7 @@ #include "src/core/client_config/resolver_registry.h" #include "src/core/client_config/resolvers/dns_resolver.h" #include "src/core/client_config/resolvers/sockaddr_resolver.h" +#include "src/core/client_config/subchannel.h" #include "src/core/debug/trace.h" #include "src/core/iomgr/executor.h" #include "src/core/iomgr/iomgr.h" @@ -125,6 +126,7 @@ void grpc_init(void) { } gpr_timers_global_init(); grpc_cq_global_init(); + grpc_subchannel_global_init(); for (i = 0; i < g_number_of_plugins; i++) { if (g_all_of_the_plugins[i].init != NULL) { g_all_of_the_plugins[i].init(); @@ -143,6 +145,7 @@ void grpc_shutdown(void) { grpc_executor_shutdown(); grpc_cq_global_shutdown(); grpc_iomgr_shutdown(); + grpc_subchannel_global_shutdown(); census_shutdown(); gpr_timers_global_destroy(); grpc_tracer_shutdown(); -- cgit v1.2.3