diff options
Diffstat (limited to 'src/core/ext/client_config/method_config.c')
-rw-r--r-- | src/core/ext/client_config/method_config.c | 284 |
1 files changed, 144 insertions, 140 deletions
diff --git a/src/core/ext/client_config/method_config.c b/src/core/ext/client_config/method_config.c index 989f776967..553a7be496 100644 --- a/src/core/ext/client_config/method_config.c +++ b/src/core/ext/client_config/method_config.c @@ -39,165 +39,214 @@ #include <grpc/support/string_util.h> #include <grpc/support/time.h> +#include "src/core/lib/transport/hashtable.h" #include "src/core/lib/transport/metadata.h" // // grpc_method_config // +// bool vtable + +static void* bool_copy(void* valuep) { + bool value = *(bool*)valuep; + bool* new_value = gpr_malloc(sizeof(bool)); + *new_value = value; + return new_value; +} + +static int bool_cmp(void* v1, void* v2) { + bool b1 = *(bool*)v1; + bool b2 = *(bool*)v2; + if (!b1 && b2) return -1; + if (b1 && !b2) return 1; + return 0; +} + +static grpc_hash_table_vtable bool_vtable = {gpr_free, bool_copy, bool_cmp}; + +// timespec vtable + +static void* timespec_copy(void* valuep) { + gpr_timespec value = *(gpr_timespec*)valuep; + gpr_timespec* new_value = gpr_malloc(sizeof(gpr_timespec)); + *new_value = value; + return new_value; +} + +static int timespec_cmp(void* v1, void* v2) { + return gpr_time_cmp(*(gpr_timespec*)v1, *(gpr_timespec*)v2); +} + +static grpc_hash_table_vtable timespec_vtable = { + gpr_free, timespec_copy, timespec_cmp}; + +// int32 vtable + +static void* int32_copy(void* valuep) { + int32_t value = *(int32_t*)valuep; + int32_t* new_value = gpr_malloc(sizeof(int32_t)); + *new_value = value; + return new_value; +} + +static int int32_cmp(void* v1, void* v2) { + int32_t i1 = *(int32_t*)v1; + int32_t i2 = *(int32_t*)v2; + if (i1 < i2) return -1; + if (i1 > i2) return 1; + return 0; +} + +static grpc_hash_table_vtable int32_vtable = {gpr_free, int32_copy, int32_cmp}; + +// Hash table keys. +#define GRPC_METHOD_CONFIG_WAIT_FOR_READY "grpc.wait_for_ready" // bool +#define GRPC_METHOD_CONFIG_TIMEOUT "grpc.timeout" // gpr_timespec +#define GRPC_METHOD_CONFIG_MAX_REQUEST_MESSAGE_BYTES \ + "grpc.max_request_message_bytes" // int32 +#define GRPC_METHOD_CONFIG_MAX_RESPONSE_MESSAGE_BYTES \ + "grpc.max_response_message_bytes" // int32 + 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_hash_table* table; + grpc_mdstr* wait_for_ready_key; + grpc_mdstr* timeout_key; + grpc_mdstr* max_request_message_bytes_key; + grpc_mdstr* max_response_message_bytes_key; }; 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); + grpc_method_config* method_config = gpr_malloc(sizeof(grpc_method_config)); + memset(method_config, 0, sizeof(grpc_method_config)); + grpc_hash_table_entry entries[4]; + size_t num_entries = 0; if (wait_for_ready != NULL) { - config->wait_for_ready = gpr_malloc(sizeof(*wait_for_ready)); - *config->wait_for_ready = *wait_for_ready; + method_config->wait_for_ready_key = + grpc_mdstr_from_string(GRPC_METHOD_CONFIG_WAIT_FOR_READY); + entries[num_entries].key = method_config->wait_for_ready_key; + entries[num_entries].value = wait_for_ready; + entries[num_entries].vtable = &bool_vtable; + ++num_entries; } if (timeout != NULL) { - config->timeout = gpr_malloc(sizeof(*timeout)); - *config->timeout = *timeout; + method_config->timeout_key = + grpc_mdstr_from_string(GRPC_METHOD_CONFIG_TIMEOUT); + entries[num_entries].key = method_config->timeout_key; + entries[num_entries].value = timeout; + entries[num_entries].vtable = ×pec_vtable; + ++num_entries; } 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; + method_config->max_request_message_bytes_key = + grpc_mdstr_from_string(GRPC_METHOD_CONFIG_MAX_REQUEST_MESSAGE_BYTES); + entries[num_entries].key = method_config->max_request_message_bytes_key; + entries[num_entries].value = max_request_message_bytes; + entries[num_entries].vtable = &int32_vtable; + ++num_entries; } 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; + method_config->max_response_message_bytes_key = + grpc_mdstr_from_string(GRPC_METHOD_CONFIG_MAX_RESPONSE_MESSAGE_BYTES); + entries[num_entries].key = method_config->max_response_message_bytes_key; + entries[num_entries].value = max_response_message_bytes; + entries[num_entries].vtable = &int32_vtable; + ++num_entries; } - return config; + method_config->table = grpc_hash_table_create(num_entries, entries); + return method_config; } grpc_method_config* grpc_method_config_ref(grpc_method_config* method_config) { - gpr_ref(&method_config->refs); + grpc_hash_table_ref(method_config->table); 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); + if (grpc_hash_table_unref(method_config->table)) { + GRPC_MDSTR_UNREF(method_config->wait_for_ready_key); + GRPC_MDSTR_UNREF(method_config->timeout_key); + GRPC_MDSTR_UNREF(method_config->max_request_message_bytes_key); + GRPC_MDSTR_UNREF(method_config->max_response_message_bytes_key); } } +int grpc_method_config_cmp(grpc_method_config* method_config1, + grpc_method_config* method_config2) { + return grpc_hash_table_cmp(method_config1->table, method_config2->table); +} + bool* grpc_method_config_get_wait_for_ready(grpc_method_config* method_config) { - return method_config->wait_for_ready; + return grpc_hash_table_get(method_config->table, + method_config->wait_for_ready_key); } gpr_timespec* grpc_method_config_get_timeout( grpc_method_config* method_config) { - return method_config->timeout; + return grpc_hash_table_get(method_config->table, method_config->timeout_key); } int32_t* grpc_method_config_get_max_request_message_bytes( grpc_method_config* method_config) { - return method_config->max_request_message_bytes; + return grpc_hash_table_get(method_config->table, + method_config->max_request_message_bytes_key); } int32_t* grpc_method_config_get_max_response_message_bytes( grpc_method_config* method_config) { - return method_config->max_response_message_bytes; + return grpc_hash_table_get(method_config->table, + method_config->max_response_message_bytes_key); } // // grpc_method_config_table // -typedef struct grpc_method_config_table_entry { - grpc_mdstr* path; - grpc_method_config* method_config; -} grpc_method_config_table_entry; - -#define METHOD_CONFIG_TABLE_SIZE 128 -struct grpc_method_config_table { - gpr_refcount refs; - grpc_method_config_table_entry entries[METHOD_CONFIG_TABLE_SIZE]; -}; - -grpc_method_config_table* grpc_method_config_table_create() { - grpc_method_config_table* table = gpr_malloc(sizeof(*table)); - memset(table, 0, sizeof(*table)); - gpr_ref_init(&table->refs, 1); - return table; +static void method_config_unref(void* valuep) { + grpc_method_config_unref(valuep); } -grpc_method_config_table* grpc_method_config_table_ref( - grpc_method_config_table* table) { - if (table != NULL) gpr_ref(&table->refs); - return table; +static void* method_config_ref(void* valuep) { + return grpc_method_config_ref(valuep); } -void grpc_method_config_table_unref(grpc_method_config_table* table) { - if (table != NULL && gpr_unref(&table->refs)) { - for (size_t i = 0; i < GPR_ARRAY_SIZE(table->entries); ++i) { - grpc_method_config_table_entry* entry = &table->entries[i]; - if (entry->path != NULL) { - GRPC_MDSTR_UNREF(entry->path); - grpc_method_config_unref(entry->method_config); - } - } - } +static int method_config_cmp(void* valuep1, void* valuep2) { + return grpc_method_config_cmp(valuep1, valuep2); } -// Helper function for insert and get operations that performs quadratic -// probing (https://en.wikipedia.org/wiki/Quadratic_probing). -static size_t grpc_method_config_table_find_index( - grpc_method_config_table* table, grpc_mdstr* path, bool find_empty) { - for (size_t i = 0; i < GPR_ARRAY_SIZE(table->entries); ++i) { - const size_t idx = (path->hash + i * i) % GPR_ARRAY_SIZE(table->entries); - if (table->entries[idx].path == NULL) - return find_empty ? idx : GPR_ARRAY_SIZE(table->entries); - if (table->entries[idx].path == path) return idx; +static const grpc_hash_table_vtable method_config_table_vtable = { + method_config_unref, method_config_ref, method_config_cmp}; + +grpc_method_config_table* grpc_method_config_table_create( + size_t num_entries, grpc_method_config_table_entry* entries) { + grpc_hash_table_entry hash_table_entries[num_entries]; + for (size_t i = 0; i < num_entries; ++i) { + hash_table_entries[i].key = entries[i].method_name; + hash_table_entries[i].value = entries[i].method_config; + hash_table_entries[i].vtable = &method_config_table_vtable; } - return GPR_ARRAY_SIZE(table->entries) + 1; // Not found. + return grpc_hash_table_create(num_entries, hash_table_entries); } -static void grpc_method_config_table_insert(grpc_method_config_table* table, - grpc_mdstr* path, - grpc_method_config* config) { - const size_t idx = - grpc_method_config_table_find_index(table, path, true /* find_empty */); - // This can happen if the table is full. - GPR_ASSERT(idx != GPR_ARRAY_SIZE(table->entries)); - grpc_method_config_table_entry* entry = &table->entries[idx]; - entry->path = GRPC_MDSTR_REF(path); - entry->method_config = grpc_method_config_ref(config); +grpc_method_config_table* grpc_method_config_table_ref( + grpc_method_config_table* table) { + return grpc_hash_table_ref(table); } -static grpc_method_config* grpc_method_config_table_get( - grpc_method_config_table* table, grpc_mdstr* path) { - const size_t idx = - grpc_method_config_table_find_index(table, path, false /* find_empty */); - if (idx == GPR_ARRAY_SIZE(table->entries)) return NULL; // Not found. - return table->entries[idx].method_config; +void grpc_method_config_table_unref(grpc_method_config_table* table) { + grpc_hash_table_unref(table); } -void grpc_method_config_table_add_method_config( - grpc_method_config_table* table, grpc_mdstr** paths, size_t num_paths, - grpc_method_config* method_config) { - for (size_t i = 0; i < num_paths; ++i) { - grpc_method_config_table_insert(table, paths[i], method_config); - } +int grpc_method_config_table_cmp(grpc_method_config_table* table1, + grpc_method_config_table* table2) { + return grpc_hash_table_cmp(table1, table2); } grpc_method_config* grpc_method_config_table_get_method_config( grpc_method_config_table* table, grpc_mdstr* path) { - grpc_method_config* method_config = grpc_method_config_table_get(table, path); + grpc_method_config* method_config = grpc_hash_table_get(table, path); // If we didn't find a match for the path, try looking for a wildcard // entry (i.e., change "/service/method" to "/service/*"). if (method_config == NULL) { @@ -209,7 +258,7 @@ grpc_method_config* grpc_method_config_table_get_method_config( buf[len] = '*'; buf[len + 1] = '\0'; grpc_mdstr* wildcard_path = grpc_mdstr_from_string(buf); - method_config = grpc_method_config_table_get(table, wildcard_path); + method_config = grpc_hash_table_get(table, wildcard_path); GRPC_MDSTR_UNREF(wildcard_path); } return grpc_method_config_ref(method_config); @@ -224,52 +273,7 @@ static void destroy_arg(void* p) { } static int cmp_arg(void* p1, void* p2) { - grpc_method_config_table* t1 = p1; - grpc_method_config_table* t2 = p2; - for (size_t i = 0; i < GPR_ARRAY_SIZE(t1->entries); ++i) { - grpc_method_config_table_entry* e1 = &t1->entries[i]; - grpc_method_config_table_entry* e2 = &t2->entries[i]; - // Compare paths by hash value. - if (e1->path->hash < e2->path->hash) return -1; - if (e1->path->hash > e2->path->hash) return 1; - // Compare wait_for_ready. - const bool wait_for_ready1 = - e1->method_config->wait_for_ready == NULL - ? false : *e1->method_config->wait_for_ready; - const bool wait_for_ready2 = - e2->method_config->wait_for_ready == NULL - ? false : *e2->method_config->wait_for_ready; - if (wait_for_ready1 < wait_for_ready2) return -1; - if (wait_for_ready1 > wait_for_ready2) return 1; - // Compare timeout. - const gpr_timespec timeout1 = - e1->method_config->timeout == NULL - ? gpr_inf_past(GPR_CLOCK_MONOTONIC) : *e1->method_config->timeout; - const gpr_timespec timeout2 = - e2->method_config->timeout == NULL - ? gpr_inf_past(GPR_CLOCK_MONOTONIC) : *e2->method_config->timeout; - const int timeout_result = gpr_time_cmp(timeout1, timeout2); - if (timeout_result != 0) return timeout_result; - // Compare max_request_message_bytes. - const int32_t max_request_message_bytes1 = - e1->method_config->max_request_message_bytes == NULL - ? -1 : *e1->method_config->max_request_message_bytes; - const int32_t max_request_message_bytes2 = - e2->method_config->max_request_message_bytes == NULL - ? -1 : *e2->method_config->max_request_message_bytes; - if (max_request_message_bytes1 < max_request_message_bytes2) return -1; - if (max_request_message_bytes1 > max_request_message_bytes2) return 1; - // Compare max_response_message_bytes. - const int32_t max_response_message_bytes1 = - e1->method_config->max_response_message_bytes == NULL - ? -1 : *e1->method_config->max_response_message_bytes; - const int32_t max_response_message_bytes2 = - e2->method_config->max_response_message_bytes == NULL - ? -1 : *e2->method_config->max_response_message_bytes; - if (max_response_message_bytes1 < max_response_message_bytes2) return -1; - if (max_response_message_bytes1 > max_response_message_bytes2) return 1; - } - return 0; + return grpc_method_config_table_cmp(p1, p2); } static grpc_arg_pointer_vtable arg_vtable = {copy_arg, destroy_arg, cmp_arg}; |