|
|
|
@ -1,35 +1,35 @@ |
|
|
|
|
/*
|
|
|
|
|
* |
|
|
|
|
* 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. |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
// Copyright 2016, 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.
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
#include "src/core/client_config/subchannel_index.h" |
|
|
|
|
|
|
|
|
@ -42,8 +42,8 @@ |
|
|
|
|
|
|
|
|
|
#include "src/core/channel/channel_args.h" |
|
|
|
|
|
|
|
|
|
/* a map of subchannel_key --> subchannel, used for detecting connections
|
|
|
|
|
to the same destination in order to share them */ |
|
|
|
|
// 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; |
|
|
|
@ -111,14 +111,18 @@ static int subchannel_key_compare(grpc_subchannel_key *a, |
|
|
|
|
return grpc_channel_args_compare(a->args.args, b->args.args); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_subchannel_key_destroy(grpc_subchannel_key *k) { |
|
|
|
|
void grpc_subchannel_key_destroy(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_subchannel_key *k) { |
|
|
|
|
grpc_connector_unref(exec_ctx, k->connector); |
|
|
|
|
gpr_free(k->args.addr); |
|
|
|
|
gpr_free(k->args.filters); |
|
|
|
|
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(current_ctx(), p); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void *sck_avl_copy(void *p) { return subchannel_key_copy(p); } |
|
|
|
|
|
|
|
|
@ -127,8 +131,7 @@ static long sck_avl_compare(void *a, void *b) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void scv_avl_destroy(void *p) { |
|
|
|
|
grpc_exec_ctx *exec_ctx = current_ctx(); |
|
|
|
|
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, p, "subchannel_index"); |
|
|
|
|
GRPC_SUBCHANNEL_WEAK_UNREF(current_ctx(), p, "subchannel_index"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void *scv_avl_copy(void *p) { |
|
|
|
@ -157,6 +160,8 @@ grpc_subchannel *grpc_subchannel_index_find(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_subchannel_key *key) { |
|
|
|
|
enter_ctx(exec_ctx); |
|
|
|
|
|
|
|
|
|
// Lock, and take a reference to the subchannel index.
|
|
|
|
|
// We don't need to do the search under a lock as avl's are immutable.
|
|
|
|
|
gpr_mu_lock(&g_mu); |
|
|
|
|
gpr_avl index = gpr_avl_ref(g_subchannel_index); |
|
|
|
|
gpr_mu_unlock(&g_mu); |
|
|
|
@ -177,22 +182,34 @@ grpc_subchannel *grpc_subchannel_index_register(grpc_exec_ctx *exec_ctx, |
|
|
|
|
grpc_subchannel *c = NULL; |
|
|
|
|
|
|
|
|
|
while (c == NULL) { |
|
|
|
|
// Compare and swap loop:
|
|
|
|
|
// - take a reference to the current index
|
|
|
|
|
gpr_mu_lock(&g_mu); |
|
|
|
|
gpr_avl index = gpr_avl_ref(g_subchannel_index); |
|
|
|
|
gpr_mu_unlock(&g_mu); |
|
|
|
|
|
|
|
|
|
// - Check to see if a subchannel already exists
|
|
|
|
|
c = gpr_avl_get(index, key); |
|
|
|
|
if (c != NULL) { |
|
|
|
|
// yes -> we're done
|
|
|
|
|
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, constructed, "index_register"); |
|
|
|
|
} else { |
|
|
|
|
gpr_avl updated = gpr_avl_add(index, key, constructed); |
|
|
|
|
|
|
|
|
|
// no -> update the avl and compare/swap
|
|
|
|
|
gpr_avl updated = |
|
|
|
|
gpr_avl_add(gpr_avl_ref(index), subchannel_key_copy(key), |
|
|
|
|
GRPC_SUBCHANNEL_WEAK_REF(constructed, "index_register")); |
|
|
|
|
|
|
|
|
|
// it may happen (but it's expected to be unlikely)
|
|
|
|
|
// that some other thread has changed the index:
|
|
|
|
|
// compare/swap here to check that, and retry as necessary
|
|
|
|
|
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(updated); |
|
|
|
|
} |
|
|
|
|
gpr_avl_unref(index); |
|
|
|
|
} |
|
|
|
@ -209,26 +226,32 @@ void grpc_subchannel_index_unregister(grpc_exec_ctx *exec_ctx, |
|
|
|
|
|
|
|
|
|
bool done = false; |
|
|
|
|
while (!done) { |
|
|
|
|
// Compare and swap loop:
|
|
|
|
|
// - take a reference to the current index
|
|
|
|
|
gpr_mu_lock(&g_mu); |
|
|
|
|
gpr_avl index = gpr_avl_ref(g_subchannel_index); |
|
|
|
|
gpr_mu_unlock(&g_mu); |
|
|
|
|
|
|
|
|
|
// Check to see if this key still refers to the previously
|
|
|
|
|
// registered subchannel
|
|
|
|
|
grpc_subchannel *c = gpr_avl_get(index, key); |
|
|
|
|
if (c != constructed) { |
|
|
|
|
gpr_avl_unref(index); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
gpr_avl updated = gpr_avl_remove(index, key); |
|
|
|
|
// compare and swap the update (some other thread may have
|
|
|
|
|
// mutated the index behind us)
|
|
|
|
|
gpr_avl updated = gpr_avl_remove(gpr_avl_ref(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_avl_unref(updated); |
|
|
|
|
gpr_avl_unref(index); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|