aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/ext/client_config/resolver_result.c
diff options
context:
space:
mode:
authorGravatar Mark D. Roth <roth@google.com>2016-09-12 11:22:27 -0700
committerGravatar Mark D. Roth <roth@google.com>2016-09-12 11:22:27 -0700
commit9fe284e5e431487cafa73c71503f1ed4b9beb332 (patch)
treeed2090fa869c0333ca286ffb146fc4bd097bc8de /src/core/ext/client_config/resolver_result.c
parent38525a9a082df5c8a61efe046cde9cb14ae4170c (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.c159
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);
+}