From 16883a37efa49ef2d58ea57c6dbbba66497f2232 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" <roth@google.com> Date: Fri, 21 Oct 2016 10:30:58 -0700 Subject: [PATCH] Set user data vtable when creating grpc_lb_addresses. --- .../ext/client_config/lb_policy_factory.c | 55 +++++++++++++++---- .../ext/client_config/lb_policy_factory.h | 23 ++++++-- src/core/ext/client_config/resolver_result.c | 2 +- src/core/ext/lb_policy/grpclb/grpclb.c | 27 ++++++--- .../ext/resolver/dns/native/dns_resolver.c | 4 +- .../ext/resolver/sockaddr/sockaddr_resolver.c | 10 ++-- test/core/end2end/fake_resolver.c | 10 ++-- 7 files changed, 93 insertions(+), 38 deletions(-) diff --git a/src/core/ext/client_config/lb_policy_factory.c b/src/core/ext/client_config/lb_policy_factory.c index c17af91a09..55e346180d 100644 --- a/src/core/ext/client_config/lb_policy_factory.c +++ b/src/core/ext/client_config/lb_policy_factory.c @@ -38,19 +38,20 @@ #include "src/core/ext/client_config/lb_policy_factory.h" -grpc_lb_addresses* grpc_lb_addresses_create(size_t num_addresses) { +grpc_lb_addresses* grpc_lb_addresses_create( + size_t num_addresses, const grpc_lb_user_data_vtable* user_data_vtable) { grpc_lb_addresses* addresses = gpr_malloc(sizeof(grpc_lb_addresses)); addresses->num_addresses = num_addresses; + addresses->user_data_vtable = user_data_vtable; const size_t addresses_size = sizeof(grpc_lb_address) * num_addresses; addresses->addresses = gpr_malloc(addresses_size); memset(addresses->addresses, 0, addresses_size); return addresses; } -grpc_lb_addresses* grpc_lb_addresses_copy(grpc_lb_addresses* addresses, - void* (*user_data_copy)(void*)) { - grpc_lb_addresses* new_addresses = - grpc_lb_addresses_create(addresses->num_addresses); +grpc_lb_addresses* grpc_lb_addresses_copy(const grpc_lb_addresses* addresses) { + grpc_lb_addresses* new_addresses = grpc_lb_addresses_create( + addresses->num_addresses, addresses->user_data_vtable); memcpy(new_addresses->addresses, addresses->addresses, sizeof(grpc_lb_address) * addresses->num_addresses); for (size_t i = 0; i < addresses->num_addresses; ++i) { @@ -58,9 +59,10 @@ grpc_lb_addresses* grpc_lb_addresses_copy(grpc_lb_addresses* addresses, new_addresses->addresses[i].balancer_name = gpr_strdup(new_addresses->addresses[i].balancer_name); } - if (user_data_copy != NULL) { + if (new_addresses->addresses[i].user_data != NULL) { new_addresses->addresses[i].user_data = - user_data_copy(new_addresses->addresses[i].user_data); + addresses->user_data_vtable->copy( + new_addresses->addresses[i].user_data); } } return new_addresses; @@ -71,6 +73,7 @@ void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index, bool is_balancer, char* balancer_name, void* user_data) { GPR_ASSERT(index < addresses->num_addresses); + if (user_data != NULL) GPR_ASSERT(addresses->user_data_vtable != NULL); grpc_lb_address* target = &addresses->addresses[index]; memcpy(target->address.addr, address, address_len); target->address.len = address_len; @@ -79,12 +82,42 @@ void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index, target->user_data = user_data; } -void grpc_lb_addresses_destroy(grpc_lb_addresses* addresses, - void (*user_data_destroy)(void*)) { +int grpc_lb_addresses_cmp(const grpc_lb_addresses* addresses1, + const grpc_lb_addresses* addresses2) { + if (addresses1->num_addresses > addresses2->num_addresses) return 1; + if (addresses1->num_addresses < addresses2->num_addresses) return -1; + if (addresses1->user_data_vtable > addresses2->user_data_vtable) return 1; + if (addresses1->user_data_vtable < addresses2->user_data_vtable) return -1; + for (size_t i = 0; i < addresses1->num_addresses; ++i) { + const grpc_lb_address* target1 = &addresses1->addresses[i]; + const grpc_lb_address* target2 = &addresses2->addresses[i]; + if (target1->address.len > target2->address.len) return 1; + if (target1->address.len < target2->address.len) return -1; + int retval = memcmp( + target1->address.addr, target2->address.addr, target1->address.len); + if (retval != 0) return retval; + if (target1->is_balancer > target2->is_balancer) return 1; + if (target1->is_balancer < target2->is_balancer) return -1; + const char* balancer_name1 = target1->balancer_name != NULL + ? target1->balancer_name : ""; + const char* balancer_name2 = target2->balancer_name != NULL + ? target2->balancer_name : ""; + retval = strcmp(balancer_name1, balancer_name2); + if (retval != 0) return retval; + if (addresses1->user_data_vtable != NULL) { + retval = addresses1->user_data_vtable->cmp(target1->user_data, + target2->user_data); + if (retval != 0) return retval; + } + } + return 0; +} + +void grpc_lb_addresses_destroy(grpc_lb_addresses* addresses) { for (size_t i = 0; i < addresses->num_addresses; ++i) { gpr_free(addresses->addresses[i].balancer_name); - if (user_data_destroy != NULL) { - user_data_destroy(addresses->addresses[i].user_data); + if (addresses->addresses[i].user_data != NULL) { + addresses->user_data_vtable->destroy(addresses->addresses[i].user_data); } } gpr_free(addresses->addresses); diff --git a/src/core/ext/client_config/lb_policy_factory.h b/src/core/ext/client_config/lb_policy_factory.h index 4e11501e01..61c3f419d1 100644 --- a/src/core/ext/client_config/lb_policy_factory.h +++ b/src/core/ext/client_config/lb_policy_factory.h @@ -59,19 +59,27 @@ typedef struct grpc_lb_address { void *user_data; } grpc_lb_address; +typedef struct grpc_lb_user_data_vtable { + void* (*copy)(void*); + void (*destroy)(void*); + int (*cmp)(void*, void*); +} grpc_lb_user_data_vtable; + typedef struct grpc_lb_addresses { size_t num_addresses; grpc_lb_address *addresses; + const grpc_lb_user_data_vtable *user_data_vtable; } grpc_lb_addresses; /** Returns a grpc_addresses struct with enough space for - * \a num_addresses addresses. */ -grpc_lb_addresses *grpc_lb_addresses_create(size_t num_addresses); + \a num_addresses addresses. The \a user_data_vtable argument may be + NULL if no user data will be added. */ +grpc_lb_addresses *grpc_lb_addresses_create( + size_t num_addresses, const grpc_lb_user_data_vtable* user_data_vtable); /** Creates a copy of \a addresses. If \a user_data_copy is not NULL, * it will be invoked to copy the \a user_data field of each address. */ -grpc_lb_addresses *grpc_lb_addresses_copy(grpc_lb_addresses *addresses, - void *(*user_data_copy)(void *)); +grpc_lb_addresses *grpc_lb_addresses_copy(const grpc_lb_addresses *addresses); /** Sets the value of the address at index \a index of \a addresses. * \a address is a socket address of length \a address_len. @@ -81,10 +89,13 @@ void grpc_lb_addresses_set_address(grpc_lb_addresses *addresses, size_t index, bool is_balancer, char *balancer_name, void *user_data); +/** Compares \a addresses1 and \a addresses2. */ +int grpc_lb_addresses_cmp(const grpc_lb_addresses *addresses1, + const grpc_lb_addresses *addresses2); + /** Destroys \a addresses. If \a user_data_destroy is not NULL, it will * be invoked to destroy the \a user_data field of each address. */ -void grpc_lb_addresses_destroy(grpc_lb_addresses *addresses, - void (*user_data_destroy)(void *)); +void grpc_lb_addresses_destroy(grpc_lb_addresses *addresses); /** Arguments passed to LB policies. */ /* TODO(roth, ctiller): Consider replacing this struct with diff --git a/src/core/ext/client_config/resolver_result.c b/src/core/ext/client_config/resolver_result.c index 5f3600e7d9..e6a6f2da62 100644 --- a/src/core/ext/client_config/resolver_result.c +++ b/src/core/ext/client_config/resolver_result.c @@ -67,7 +67,7 @@ void grpc_resolver_result_unref(grpc_exec_ctx* exec_ctx, grpc_resolver_result* result) { if (gpr_unref(&result->refs)) { gpr_free(result->server_name); - grpc_lb_addresses_destroy(result->addresses, NULL /* user_data_destroy */); + grpc_lb_addresses_destroy(result->addresses); gpr_free(result->lb_policy_name); grpc_channel_args_destroy(result->channel_args); gpr_free(result); diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c index 663f1d3300..1467508d6d 100644 --- a/src/core/ext/lb_policy/grpclb/grpclb.c +++ b/src/core/ext/lb_policy/grpclb/grpclb.c @@ -338,6 +338,21 @@ static bool is_server_valid(const grpc_grpclb_server *server, size_t idx, return true; } +/* vtable for LB tokens in grpc_lb_addresses. */ +static void* lb_token_copy(void *token) { + return token == NULL ? NULL : GRPC_MDELEM_REF(token); +} +static void lb_token_destroy(void *token) { + if (token != NULL) GRPC_MDELEM_UNREF(token); +} +static int lb_token_cmp(void* token1, void* token2) { + if (token1 > token2) return 1; + if (token1 < token2) return -1; + return 0; +} +static const grpc_lb_user_data_vtable lb_token_vtable = { + lb_token_copy, lb_token_destroy, lb_token_cmp}; + /* Returns addresses extracted from \a serverlist. */ static grpc_lb_addresses *process_serverlist( const grpc_grpclb_serverlist *serverlist) { @@ -349,7 +364,8 @@ static grpc_lb_addresses *process_serverlist( } if (num_valid == 0) return NULL; - grpc_lb_addresses *lb_addresses = grpc_lb_addresses_create(num_valid); + grpc_lb_addresses *lb_addresses = + grpc_lb_addresses_create(num_valid, &lb_token_vtable); /* second pass: actually populate the addresses and LB tokens (aka user data * to the outside world) to be read by the RR policy during its creation. @@ -410,11 +426,6 @@ static grpc_lb_addresses *process_serverlist( return lb_addresses; } -/* A plugin for grpc_lb_addresses_destroy that unrefs the LB token metadata. */ -static void lb_token_destroy(void *token) { - if (token != NULL) GRPC_MDELEM_UNREF(token); -} - /* perform a pick over \a rr_policy. Given that a pick can return immediately * (ignoring its completion callback) we need to perform the cleanups this * callback would be otherwise resposible for */ @@ -465,7 +476,7 @@ static grpc_lb_policy *create_rr_locked( if (glb_policy->addresses != NULL) { /* dispose of the previous version */ - grpc_lb_addresses_destroy(glb_policy->addresses, lb_token_destroy); + grpc_lb_addresses_destroy(glb_policy->addresses); } glb_policy->addresses = args.addresses; @@ -662,7 +673,7 @@ static void glb_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { grpc_grpclb_destroy_serverlist(glb_policy->serverlist); } gpr_mu_destroy(&glb_policy->mu); - grpc_lb_addresses_destroy(glb_policy->addresses, lb_token_destroy); + grpc_lb_addresses_destroy(glb_policy->addresses); gpr_free(glb_policy); } diff --git a/src/core/ext/resolver/dns/native/dns_resolver.c b/src/core/ext/resolver/dns/native/dns_resolver.c index a4f6ed8c4e..0694d8b6b7 100644 --- a/src/core/ext/resolver/dns/native/dns_resolver.c +++ b/src/core/ext/resolver/dns/native/dns_resolver.c @@ -170,8 +170,8 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg, GPR_ASSERT(r->resolving); r->resolving = false; if (r->addresses != NULL) { - grpc_lb_addresses *addresses = - grpc_lb_addresses_create(r->addresses->naddrs); + grpc_lb_addresses *addresses = grpc_lb_addresses_create( + r->addresses->naddrs, NULL /* user_data_vtable */); for (size_t i = 0; i < r->addresses->naddrs; ++i) { grpc_lb_addresses_set_address( addresses, i, &r->addresses->addrs[i].addr, diff --git a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c index eaaa2e47c2..d34094f8e8 100644 --- a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c +++ b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c @@ -121,8 +121,7 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx, if (r->next_completion != NULL && !r->published) { r->published = true; *r->target_result = grpc_resolver_result_create( - r->target_name, - grpc_lb_addresses_copy(r->addresses, NULL /* user_data_copy */), + r->target_name, grpc_lb_addresses_copy(r->addresses), NULL /* lb_policy_name */, grpc_channel_args_copy(r->channel_args)); grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL); r->next_completion = NULL; @@ -133,7 +132,7 @@ static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) { sockaddr_resolver *r = (sockaddr_resolver *)gr; gpr_mu_destroy(&r->mu); gpr_free(r->target_name); - grpc_lb_addresses_destroy(r->addresses, NULL /* user_data_destroy */); + grpc_lb_addresses_destroy(r->addresses); grpc_channel_args_destroy(r->channel_args); gpr_free(r); } @@ -178,7 +177,8 @@ static grpc_resolver *sockaddr_create(grpc_resolver_args *args, gpr_slice_buffer path_parts; gpr_slice_buffer_init(&path_parts); gpr_slice_split(path_slice, ",", &path_parts); - grpc_lb_addresses *addresses = grpc_lb_addresses_create(path_parts.count); + grpc_lb_addresses *addresses = grpc_lb_addresses_create( + path_parts.count, NULL /* user_data_vtable */); bool errors_found = false; for (size_t i = 0; i < addresses->num_addresses; i++) { grpc_uri ith_uri = *args->uri; @@ -196,7 +196,7 @@ static grpc_resolver *sockaddr_create(grpc_resolver_args *args, gpr_slice_buffer_destroy(&path_parts); gpr_slice_unref(path_slice); if (errors_found) { - grpc_lb_addresses_destroy(addresses, NULL /* user_data_destroy */); + grpc_lb_addresses_destroy(addresses); return NULL; } /* Instantiate resolver. */ diff --git a/test/core/end2end/fake_resolver.c b/test/core/end2end/fake_resolver.c index 32dc9e2711..67337f4f84 100644 --- a/test/core/end2end/fake_resolver.c +++ b/test/core/end2end/fake_resolver.c @@ -78,7 +78,7 @@ static void fake_resolver_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* gr) { fake_resolver* r = (fake_resolver*)gr; gpr_mu_destroy(&r->mu); gpr_free(r->target_name); - grpc_lb_addresses_destroy(r->addresses, NULL /* user_data_destroy */); + grpc_lb_addresses_destroy(r->addresses); gpr_free(r->lb_policy_name); grpc_method_config_table_unref(r->method_config_table); gpr_free(r); @@ -107,8 +107,7 @@ static void fake_resolver_maybe_finish_next_locked(grpc_exec_ctx* exec_ctx, lb_policy_args = grpc_channel_args_copy_and_add(NULL /* src */, &arg, 1); } *r->target_result = grpc_resolver_result_create( - r->target_name, - grpc_lb_addresses_copy(r->addresses, NULL /* user_data_copy */), + r->target_name, grpc_lb_addresses_copy(r->addresses), r->lb_policy_name, lb_policy_args); grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL); r->next_completion = NULL; @@ -168,7 +167,8 @@ static grpc_resolver* fake_resolver_create(grpc_resolver_factory* factory, gpr_slice_buffer path_parts; gpr_slice_buffer_init(&path_parts); gpr_slice_split(path_slice, ",", &path_parts); - grpc_lb_addresses* addresses = grpc_lb_addresses_create(path_parts.count); + grpc_lb_addresses* addresses = grpc_lb_addresses_create( + path_parts.count, NULL /* user_data_vtable */); bool errors_found = false; for (size_t i = 0; i < addresses->num_addresses; i++) { grpc_uri ith_uri = *args->uri; @@ -187,7 +187,7 @@ static grpc_resolver* fake_resolver_create(grpc_resolver_factory* factory, gpr_slice_buffer_destroy(&path_parts); gpr_slice_unref(path_slice); if (errors_found) { - grpc_lb_addresses_destroy(addresses, NULL /* user_data_destroy */); + grpc_lb_addresses_destroy(addresses); return NULL; } // Construct method config table. -- GitLab