aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/lib/transport
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/lib/transport')
-rw-r--r--src/core/lib/transport/README.md7
-rw-r--r--src/core/lib/transport/byte_stream.c5
-rw-r--r--src/core/lib/transport/connectivity_state.c14
-rw-r--r--src/core/lib/transport/mdstr_hash_table.c7
-rw-r--r--src/core/lib/transport/mdstr_hash_table.h5
-rw-r--r--src/core/lib/transport/metadata.c66
-rw-r--r--src/core/lib/transport/metadata.h38
-rw-r--r--src/core/lib/transport/metadata_batch.c25
-rw-r--r--src/core/lib/transport/metadata_batch.h12
-rw-r--r--src/core/lib/transport/method_config.c347
-rw-r--r--src/core/lib/transport/method_config.h139
-rw-r--r--src/core/lib/transport/pid_controller.h2
-rw-r--r--src/core/lib/transport/service_config.c20
-rw-r--r--src/core/lib/transport/service_config.h5
-rw-r--r--src/core/lib/transport/transport.c43
-rw-r--r--src/core/lib/transport/transport.h7
16 files changed, 636 insertions, 106 deletions
diff --git a/src/core/lib/transport/README.md b/src/core/lib/transport/README.md
new file mode 100644
index 0000000000..e7e135edeb
--- /dev/null
+++ b/src/core/lib/transport/README.md
@@ -0,0 +1,7 @@
+# Transport
+
+Common implementation details for gRPC Transports.
+
+Transports multiplex messages across some single connection. In ext/ there are
+implementations atop [a custom http2 implementation](/src/core/ext/transport/chttp2/README.md)
+and atop [cronet](/src/core/ext/transport/cronet/README.md).
diff --git a/src/core/lib/transport/byte_stream.c b/src/core/lib/transport/byte_stream.c
index 2f1d7b7c60..4d4206189e 100644
--- a/src/core/lib/transport/byte_stream.c
+++ b/src/core/lib/transport/byte_stream.c
@@ -37,6 +37,8 @@
#include <grpc/support/log.h>
+#include "src/core/lib/slice/slice_internal.h"
+
int grpc_byte_stream_next(grpc_exec_ctx *exec_ctx,
grpc_byte_stream *byte_stream, grpc_slice *slice,
size_t max_size_hint, grpc_closure *on_complete) {
@@ -57,7 +59,8 @@ static int slice_buffer_stream_next(grpc_exec_ctx *exec_ctx,
grpc_closure *on_complete) {
grpc_slice_buffer_stream *stream = (grpc_slice_buffer_stream *)byte_stream;
GPR_ASSERT(stream->cursor < stream->backing_buffer->count);
- *slice = grpc_slice_ref(stream->backing_buffer->slices[stream->cursor]);
+ *slice =
+ grpc_slice_ref_internal(stream->backing_buffer->slices[stream->cursor]);
stream->cursor++;
return 1;
}
diff --git a/src/core/lib/transport/connectivity_state.c b/src/core/lib/transport/connectivity_state.c
index 4f49d7cf7d..c656d93740 100644
--- a/src/core/lib/transport/connectivity_state.c
+++ b/src/core/lib/transport/connectivity_state.c
@@ -81,7 +81,7 @@ void grpc_connectivity_state_destroy(grpc_exec_ctx *exec_ctx,
} else {
error = GRPC_ERROR_CREATE("Shutdown connectivity owner");
}
- grpc_exec_ctx_sched(exec_ctx, w->notify, error, NULL);
+ grpc_closure_sched(exec_ctx, w->notify, error);
gpr_free(w);
}
GRPC_ERROR_UNREF(tracker->current_error);
@@ -121,7 +121,7 @@ bool grpc_connectivity_state_notify_on_state_change(
if (current == NULL) {
grpc_connectivity_state_watcher *w = tracker->watchers;
if (w != NULL && w->notify == notify) {
- grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_CANCELLED, NULL);
+ grpc_closure_sched(exec_ctx, notify, GRPC_ERROR_CANCELLED);
tracker->watchers = w->next;
gpr_free(w);
return false;
@@ -129,7 +129,7 @@ bool grpc_connectivity_state_notify_on_state_change(
while (w != NULL) {
grpc_connectivity_state_watcher *rm_candidate = w->next;
if (rm_candidate != NULL && rm_candidate->notify == notify) {
- grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_CANCELLED, NULL);
+ grpc_closure_sched(exec_ctx, notify, GRPC_ERROR_CANCELLED);
w->next = w->next->next;
gpr_free(rm_candidate);
return false;
@@ -140,8 +140,8 @@ bool grpc_connectivity_state_notify_on_state_change(
} else {
if (tracker->current_state != *current) {
*current = tracker->current_state;
- grpc_exec_ctx_sched(exec_ctx, notify,
- GRPC_ERROR_REF(tracker->current_error), NULL);
+ grpc_closure_sched(exec_ctx, notify,
+ GRPC_ERROR_REF(tracker->current_error));
} else {
grpc_connectivity_state_watcher *w = gpr_malloc(sizeof(*w));
w->current = current;
@@ -191,8 +191,8 @@ void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx,
gpr_log(GPR_DEBUG, "NOTIFY: %p %s: %p", tracker, tracker->name,
w->notify);
}
- grpc_exec_ctx_sched(exec_ctx, w->notify,
- GRPC_ERROR_REF(tracker->current_error), NULL);
+ grpc_closure_sched(exec_ctx, w->notify,
+ GRPC_ERROR_REF(tracker->current_error));
gpr_free(w);
}
}
diff --git a/src/core/lib/transport/mdstr_hash_table.c b/src/core/lib/transport/mdstr_hash_table.c
index 3d01e56df7..2791bf653b 100644
--- a/src/core/lib/transport/mdstr_hash_table.c
+++ b/src/core/lib/transport/mdstr_hash_table.c
@@ -94,13 +94,14 @@ grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table) {
return table;
}
-void grpc_mdstr_hash_table_unref(grpc_mdstr_hash_table* table) {
+void grpc_mdstr_hash_table_unref(grpc_exec_ctx* exec_ctx,
+ grpc_mdstr_hash_table* table) {
if (table != NULL && gpr_unref(&table->refs)) {
for (size_t i = 0; i < table->size; ++i) {
grpc_mdstr_hash_table_entry* entry = &table->entries[i];
if (entry->key != NULL) {
- GRPC_MDSTR_UNREF(entry->key);
- entry->vtable->destroy_value(entry->value);
+ GRPC_MDSTR_UNREF(exec_ctx, entry->key);
+ entry->vtable->destroy_value(exec_ctx, entry->value);
}
}
gpr_free(table->entries);
diff --git a/src/core/lib/transport/mdstr_hash_table.h b/src/core/lib/transport/mdstr_hash_table.h
index 8982ec3a8d..57f497ee27 100644
--- a/src/core/lib/transport/mdstr_hash_table.h
+++ b/src/core/lib/transport/mdstr_hash_table.h
@@ -49,7 +49,7 @@
typedef struct grpc_mdstr_hash_table grpc_mdstr_hash_table;
typedef struct grpc_mdstr_hash_table_vtable {
- void (*destroy_value)(void* value);
+ void (*destroy_value)(grpc_exec_ctx* exec_ctx, void* value);
void* (*copy_value)(void* value);
} grpc_mdstr_hash_table_vtable;
@@ -66,7 +66,8 @@ grpc_mdstr_hash_table* grpc_mdstr_hash_table_create(
size_t num_entries, grpc_mdstr_hash_table_entry* entries);
grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table);
-void grpc_mdstr_hash_table_unref(grpc_mdstr_hash_table* table);
+void grpc_mdstr_hash_table_unref(grpc_exec_ctx* exec_ctx,
+ grpc_mdstr_hash_table* table);
/** Returns the value from \a table associated with \a key.
Returns NULL if \a key is not found. */
diff --git a/src/core/lib/transport/metadata.c b/src/core/lib/transport/metadata.c
index fac19b91d9..54c39df6a7 100644
--- a/src/core/lib/transport/metadata.c
+++ b/src/core/lib/transport/metadata.c
@@ -47,6 +47,7 @@
#include "src/core/lib/iomgr/iomgr_internal.h"
#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/murmur_hash.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/static_metadata.h"
@@ -153,7 +154,7 @@ static size_t g_static_mdtab_maxprobe;
static strtab_shard g_strtab_shard[STRTAB_SHARD_COUNT];
static mdtab_shard g_mdtab_shard[MDTAB_SHARD_COUNT];
-static void gc_mdtab(mdtab_shard *shard);
+static void gc_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard);
void grpc_test_only_set_metadata_hash_seed(uint32_t seed) {
g_hash_seed = seed;
@@ -227,12 +228,12 @@ void grpc_mdctx_global_init(void) {
}
}
-void grpc_mdctx_global_shutdown(void) {
+void grpc_mdctx_global_shutdown(grpc_exec_ctx *exec_ctx) {
size_t i;
for (i = 0; i < MDTAB_SHARD_COUNT; i++) {
mdtab_shard *shard = &g_mdtab_shard[i];
gpr_mu_destroy(&shard->mu);
- gc_mdtab(shard);
+ gc_mdtab(exec_ctx, shard);
/* TODO(ctiller): GPR_ASSERT(shard->count == 0); */
if (shard->count != 0) {
gpr_log(GPR_DEBUG, "WARNING: %" PRIuPTR " metadata elements were leaked",
@@ -316,12 +317,13 @@ static void grow_strtab(strtab_shard *shard) {
GPR_TIMER_END("grow_strtab", 0);
}
-static void internal_destroy_string(strtab_shard *shard, internal_string *is) {
+static void internal_destroy_string(grpc_exec_ctx *exec_ctx,
+ strtab_shard *shard, internal_string *is) {
internal_string **prev_next;
internal_string *cur;
GPR_TIMER_BEGIN("internal_destroy_string", 0);
if (is->has_base64_and_huffman_encoded) {
- grpc_slice_unref(is->base64_and_huffman);
+ grpc_slice_unref_internal(exec_ctx, is->base64_and_huffman);
}
for (prev_next = &shard->strs[TABLE_IDX(is->hash, LOG2_STRTAB_SHARD_COUNT,
shard->capacity)],
@@ -340,20 +342,20 @@ static void slice_ref(void *p) {
GRPC_MDSTR_REF((grpc_mdstr *)(is));
}
-static void slice_unref(void *p) {
+static void slice_unref(grpc_exec_ctx *exec_ctx, void *p) {
internal_string *is =
(internal_string *)((char *)p - offsetof(internal_string, refcount));
- GRPC_MDSTR_UNREF((grpc_mdstr *)(is));
+ GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)(is));
}
grpc_mdstr *grpc_mdstr_from_string(const char *str) {
return grpc_mdstr_from_buffer((const uint8_t *)str, strlen(str));
}
-grpc_mdstr *grpc_mdstr_from_slice(grpc_slice slice) {
+grpc_mdstr *grpc_mdstr_from_slice(grpc_exec_ctx *exec_ctx, grpc_slice slice) {
grpc_mdstr *result = grpc_mdstr_from_buffer(GRPC_SLICE_START_PTR(slice),
GRPC_SLICE_LENGTH(slice));
- grpc_slice_unref(slice);
+ grpc_slice_unref_internal(exec_ctx, slice);
return result;
}
@@ -444,7 +446,7 @@ grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *buf, size_t length) {
return (grpc_mdstr *)s;
}
-static void gc_mdtab(mdtab_shard *shard) {
+static void gc_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard) {
size_t i;
internal_metadata **prev_next;
internal_metadata *md, *next;
@@ -457,8 +459,8 @@ static void gc_mdtab(mdtab_shard *shard) {
void *user_data = (void *)gpr_atm_no_barrier_load(&md->user_data);
next = md->bucket_next;
if (gpr_atm_acq_load(&md->refcnt) == 0) {
- GRPC_MDSTR_UNREF((grpc_mdstr *)md->key);
- GRPC_MDSTR_UNREF((grpc_mdstr *)md->value);
+ GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)md->key);
+ GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)md->value);
if (md->user_data) {
((destroy_user_data_func)gpr_atm_no_barrier_load(
&md->destroy_user_data))(user_data);
@@ -506,16 +508,17 @@ static void grow_mdtab(mdtab_shard *shard) {
GPR_TIMER_END("grow_mdtab", 0);
}
-static void rehash_mdtab(mdtab_shard *shard) {
+static void rehash_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard) {
if (gpr_atm_no_barrier_load(&shard->free_estimate) >
(gpr_atm)(shard->capacity / 4)) {
- gc_mdtab(shard);
+ gc_mdtab(exec_ctx, shard);
} else {
grow_mdtab(shard);
}
}
-grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdstr *mkey,
+grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_exec_ctx *exec_ctx,
+ grpc_mdstr *mkey,
grpc_mdstr *mvalue) {
internal_string *key = (internal_string *)mkey;
internal_string *value = (internal_string *)mvalue;
@@ -547,8 +550,8 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdstr *mkey,
for (md = shard->elems[idx]; md; md = md->bucket_next) {
if (md->key == key && md->value == value) {
REF_MD_LOCKED(shard, md);
- GRPC_MDSTR_UNREF((grpc_mdstr *)key);
- GRPC_MDSTR_UNREF((grpc_mdstr *)value);
+ GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)key);
+ GRPC_MDSTR_UNREF(exec_ctx, (grpc_mdstr *)value);
gpr_mu_unlock(&shard->mu);
GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0);
return (grpc_mdelem *)md;
@@ -574,7 +577,7 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdstr *mkey,
shard->count++;
if (shard->count > shard->capacity * 2) {
- rehash_mdtab(shard);
+ rehash_mdtab(exec_ctx, shard);
}
gpr_mu_unlock(&shard->mu);
@@ -584,21 +587,26 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdstr *mkey,
return (grpc_mdelem *)md;
}
-grpc_mdelem *grpc_mdelem_from_strings(const char *key, const char *value) {
- return grpc_mdelem_from_metadata_strings(grpc_mdstr_from_string(key),
- grpc_mdstr_from_string(value));
+grpc_mdelem *grpc_mdelem_from_strings(grpc_exec_ctx *exec_ctx, const char *key,
+ const char *value) {
+ return grpc_mdelem_from_metadata_strings(
+ exec_ctx, grpc_mdstr_from_string(key), grpc_mdstr_from_string(value));
}
-grpc_mdelem *grpc_mdelem_from_slices(grpc_slice key, grpc_slice value) {
- return grpc_mdelem_from_metadata_strings(grpc_mdstr_from_slice(key),
- grpc_mdstr_from_slice(value));
+grpc_mdelem *grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key,
+ grpc_slice value) {
+ return grpc_mdelem_from_metadata_strings(
+ exec_ctx, grpc_mdstr_from_slice(exec_ctx, key),
+ grpc_mdstr_from_slice(exec_ctx, value));
}
-grpc_mdelem *grpc_mdelem_from_string_and_buffer(const char *key,
+grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_exec_ctx *exec_ctx,
+ const char *key,
const uint8_t *value,
size_t value_length) {
return grpc_mdelem_from_metadata_strings(
- grpc_mdstr_from_string(key), grpc_mdstr_from_buffer(value, value_length));
+ exec_ctx, grpc_mdstr_from_string(key),
+ grpc_mdstr_from_buffer(value, value_length));
}
static size_t get_base64_encoded_size(size_t raw_length) {
@@ -654,7 +662,7 @@ grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd DEBUG_ARGS) {
return gmd;
}
-void grpc_mdelem_unref(grpc_mdelem *gmd DEBUG_ARGS) {
+void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem *gmd DEBUG_ARGS) {
internal_metadata *md = (internal_metadata *)gmd;
if (!md) return;
if (is_mdelem_static(gmd)) return;
@@ -696,7 +704,7 @@ grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs DEBUG_ARGS) {
return gs;
}
-void grpc_mdstr_unref(grpc_mdstr *gs DEBUG_ARGS) {
+void grpc_mdstr_unref(grpc_exec_ctx *exec_ctx, grpc_mdstr *gs DEBUG_ARGS) {
internal_string *s = (internal_string *)gs;
if (is_mdstr_static(gs)) return;
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
@@ -709,7 +717,7 @@ void grpc_mdstr_unref(grpc_mdstr *gs DEBUG_ARGS) {
&g_strtab_shard[SHARD_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT)];
gpr_mu_lock(&shard->mu);
GPR_ASSERT(0 == gpr_atm_no_barrier_load(&s->refcnt));
- internal_destroy_string(shard, s);
+ internal_destroy_string(exec_ctx, shard, s);
gpr_mu_unlock(&shard->mu);
}
}
diff --git a/src/core/lib/transport/metadata.h b/src/core/lib/transport/metadata.h
index a4955a1ea7..991eee96f1 100644
--- a/src/core/lib/transport/metadata.h
+++ b/src/core/lib/transport/metadata.h
@@ -37,6 +37,8 @@
#include <grpc/slice.h>
#include <grpc/support/useful.h>
+#include "src/core/lib/iomgr/exec_ctx.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -96,7 +98,7 @@ void grpc_test_only_set_metadata_hash_seed(uint32_t seed);
clients may have handy */
grpc_mdstr *grpc_mdstr_from_string(const char *str);
/* Unrefs the slice. */
-grpc_mdstr *grpc_mdstr_from_slice(grpc_slice slice);
+grpc_mdstr *grpc_mdstr_from_slice(grpc_exec_ctx *exec_ctx, grpc_slice slice);
grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *str, size_t length);
/* Returns a borrowed slice from the mdstr with its contents base64 encoded
@@ -105,12 +107,16 @@ grpc_slice grpc_mdstr_as_base64_encoded_and_huffman_compressed(grpc_mdstr *str);
/* Constructors for grpc_mdelem instances; take a variety of data types that
clients may have handy */
-grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdstr *key,
+grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_exec_ctx *exec_ctx,
+ grpc_mdstr *key,
grpc_mdstr *value);
-grpc_mdelem *grpc_mdelem_from_strings(const char *key, const char *value);
+grpc_mdelem *grpc_mdelem_from_strings(grpc_exec_ctx *exec_ctx, const char *key,
+ const char *value);
/* Unrefs the slices. */
-grpc_mdelem *grpc_mdelem_from_slices(grpc_slice key, grpc_slice value);
-grpc_mdelem *grpc_mdelem_from_string_and_buffer(const char *key,
+grpc_mdelem *grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key,
+ grpc_slice value);
+grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_exec_ctx *exec_ctx,
+ const char *key,
const uint8_t *value,
size_t value_length);
@@ -127,22 +133,26 @@ void *grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *),
//#define GRPC_METADATA_REFCOUNT_DEBUG
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
#define GRPC_MDSTR_REF(s) grpc_mdstr_ref((s), __FILE__, __LINE__)
-#define GRPC_MDSTR_UNREF(s) grpc_mdstr_unref((s), __FILE__, __LINE__)
+#define GRPC_MDSTR_UNREF(exec_ctx, s) \
+ grpc_mdstr_unref((exec_ctx), (s), __FILE__, __LINE__)
#define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s), __FILE__, __LINE__)
-#define GRPC_MDELEM_UNREF(s) grpc_mdelem_unref((s), __FILE__, __LINE__)
+#define GRPC_MDELEM_UNREF(exec_ctx, s) \
+ grpc_mdelem_unref((exec_ctx), (s), __FILE__, __LINE__)
grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *s, const char *file, int line);
-void grpc_mdstr_unref(grpc_mdstr *s, const char *file, int line);
+void grpc_mdstr_unref(grpc_exec_ctx *exec_ctx, grpc_mdstr *s, const char *file,
+ int line);
grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *md, const char *file, int line);
-void grpc_mdelem_unref(grpc_mdelem *md, const char *file, int line);
+void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem *md,
+ const char *file, int line);
#else
#define GRPC_MDSTR_REF(s) grpc_mdstr_ref((s))
-#define GRPC_MDSTR_UNREF(s) grpc_mdstr_unref((s))
+#define GRPC_MDSTR_UNREF(exec_ctx, s) grpc_mdstr_unref((exec_ctx), (s))
#define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s))
-#define GRPC_MDELEM_UNREF(s) grpc_mdelem_unref((s))
+#define GRPC_MDELEM_UNREF(exec_ctx, s) grpc_mdelem_unref((exec_ctx), (s))
grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *s);
-void grpc_mdstr_unref(grpc_mdstr *s);
+void grpc_mdstr_unref(grpc_exec_ctx *exec_ctx, grpc_mdstr *s);
grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *md);
-void grpc_mdelem_unref(grpc_mdelem *md);
+void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem *md);
#endif
/* Recover a char* from a grpc_mdstr. The returned string is null terminated.
@@ -162,7 +172,7 @@ int grpc_mdstr_is_bin_suffixed(grpc_mdstr *s);
#define GRPC_MDSTR_KV_HASH(k_hash, v_hash) (GPR_ROTL((k_hash), 2) ^ (v_hash))
void grpc_mdctx_global_init(void);
-void grpc_mdctx_global_shutdown(void);
+void grpc_mdctx_global_shutdown(grpc_exec_ctx *exec_ctx);
/* Implementation provided by chttp2_transport */
extern grpc_slice (*grpc_chttp2_base64_encode_and_huffman_compress)(
diff --git a/src/core/lib/transport/metadata_batch.c b/src/core/lib/transport/metadata_batch.c
index 84b5a74d51..b62ecc3aa6 100644
--- a/src/core/lib/transport/metadata_batch.c
+++ b/src/core/lib/transport/metadata_batch.c
@@ -72,10 +72,11 @@ void grpc_metadata_batch_init(grpc_metadata_batch *batch) {
batch->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
}
-void grpc_metadata_batch_destroy(grpc_metadata_batch *batch) {
+void grpc_metadata_batch_destroy(grpc_exec_ctx *exec_ctx,
+ grpc_metadata_batch *batch) {
grpc_linked_mdelem *l;
for (l = batch->list.head; l; l = l->next) {
- GRPC_MDELEM_UNREF(l->md);
+ GRPC_MDELEM_UNREF(exec_ctx, l->md);
}
}
@@ -140,8 +141,10 @@ void grpc_metadata_batch_move(grpc_metadata_batch *dst,
memset(src, 0, sizeof(grpc_metadata_batch));
}
-void grpc_metadata_batch_filter(grpc_metadata_batch *batch,
- grpc_mdelem *(*filter)(void *user_data,
+void grpc_metadata_batch_filter(grpc_exec_ctx *exec_ctx,
+ grpc_metadata_batch *batch,
+ grpc_mdelem *(*filter)(grpc_exec_ctx *exec_ctx,
+ void *user_data,
grpc_mdelem *elem),
void *user_data) {
grpc_linked_mdelem *l;
@@ -152,7 +155,7 @@ void grpc_metadata_batch_filter(grpc_metadata_batch *batch,
assert_valid_list(&batch->list);
for (l = batch->list.head; l; l = next) {
grpc_mdelem *orig = l->md;
- grpc_mdelem *filt = filter(user_data, orig);
+ grpc_mdelem *filt = filter(exec_ctx, user_data, orig);
next = l->next;
if (filt == NULL) {
if (l->prev) {
@@ -168,9 +171,9 @@ void grpc_metadata_batch_filter(grpc_metadata_batch *batch,
batch->list.tail = l->prev;
}
assert_valid_list(&batch->list);
- GRPC_MDELEM_UNREF(l->md);
+ GRPC_MDELEM_UNREF(exec_ctx, l->md);
} else if (filt != orig) {
- GRPC_MDELEM_UNREF(orig);
+ GRPC_MDELEM_UNREF(exec_ctx, orig);
l->md = filt;
}
}
@@ -179,13 +182,15 @@ void grpc_metadata_batch_filter(grpc_metadata_batch *batch,
GPR_TIMER_END("grpc_metadata_batch_filter", 0);
}
-static grpc_mdelem *no_metadata_for_you(void *user_data, grpc_mdelem *elem) {
+static grpc_mdelem *no_metadata_for_you(grpc_exec_ctx *exec_ctx,
+ void *user_data, grpc_mdelem *elem) {
return NULL;
}
-void grpc_metadata_batch_clear(grpc_metadata_batch *batch) {
+void grpc_metadata_batch_clear(grpc_exec_ctx *exec_ctx,
+ grpc_metadata_batch *batch) {
batch->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
- grpc_metadata_batch_filter(batch, no_metadata_for_you, NULL);
+ grpc_metadata_batch_filter(exec_ctx, batch, no_metadata_for_you, NULL);
}
bool grpc_metadata_batch_is_empty(grpc_metadata_batch *batch) {
diff --git a/src/core/lib/transport/metadata_batch.h b/src/core/lib/transport/metadata_batch.h
index 7a9ccb4bc8..c0bd5174ab 100644
--- a/src/core/lib/transport/metadata_batch.h
+++ b/src/core/lib/transport/metadata_batch.h
@@ -68,8 +68,10 @@ typedef struct grpc_metadata_batch {
} grpc_metadata_batch;
void grpc_metadata_batch_init(grpc_metadata_batch *batch);
-void grpc_metadata_batch_destroy(grpc_metadata_batch *batch);
-void grpc_metadata_batch_clear(grpc_metadata_batch *batch);
+void grpc_metadata_batch_destroy(grpc_exec_ctx *exec_ctx,
+ grpc_metadata_batch *batch);
+void grpc_metadata_batch_clear(grpc_exec_ctx *exec_ctx,
+ grpc_metadata_batch *batch);
bool grpc_metadata_batch_is_empty(grpc_metadata_batch *batch);
/* Returns the transport size of the batch. */
@@ -118,8 +120,10 @@ void grpc_metadata_batch_add_tail(grpc_metadata_batch *batch,
The return value from \a filter will be substituted for the
grpc_mdelem passed to \a filter. If \a filter returns NULL,
the element will be moved to the garbage list. */
-void grpc_metadata_batch_filter(grpc_metadata_batch *batch,
- grpc_mdelem *(*filter)(void *user_data,
+void grpc_metadata_batch_filter(grpc_exec_ctx *exec_ctx,
+ grpc_metadata_batch *batch,
+ grpc_mdelem *(*filter)(grpc_exec_ctx *exec_ctx,
+ void *user_data,
grpc_mdelem *elem),
void *user_data);
diff --git a/src/core/lib/transport/method_config.c b/src/core/lib/transport/method_config.c
new file mode 100644
index 0000000000..25fb54b37d
--- /dev/null
+++ b/src/core/lib/transport/method_config.c
@@ -0,0 +1,347 @@
+//
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include "src/core/lib/transport/method_config.h"
+
+#include <string.h>
+
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/time.h>
+
+#include "src/core/lib/transport/mdstr_hash_table.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 void free_mem(grpc_exec_ctx* exec_ctx, void* p) { gpr_free(p); }
+
+static grpc_mdstr_hash_table_vtable bool_vtable = {free_mem, 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_mdstr_hash_table_vtable timespec_vtable = {free_mem, 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_mdstr_hash_table_vtable int32_vtable = {free_mem, 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 {
+ grpc_mdstr_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* method_config = gpr_malloc(sizeof(grpc_method_config));
+ memset(method_config, 0, sizeof(grpc_method_config));
+ method_config->wait_for_ready_key =
+ grpc_mdstr_from_string(GRPC_METHOD_CONFIG_WAIT_FOR_READY);
+ method_config->timeout_key =
+ grpc_mdstr_from_string(GRPC_METHOD_CONFIG_TIMEOUT);
+ method_config->max_request_message_bytes_key =
+ grpc_mdstr_from_string(GRPC_METHOD_CONFIG_MAX_REQUEST_MESSAGE_BYTES);
+ method_config->max_response_message_bytes_key =
+ grpc_mdstr_from_string(GRPC_METHOD_CONFIG_MAX_RESPONSE_MESSAGE_BYTES);
+ grpc_mdstr_hash_table_entry entries[4];
+ size_t num_entries = 0;
+ if (wait_for_ready != NULL) {
+ 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) {
+ entries[num_entries].key = method_config->timeout_key;
+ entries[num_entries].value = timeout;
+ entries[num_entries].vtable = &timespec_vtable;
+ ++num_entries;
+ }
+ if (max_request_message_bytes != NULL) {
+ 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) {
+ 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;
+ }
+ method_config->table = grpc_mdstr_hash_table_create(num_entries, entries);
+ return method_config;
+}
+
+grpc_method_config* grpc_method_config_ref(grpc_method_config* method_config) {
+ grpc_mdstr_hash_table_ref(method_config->table);
+ return method_config;
+}
+
+void grpc_method_config_unref(grpc_exec_ctx* exec_ctx,
+ grpc_method_config* method_config) {
+ if (grpc_mdstr_hash_table_unref(exec_ctx, method_config->table)) {
+ GRPC_MDSTR_UNREF(exec_ctx, method_config->wait_for_ready_key);
+ GRPC_MDSTR_UNREF(exec_ctx, method_config->timeout_key);
+ GRPC_MDSTR_UNREF(exec_ctx, method_config->max_request_message_bytes_key);
+ GRPC_MDSTR_UNREF(exec_ctx, method_config->max_response_message_bytes_key);
+ gpr_free(method_config);
+ }
+}
+
+int grpc_method_config_cmp(const grpc_method_config* method_config1,
+ const grpc_method_config* method_config2) {
+ return grpc_mdstr_hash_table_cmp(method_config1->table,
+ method_config2->table);
+}
+
+const bool* grpc_method_config_get_wait_for_ready(
+ const grpc_method_config* method_config) {
+ return grpc_mdstr_hash_table_get(method_config->table,
+ method_config->wait_for_ready_key);
+}
+
+const gpr_timespec* grpc_method_config_get_timeout(
+ const grpc_method_config* method_config) {
+ return grpc_mdstr_hash_table_get(method_config->table,
+ method_config->timeout_key);
+}
+
+const int32_t* grpc_method_config_get_max_request_message_bytes(
+ const grpc_method_config* method_config) {
+ return grpc_mdstr_hash_table_get(
+ method_config->table, method_config->max_request_message_bytes_key);
+}
+
+const int32_t* grpc_method_config_get_max_response_message_bytes(
+ const grpc_method_config* method_config) {
+ return grpc_mdstr_hash_table_get(
+ method_config->table, method_config->max_response_message_bytes_key);
+}
+
+//
+// grpc_method_config_table
+//
+
+static void method_config_unref(grpc_exec_ctx* exec_ctx, void* valuep) {
+ grpc_method_config_unref(exec_ctx, valuep);
+}
+
+static void* method_config_ref(void* valuep) {
+ return grpc_method_config_ref(valuep);
+}
+
+static int method_config_cmp(void* valuep1, void* valuep2) {
+ return grpc_method_config_cmp(valuep1, valuep2);
+}
+
+static const grpc_mdstr_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_mdstr_hash_table_entry* hash_table_entries =
+ gpr_malloc(sizeof(grpc_mdstr_hash_table_entry) * 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;
+ }
+ grpc_method_config_table* method_config_table =
+ grpc_mdstr_hash_table_create(num_entries, hash_table_entries);
+ gpr_free(hash_table_entries);
+ return method_config_table;
+}
+
+grpc_method_config_table* grpc_method_config_table_ref(
+ grpc_method_config_table* table) {
+ return grpc_mdstr_hash_table_ref(table);
+}
+
+void grpc_method_config_table_unref(grpc_exec_ctx* exec_ctx,
+ grpc_method_config_table* table) {
+ grpc_mdstr_hash_table_unref(exec_ctx, table);
+}
+
+int grpc_method_config_table_cmp(const grpc_method_config_table* table1,
+ const grpc_method_config_table* table2) {
+ return grpc_mdstr_hash_table_cmp(table1, table2);
+}
+
+void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx,
+ 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 (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);
+ char* buf = gpr_malloc(len + 2); // '*' and NUL
+ memcpy(buf, path_str, len);
+ buf[len] = '*';
+ buf[len + 1] = '\0';
+ grpc_mdstr* wildcard_path = grpc_mdstr_from_string(buf);
+ gpr_free(buf);
+ value = grpc_mdstr_hash_table_get(table, wildcard_path);
+ GRPC_MDSTR_UNREF(exec_ctx, wildcard_path);
+ }
+ return value;
+}
+
+static void* copy_arg(void* p) { return grpc_method_config_table_ref(p); }
+
+static void destroy_arg(grpc_exec_ctx* exec_ctx, void* p) {
+ grpc_method_config_table_unref(exec_ctx, p);
+}
+
+static int cmp_arg(void* p1, void* p2) {
+ return grpc_method_config_table_cmp(p1, p2);
+}
+
+static grpc_arg_pointer_vtable arg_vtable = {copy_arg, destroy_arg, cmp_arg};
+
+grpc_arg grpc_method_config_table_create_channel_arg(
+ grpc_method_config_table* table) {
+ grpc_arg arg;
+ arg.type = GRPC_ARG_POINTER;
+ arg.key = GRPC_ARG_SERVICE_CONFIG;
+ arg.value.pointer.p = table;
+ 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(
+ grpc_exec_ctx* exec_ctx, 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(exec_ctx, state.entries[i].key);
+ vtable->destroy_value(exec_ctx, state.entries[i].value);
+ }
+ gpr_free(state.entries);
+ // Return the new table.
+ return new_table;
+}
diff --git a/src/core/lib/transport/method_config.h b/src/core/lib/transport/method_config.h
new file mode 100644
index 0000000000..d17a493fd4
--- /dev/null
+++ b/src/core/lib/transport/method_config.h
@@ -0,0 +1,139 @@
+//
+// Copyright 2016, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+#ifndef GRPC_CORE_LIB_TRANSPORT_METHOD_CONFIG_H
+#define GRPC_CORE_LIB_TRANSPORT_METHOD_CONFIG_H
+
+#include <stdbool.h>
+
+#include <grpc/impl/codegen/gpr_types.h>
+#include <grpc/impl/codegen/grpc_types.h>
+
+#include "src/core/lib/transport/mdstr_hash_table.h"
+#include "src/core/lib/transport/metadata.h"
+
+/// Per-method configuration.
+typedef struct grpc_method_config grpc_method_config;
+
+/// Creates a grpc_method_config with the specified parameters.
+/// Any parameter may be NULL to indicate that the value is unset.
+///
+/// \a wait_for_ready indicates whether the client should wait until the
+/// request deadline for the channel to become ready, even if there is a
+/// temporary failure before the deadline while attempting to connect.
+///
+/// \a timeout indicates the timeout for calls.
+///
+/// \a max_request_message_bytes and \a max_response_message_bytes
+/// indicate the maximum sizes of the request (checked when sending) and
+/// response (checked when receiving) messages.
+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* grpc_method_config_ref(grpc_method_config* method_config);
+void grpc_method_config_unref(grpc_exec_ctx* exec_ctx,
+ grpc_method_config* method_config);
+
+/// Compares two grpc_method_configs.
+/// The sort order is stable but undefined.
+int grpc_method_config_cmp(const grpc_method_config* method_config1,
+ const grpc_method_config* method_config2);
+
+/// These methods return NULL if the requested field is unset.
+/// The caller does NOT take ownership of the result.
+const bool* grpc_method_config_get_wait_for_ready(
+ const grpc_method_config* method_config);
+const gpr_timespec* grpc_method_config_get_timeout(
+ const grpc_method_config* method_config);
+const int32_t* grpc_method_config_get_max_request_message_bytes(
+ const grpc_method_config* method_config);
+const int32_t* grpc_method_config_get_max_response_message_bytes(
+ const grpc_method_config* method_config);
+
+/// A table of method configs.
+typedef grpc_mdstr_hash_table grpc_method_config_table;
+
+typedef struct grpc_method_config_table_entry {
+ /// The name is of one of the following forms:
+ /// service/method -- specifies exact service and method name
+ /// service/* -- matches all methods for the specified service
+ grpc_mdstr* method_name;
+ grpc_method_config* method_config;
+} grpc_method_config_table_entry;
+
+/// Takes new references to all keys and values in \a entries.
+grpc_method_config_table* grpc_method_config_table_create(
+ size_t num_entries, grpc_method_config_table_entry* entries);
+
+grpc_method_config_table* grpc_method_config_table_ref(
+ grpc_method_config_table* table);
+void grpc_method_config_table_unref(grpc_exec_ctx* exec_ctx,
+ grpc_method_config_table* table);
+
+/// Compares two grpc_method_config_tables.
+/// The sort order is stable but undefined.
+int grpc_method_config_table_cmp(const grpc_method_config_table* table1,
+ const grpc_method_config_table* table2);
+
+/// Gets the method config for the specified \a path, which should be of
+/// the form "/service/method".
+/// Returns NULL if the method has no config.
+/// Caller does NOT own a reference to the result.
+///
+/// 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(grpc_exec_ctx* exec_ctx,
+ 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.
+///
+/// This is generally used to convert the table's value type from
+/// grpc_method_config to a simple struct containing only the parameters
+/// relevant to a particular filter, thus avoiding the need for a hash
+/// table lookup on the fast path. In that scenario, \a convert_value
+/// will return a new instance of the struct containing the values from
+/// the grpc_method_config, and \a vtable provides the methods for
+/// operating on the struct type.
+grpc_mdstr_hash_table* grpc_method_config_table_convert(
+ grpc_exec_ctx* exec_ctx, 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_LIB_TRANSPORT_METHOD_CONFIG_H */
diff --git a/src/core/lib/transport/pid_controller.h b/src/core/lib/transport/pid_controller.h
index 059b5b0834..83c82d6471 100644
--- a/src/core/lib/transport/pid_controller.h
+++ b/src/core/lib/transport/pid_controller.h
@@ -61,4 +61,4 @@ void grpc_pid_controller_reset(grpc_pid_controller *pid_controller);
double grpc_pid_controller_update(grpc_pid_controller *pid_controller,
double error, double dt);
-#endif
+#endif /* GRPC_CORE_LIB_TRANSPORT_PID_CONTROLLER_H */
diff --git a/src/core/lib/transport/service_config.c b/src/core/lib/transport/service_config.c
index 2e2b59e3f7..552d3ec856 100644
--- a/src/core/lib/transport/service_config.c
+++ b/src/core/lib/transport/service_config.c
@@ -146,7 +146,8 @@ static char* parse_json_method_name(grpc_json* json) {
// each name found, incrementing \a idx for each entry added.
// Returns false on error.
static bool parse_json_method_config(
- grpc_json* json, void* (*create_value)(const grpc_json* method_config_json),
+ grpc_exec_ctx* exec_ctx, grpc_json* json,
+ void* (*create_value)(const grpc_json* method_config_json),
const grpc_mdstr_hash_table_vtable* vtable,
grpc_mdstr_hash_table_entry* entries, size_t* idx) {
// Construct value.
@@ -176,13 +177,13 @@ static bool parse_json_method_config(
}
success = true;
done:
- vtable->destroy_value(method_config);
+ vtable->destroy_value(exec_ctx, method_config);
gpr_strvec_destroy(&paths);
return success;
}
grpc_mdstr_hash_table* grpc_service_config_create_method_config_table(
- const grpc_service_config* service_config,
+ grpc_exec_ctx* exec_ctx, const grpc_service_config* service_config,
void* (*create_value)(const grpc_json* method_config_json),
const grpc_mdstr_hash_table_vtable* vtable) {
const grpc_json* json = service_config->json_tree;
@@ -205,8 +206,8 @@ grpc_mdstr_hash_table* grpc_service_config_create_method_config_table(
size_t idx = 0;
for (grpc_json* method = field->child; method != NULL;
method = method->next) {
- if (!parse_json_method_config(method, create_value, vtable, entries,
- &idx)) {
+ if (!parse_json_method_config(exec_ctx, method, create_value, vtable,
+ entries, &idx)) {
return NULL;
}
}
@@ -219,15 +220,16 @@ grpc_mdstr_hash_table* grpc_service_config_create_method_config_table(
method_config_table = grpc_mdstr_hash_table_create(num_entries, entries);
// Clean up.
for (size_t i = 0; i < num_entries; ++i) {
- GRPC_MDSTR_UNREF(entries[i].key);
- vtable->destroy_value(entries[i].value);
+ GRPC_MDSTR_UNREF(exec_ctx, entries[i].key);
+ vtable->destroy_value(exec_ctx, entries[i].value);
}
gpr_free(entries);
}
return method_config_table;
}
-void* grpc_method_config_table_get(const grpc_mdstr_hash_table* table,
+void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx,
+ 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
@@ -243,7 +245,7 @@ void* grpc_method_config_table_get(const grpc_mdstr_hash_table* table,
grpc_mdstr* wildcard_path = grpc_mdstr_from_string(buf);
gpr_free(buf);
value = grpc_mdstr_hash_table_get(table, wildcard_path);
- GRPC_MDSTR_UNREF(wildcard_path);
+ GRPC_MDSTR_UNREF(exec_ctx, wildcard_path);
}
return value;
}
diff --git a/src/core/lib/transport/service_config.h b/src/core/lib/transport/service_config.h
index 2ffe475193..f0897170fa 100644
--- a/src/core/lib/transport/service_config.h
+++ b/src/core/lib/transport/service_config.h
@@ -54,7 +54,7 @@ const char* grpc_service_config_get_lb_policy_name(
/// \a vtable provides methods used to manage the values.
/// Returns NULL on error.
grpc_mdstr_hash_table* grpc_service_config_create_method_config_table(
- const grpc_service_config* service_config,
+ grpc_exec_ctx* exec_ctx, const grpc_service_config* service_config,
void* (*create_value)(const grpc_json* method_config_json),
const grpc_mdstr_hash_table_vtable* vtable);
@@ -64,7 +64,8 @@ grpc_mdstr_hash_table* grpc_service_config_create_method_config_table(
/// the form "/service/method".
/// Returns NULL if the method has no config.
/// Caller does NOT own a reference to the result.
-void* grpc_method_config_table_get(const grpc_mdstr_hash_table* table,
+void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx,
+ const grpc_mdstr_hash_table* table,
const grpc_mdstr* path);
#endif /* GRPC_CORE_LIB_TRANSPORT_SERVICE_CONFIG_H */
diff --git a/src/core/lib/transport/transport.c b/src/core/lib/transport/transport.c
index b448126da8..055edbb39f 100644
--- a/src/core/lib/transport/transport.c
+++ b/src/core/lib/transport/transport.c
@@ -40,6 +40,7 @@
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
+#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/transport_impl.h"
@@ -68,7 +69,7 @@ void grpc_stream_unref(grpc_exec_ctx *exec_ctx,
grpc_stream_refcount *refcount) {
#endif
if (gpr_unref(&refcount->refs)) {
- grpc_exec_ctx_sched(exec_ctx, &refcount->destroy, GRPC_ERROR_NONE, NULL);
+ grpc_closure_sched(exec_ctx, &refcount->destroy, GRPC_ERROR_NONE);
}
}
@@ -82,7 +83,7 @@ void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs,
grpc_iomgr_cb_func cb, void *cb_arg) {
#endif
gpr_ref_init(&refcount->refs, initial_refs);
- grpc_closure_init(&refcount->destroy, cb, cb_arg);
+ grpc_closure_init(&refcount->destroy, cb, cb_arg, grpc_schedule_on_exec_ctx);
}
static void move64(uint64_t *from, uint64_t *to) {
@@ -168,11 +169,10 @@ grpc_endpoint *grpc_transport_get_endpoint(grpc_exec_ctx *exec_ctx,
void grpc_transport_stream_op_finish_with_failure(grpc_exec_ctx *exec_ctx,
grpc_transport_stream_op *op,
grpc_error *error) {
- grpc_exec_ctx_sched(exec_ctx, op->recv_message_ready, GRPC_ERROR_REF(error),
- NULL);
- grpc_exec_ctx_sched(exec_ctx, op->recv_initial_metadata_ready,
- GRPC_ERROR_REF(error), NULL);
- grpc_exec_ctx_sched(exec_ctx, op->on_complete, error, NULL);
+ grpc_closure_sched(exec_ctx, op->recv_message_ready, GRPC_ERROR_REF(error));
+ grpc_closure_sched(exec_ctx, op->recv_initial_metadata_ready,
+ GRPC_ERROR_REF(error));
+ grpc_closure_sched(exec_ctx, op->on_complete, error);
}
typedef struct {
@@ -196,7 +196,8 @@ static void add_error(grpc_transport_stream_op *op, grpc_error **which,
cmd = gpr_malloc(sizeof(*cmd));
cmd->error = error;
cmd->then_call = op->on_complete;
- grpc_closure_init(&cmd->closure, free_message, cmd);
+ grpc_closure_init(&cmd->closure, free_message, cmd,
+ grpc_schedule_on_exec_ctx);
op->on_complete = &cmd->closure;
*which = error;
}
@@ -212,12 +213,12 @@ void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
}
void grpc_transport_stream_op_add_cancellation_with_message(
- grpc_transport_stream_op *op, grpc_status_code status,
- grpc_slice *optional_message) {
+ grpc_exec_ctx *exec_ctx, grpc_transport_stream_op *op,
+ grpc_status_code status, grpc_slice *optional_message) {
GPR_ASSERT(status != GRPC_STATUS_OK);
if (op->cancel_error != GRPC_ERROR_NONE) {
if (optional_message) {
- grpc_slice_unref(*optional_message);
+ grpc_slice_unref_internal(exec_ctx, *optional_message);
}
return;
}
@@ -227,7 +228,7 @@ void grpc_transport_stream_op_add_cancellation_with_message(
error = grpc_error_set_str(GRPC_ERROR_CREATE(msg),
GRPC_ERROR_STR_GRPC_MESSAGE, msg);
gpr_free(msg);
- grpc_slice_unref(*optional_message);
+ grpc_slice_unref_internal(exec_ctx, *optional_message);
} else {
error = GRPC_ERROR_CREATE("Call cancelled");
}
@@ -235,14 +236,15 @@ void grpc_transport_stream_op_add_cancellation_with_message(
add_error(op, &op->cancel_error, error);
}
-void grpc_transport_stream_op_add_close(grpc_transport_stream_op *op,
+void grpc_transport_stream_op_add_close(grpc_exec_ctx *exec_ctx,
+ grpc_transport_stream_op *op,
grpc_status_code status,
grpc_slice *optional_message) {
GPR_ASSERT(status != GRPC_STATUS_OK);
if (op->cancel_error != GRPC_ERROR_NONE ||
op->close_error != GRPC_ERROR_NONE) {
if (optional_message) {
- grpc_slice_unref(*optional_message);
+ grpc_slice_unref_internal(exec_ctx, *optional_message);
}
return;
}
@@ -252,7 +254,7 @@ void grpc_transport_stream_op_add_close(grpc_transport_stream_op *op,
error = grpc_error_set_str(GRPC_ERROR_CREATE(msg),
GRPC_ERROR_STR_GRPC_MESSAGE, msg);
gpr_free(msg);
- grpc_slice_unref(*optional_message);
+ grpc_slice_unref_internal(exec_ctx, *optional_message);
} else {
error = GRPC_ERROR_CREATE("Call force closed");
}
@@ -269,14 +271,14 @@ typedef struct {
static void destroy_made_transport_op(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
made_transport_op *op = arg;
- grpc_exec_ctx_sched(exec_ctx, op->inner_on_complete, GRPC_ERROR_REF(error),
- NULL);
+ grpc_closure_sched(exec_ctx, op->inner_on_complete, GRPC_ERROR_REF(error));
gpr_free(op);
}
grpc_transport_op *grpc_make_transport_op(grpc_closure *on_complete) {
made_transport_op *op = gpr_malloc(sizeof(*op));
- grpc_closure_init(&op->outer_on_complete, destroy_made_transport_op, op);
+ grpc_closure_init(&op->outer_on_complete, destroy_made_transport_op, op,
+ grpc_schedule_on_exec_ctx);
op->inner_on_complete = on_complete;
memset(&op->op, 0, sizeof(op->op));
op->op.on_consumed = &op->outer_on_complete;
@@ -292,8 +294,7 @@ typedef struct {
static void destroy_made_transport_stream_op(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
made_transport_stream_op *op = arg;
- grpc_exec_ctx_sched(exec_ctx, op->inner_on_complete, GRPC_ERROR_REF(error),
- NULL);
+ grpc_closure_sched(exec_ctx, op->inner_on_complete, GRPC_ERROR_REF(error));
gpr_free(op);
}
@@ -301,7 +302,7 @@ grpc_transport_stream_op *grpc_make_transport_stream_op(
grpc_closure *on_complete) {
made_transport_stream_op *op = gpr_malloc(sizeof(*op));
grpc_closure_init(&op->outer_on_complete, destroy_made_transport_stream_op,
- op);
+ op, grpc_schedule_on_exec_ctx);
op->inner_on_complete = on_complete;
memset(&op->op, 0, sizeof(op->op));
op->op.on_complete = &op->outer_on_complete;
diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h
index 96c26749c8..d1281830aa 100644
--- a/src/core/lib/transport/transport.h
+++ b/src/core/lib/transport/transport.h
@@ -249,10 +249,11 @@ void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
grpc_status_code status);
void grpc_transport_stream_op_add_cancellation_with_message(
- grpc_transport_stream_op *op, grpc_status_code status,
- grpc_slice *optional_message);
+ grpc_exec_ctx *exec_ctx, grpc_transport_stream_op *op,
+ grpc_status_code status, grpc_slice *optional_message);
-void grpc_transport_stream_op_add_close(grpc_transport_stream_op *op,
+void grpc_transport_stream_op_add_close(grpc_exec_ctx *exec_ctx,
+ grpc_transport_stream_op *op,
grpc_status_code status,
grpc_slice *optional_message);