diff options
author | Mark D. Roth <roth@google.com> | 2016-09-12 11:22:27 -0700 |
---|---|---|
committer | Mark D. Roth <roth@google.com> | 2016-09-12 11:22:27 -0700 |
commit | 9fe284e5e431487cafa73c71503f1ed4b9beb332 (patch) | |
tree | ed2090fa869c0333ca286ffb146fc4bd097bc8de /src/core/ext/client_config/resolver_result.c | |
parent | 38525a9a082df5c8a61efe046cde9cb14ae4170c (diff) |
Add map of path name to grpc_method_config data structures.
Diffstat (limited to 'src/core/ext/client_config/resolver_result.c')
-rw-r--r-- | src/core/ext/client_config/resolver_result.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/src/core/ext/client_config/resolver_result.c b/src/core/ext/client_config/resolver_result.c index b0602d583d..235ea5b23f 100644 --- a/src/core/ext/client_config/resolver_result.c +++ b/src/core/ext/client_config/resolver_result.c @@ -38,6 +38,11 @@ #include <grpc/support/alloc.h> #include <grpc/support/string_util.h> +#include "src/core/lib/support/murmur_hash.h" +#include "src/core/lib/transport/metadata.h" + +/* grpc_addresses */ + grpc_addresses *grpc_addresses_create(size_t num_addresses) { grpc_addresses *addresses = gpr_malloc(sizeof(grpc_addresses)); addresses->num_addresses = num_addresses; @@ -69,10 +74,148 @@ void grpc_addresses_destroy(grpc_addresses *addresses) { gpr_free(addresses); } +/* grpc_method_config */ + +struct grpc_method_config { + gpr_refcount refs; + bool* wait_for_ready; + gpr_timespec* timeout; + int32_t* max_request_message_bytes; + int32_t* max_response_message_bytes; +}; + +grpc_method_config *grpc_method_config_create( + bool *wait_for_ready, gpr_timespec *timeout, + int32_t *max_request_message_bytes, int32_t *max_response_message_bytes) { + grpc_method_config *config = gpr_malloc(sizeof(*config)); + memset(config, 0, sizeof(*config)); + gpr_ref_init(&config->refs, 1); + if (wait_for_ready != NULL) { + config->wait_for_ready = gpr_malloc(sizeof(*wait_for_ready)); + *config->wait_for_ready = *wait_for_ready; + } + if (timeout != NULL) { + config->timeout = gpr_malloc(sizeof(*timeout)); + *config->timeout = *timeout; + } + if (max_request_message_bytes != NULL) { + config->max_request_message_bytes = + gpr_malloc(sizeof(*max_request_message_bytes)); + *config->max_request_message_bytes = *max_request_message_bytes; + } + if (max_response_message_bytes != NULL) { + config->max_response_message_bytes = + gpr_malloc(sizeof(*max_response_message_bytes)); + *config->max_response_message_bytes = *max_response_message_bytes; + } + return config; +} + +grpc_method_config *grpc_method_config_ref(grpc_method_config *method_config) { + gpr_ref(&method_config->refs); + return method_config; +} + +void grpc_method_config_unref(grpc_method_config *method_config) { + if (gpr_unref(&method_config->refs)) { + gpr_free(method_config->wait_for_ready); + gpr_free(method_config->timeout); + gpr_free(method_config->max_request_message_bytes); + gpr_free(method_config->max_response_message_bytes); + gpr_free(method_config); + } +} + +bool* grpc_method_config_get_wait_for_ready( + grpc_method_config *method_config) { + return method_config->wait_for_ready; +} + +gpr_timespec* grpc_method_config_get_timeout( + grpc_method_config *method_config) { + return method_config->timeout; +} + +int32_t* grpc_method_config_get_max_request_message_bytes( + grpc_method_config *method_config) { + return method_config->max_request_message_bytes; +} + +int32_t* grpc_method_config_get_max_response_message_bytes( + grpc_method_config *method_config) { + return method_config->max_response_message_bytes; +} + +/* method_config_table */ + +typedef struct method_config_table_entry { + grpc_mdstr *path; + grpc_method_config *method_config; + struct method_config_table_entry *next; // Chaining for collisions. +} method_config_table_entry; + +#define METHOD_CONFIG_TABLE_SIZE 30 +typedef struct method_config_table { + method_config_table_entry *entries[METHOD_CONFIG_TABLE_SIZE]; + uint32_t hash_seed; +} method_config_table; + +static void method_config_table_init(method_config_table* table) { + memset(table, 0, sizeof(*table)); + table->hash_seed = (uint32_t)gpr_now(GPR_CLOCK_REALTIME).tv_nsec; +} + +static void method_config_table_destroy(method_config_table* table) { + for (size_t i = 0; i < GPR_ARRAY_SIZE(table->entries); ++i) { + method_config_table_entry *entry = table->entries[i]; + while (entry != NULL) { + method_config_table_entry *next_entry = entry->next; + GRPC_MDSTR_UNREF(entry->path); + grpc_method_config_unref(entry->method_config); + gpr_free(entry); + entry = next_entry; + } + } +} + +static void method_config_table_insert(method_config_table* table, + grpc_mdstr *path, + grpc_method_config *config) { + method_config_table_entry *entry = gpr_malloc(sizeof(*entry)); + entry->path = GRPC_MDSTR_REF(path); + entry->method_config = grpc_method_config_ref(config); + entry->next = NULL; + const uint32_t hash = gpr_murmur_hash3(path, sizeof(path), table->hash_seed); + const size_t idx = hash % GPR_ARRAY_SIZE(table->entries); + if (table->entries[idx] == NULL) { + table->entries[idx] = entry; + } else { + method_config_table_entry *last_entry = table->entries[idx]; + while (last_entry->next != NULL) { + last_entry = last_entry->next; + } + last_entry->next = entry; + } +} + +static grpc_method_config *method_config_table_get(method_config_table* table, + grpc_mdstr *path) { + const uint32_t hash = gpr_murmur_hash3(path, sizeof(path), table->hash_seed); + const size_t idx = hash % GPR_ARRAY_SIZE(table->entries); + for (method_config_table_entry *entry = table->entries[idx]; + entry != NULL; entry = entry->next) { + if (entry->path == path) return entry->method_config; + } + return NULL; // Not found. +} + +/* grpc_resolver_result */ + struct grpc_resolver_result { gpr_refcount refs; grpc_addresses *addresses; char *lb_policy_name; + method_config_table method_configs; }; grpc_resolver_result *grpc_resolver_result_create(grpc_addresses *addresses, @@ -82,6 +225,7 @@ grpc_resolver_result *grpc_resolver_result_create(grpc_addresses *addresses, gpr_ref_init(&result->refs, 1); result->addresses = addresses; result->lb_policy_name = gpr_strdup(lb_policy_name); + method_config_table_init(&result->method_configs); return result; } @@ -94,6 +238,7 @@ void grpc_resolver_result_unref(grpc_exec_ctx *exec_ctx, if (gpr_unref(&result->refs)) { grpc_addresses_destroy(result->addresses); gpr_free(result->lb_policy_name); + method_config_table_destroy(&result->method_configs); gpr_free(result); } } @@ -107,3 +252,17 @@ const char *grpc_resolver_result_get_lb_policy_name( grpc_resolver_result *result) { return result->lb_policy_name; } + +void grpc_resolver_result_add_method_config( + grpc_resolver_result *result, grpc_mdstr **paths, size_t num_paths, + grpc_method_config *method_config) { + for (size_t i = 0; i < num_paths; ++i) { + method_config_table_insert(&result->method_configs, paths[i], + method_config); + } +} + +grpc_method_config *grpc_resolver_result_get_method_config( + grpc_resolver_result *result, grpc_mdstr *path) { + return method_config_table_get(&result->method_configs, path); +} |