aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/ext/client_config
diff options
context:
space:
mode:
authorGravatar Mark D. Roth <roth@google.com>2016-10-19 13:46:38 -0700
committerGravatar Mark D. Roth <roth@google.com>2016-10-19 13:46:38 -0700
commit29a7f40af3d08c70ab8ba23fe33eb073a3da7b7f (patch)
tree8d2d044852d76f01a040472312d33cc59fc09f2f /src/core/ext/client_config
parentf222593de2ddf4afe9dbcfc4fdb32d03b2692ae7 (diff)
Convert method config to a struct for use in the fast path.
Diffstat (limited to 'src/core/ext/client_config')
-rw-r--r--src/core/ext/client_config/client_channel.c6
-rw-r--r--src/core/ext/client_config/method_config.c56
-rw-r--r--src/core/ext/client_config/method_config.h16
3 files changed, 66 insertions, 12 deletions
diff --git a/src/core/ext/client_config/client_channel.c b/src/core/ext/client_config/client_channel.c
index beaa9637c3..613e98922b 100644
--- a/src/core/ext/client_config/client_channel.c
+++ b/src/core/ext/client_config/client_channel.c
@@ -855,8 +855,7 @@ static void read_service_config(grpc_exec_ctx *exec_ctx, void *arg,
// If the method config table was present, use it.
if (method_config_table != NULL) {
const grpc_method_config *method_config =
- grpc_method_config_table_get_method_config(method_config_table,
- calld->path);
+ grpc_method_config_table_get(method_config_table, calld->path);
if (method_config != NULL) {
const gpr_timespec *per_method_timeout =
grpc_method_config_get_timeout(method_config);
@@ -922,8 +921,7 @@ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_method_config_table_ref(chand->method_config_table);
gpr_mu_unlock(&chand->mu);
grpc_method_config *method_config =
- grpc_method_config_table_get_method_config(method_config_table,
- args->path);
+ grpc_method_config_table_get(method_config_table, args->path);
if (method_config != NULL) {
const gpr_timespec *per_method_timeout =
grpc_method_config_get_timeout(method_config);
diff --git a/src/core/ext/client_config/method_config.c b/src/core/ext/client_config/method_config.c
index f8a82323e7..a42fe2bfd9 100644
--- a/src/core/ext/client_config/method_config.c
+++ b/src/core/ext/client_config/method_config.c
@@ -254,12 +254,12 @@ int grpc_method_config_table_cmp(const grpc_method_config_table* table1,
return grpc_mdstr_hash_table_cmp(table1, table2);
}
-grpc_method_config* grpc_method_config_table_get_method_config(
- const grpc_method_config_table* table, const grpc_mdstr* path) {
- grpc_method_config* method_config = grpc_mdstr_hash_table_get(table, path);
+void* grpc_method_config_table_get(const grpc_mdstr_hash_table* table,
+ const grpc_mdstr* path) {
+ void* value = grpc_mdstr_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) {
+ if (value == NULL) {
const char* path_str = grpc_mdstr_as_c_string(path);
const char* sep = strrchr(path_str, '/') + 1;
const size_t len = (size_t)(sep - path_str);
@@ -269,10 +269,10 @@ grpc_method_config* grpc_method_config_table_get_method_config(
buf[len + 1] = '\0';
grpc_mdstr* wildcard_path = grpc_mdstr_from_string(buf);
gpr_free(buf);
- method_config = grpc_mdstr_hash_table_get(table, wildcard_path);
+ value = grpc_mdstr_hash_table_get(table, wildcard_path);
GRPC_MDSTR_UNREF(wildcard_path);
}
- return method_config;
+ return value;
}
static void* copy_arg(void* p) { return grpc_method_config_table_ref(p); }
@@ -294,3 +294,47 @@ grpc_arg grpc_method_config_table_create_channel_arg(
arg.value.pointer.vtable = &arg_vtable;
return arg;
}
+
+// State used by convert_entry() below.
+typedef struct conversion_state {
+ void* (*convert_value)(const grpc_method_config* method_config);
+ const grpc_mdstr_hash_table_vtable* vtable;
+ size_t num_entries;
+ grpc_mdstr_hash_table_entry* entries;
+} conversion_state;
+
+// A function to be passed to grpc_mdstr_hash_table_iterate() to create
+// a copy of the entries.
+static void convert_entry(const grpc_mdstr_hash_table_entry* entry,
+ void* user_data) {
+ conversion_state* state = user_data;
+ state->entries[state->num_entries].key = GRPC_MDSTR_REF(entry->key);
+ state->entries[state->num_entries].value = state->convert_value(entry->value);
+ state->entries[state->num_entries].vtable = state->vtable;
+ ++state->num_entries;
+}
+
+grpc_mdstr_hash_table* grpc_method_config_table_convert(
+ const grpc_method_config_table* table,
+ void* (*convert_value)(const grpc_method_config* method_config),
+ const grpc_mdstr_hash_table_vtable* vtable) {
+ // Create an array of the entries in the table with converted values.
+ conversion_state state;
+ state.convert_value = convert_value;
+ state.vtable = vtable;
+ state.num_entries = 0;
+ state.entries = gpr_malloc(sizeof(grpc_mdstr_hash_table_entry) *
+ grpc_mdstr_hash_table_num_entries(table));
+ grpc_mdstr_hash_table_iterate(table, convert_entry, &state);
+ // Create a new table based on the array we just constructed.
+ grpc_mdstr_hash_table* new_table =
+ grpc_mdstr_hash_table_create(state.num_entries, state.entries);
+ // Clean up the array.
+ for (size_t i = 0; i < state.num_entries; ++i) {
+ GRPC_MDSTR_UNREF(state.entries[i].key);
+ vtable->destroy_value(state.entries[i].value);
+ }
+ gpr_free(state.entries);
+ // Return the new table.
+ return new_table;
+}
diff --git a/src/core/ext/client_config/method_config.h b/src/core/ext/client_config/method_config.h
index 1302ac425d..87c72ec064 100644
--- a/src/core/ext/client_config/method_config.h
+++ b/src/core/ext/client_config/method_config.h
@@ -106,11 +106,23 @@ int grpc_method_config_table_cmp(const grpc_method_config_table* table1,
/// the form "/service/method".
/// Returns NULL if the method has no config.
/// Caller does NOT own a reference to the result.
-grpc_method_config* grpc_method_config_table_get_method_config(
- const grpc_method_config_table* table, const grpc_mdstr* path);
+///
+/// Note: This returns a void* instead of a grpc_method_config* so that
+/// it can also be used for tables constructed via
+/// grpc_method_config_table_convert().
+void* grpc_method_config_table_get(const grpc_mdstr_hash_table* table,
+ const grpc_mdstr* path);
/// Returns a channel arg containing \a table.
grpc_arg grpc_method_config_table_create_channel_arg(
grpc_method_config_table* table);
+/// Generates a new table from \a table whose values are converted to a
+/// new form via the \a convert_value function. The new table will use
+/// \a vtable for its values.
+grpc_mdstr_hash_table* grpc_method_config_table_convert(
+ const grpc_method_config_table* table,
+ void* (*convert_value)(const grpc_method_config* method_config),
+ const grpc_mdstr_hash_table_vtable* vtable);
+
#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_METHOD_CONFIG_H */