diff options
Diffstat (limited to 'src/core/lib/transport/metadata_batch.c')
-rw-r--r-- | src/core/lib/transport/metadata_batch.c | 242 |
1 files changed, 64 insertions, 178 deletions
diff --git a/src/core/lib/transport/metadata_batch.c b/src/core/lib/transport/metadata_batch.c index 95b71d33d7..b62ecc3aa6 100644 --- a/src/core/lib/transport/metadata_batch.c +++ b/src/core/lib/transport/metadata_batch.c @@ -40,8 +40,6 @@ #include <grpc/support/log.h> #include "src/core/lib/profiling/timers.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/slice/slice_string_helpers.h" static void assert_valid_list(grpc_mdelem_list *list) { #ifndef NDEBUG @@ -53,34 +51,16 @@ static void assert_valid_list(grpc_mdelem_list *list) { GPR_ASSERT(list->tail->next == NULL); GPR_ASSERT((list->head == list->tail) == (list->head->next == NULL)); - size_t verified_count = 0; for (l = list->head; l; l = l->next) { - GPR_ASSERT(!GRPC_MDISNULL(l->md)); + GPR_ASSERT(l->md); GPR_ASSERT((l->prev == NULL) == (l == list->head)); GPR_ASSERT((l->next == NULL) == (l == list->tail)); if (l->next) GPR_ASSERT(l->next->prev == l); if (l->prev) GPR_ASSERT(l->prev->next == l); - verified_count++; } - GPR_ASSERT(list->count == verified_count); #endif /* NDEBUG */ } -static void assert_valid_callouts(grpc_exec_ctx *exec_ctx, - grpc_metadata_batch *batch) { -#ifndef NDEBUG - for (grpc_linked_mdelem *l = batch->list.head; l != NULL; l = l->next) { - grpc_slice key_interned = grpc_slice_intern(GRPC_MDKEY(l->md)); - grpc_metadata_batch_callouts_index callout_idx = - GRPC_BATCH_INDEX_OF(key_interned); - if (callout_idx != GRPC_BATCH_CALLOUTS_COUNT) { - GPR_ASSERT(batch->idx.array[callout_idx] == l); - } - grpc_slice_unref_internal(exec_ctx, key_interned); - } -#endif -} - #ifndef NDEBUG void grpc_metadata_batch_assert_ok(grpc_metadata_batch *batch) { assert_valid_list(&batch->list); @@ -88,7 +68,7 @@ void grpc_metadata_batch_assert_ok(grpc_metadata_batch *batch) { #endif /* NDEBUG */ void grpc_metadata_batch_init(grpc_metadata_batch *batch) { - memset(batch, 0, sizeof(*batch)); + batch->list.head = batch->list.tail = NULL; batch->deadline = gpr_inf_future(GPR_CLOCK_REALTIME); } @@ -100,58 +80,17 @@ void grpc_metadata_batch_destroy(grpc_exec_ctx *exec_ctx, } } -grpc_error *grpc_attach_md_to_error(grpc_error *src, grpc_mdelem md) { - char *k = grpc_slice_to_c_string(GRPC_MDKEY(md)); - char *v = grpc_slice_to_c_string(GRPC_MDVALUE(md)); - grpc_error *out = grpc_error_set_str( - grpc_error_set_str(src, GRPC_ERROR_STR_KEY, k), GRPC_ERROR_STR_VALUE, v); - gpr_free(k); - gpr_free(v); - return out; -} - -static grpc_error *maybe_link_callout(grpc_metadata_batch *batch, - grpc_linked_mdelem *storage) - GRPC_MUST_USE_RESULT; - -static grpc_error *maybe_link_callout(grpc_metadata_batch *batch, - grpc_linked_mdelem *storage) { - grpc_metadata_batch_callouts_index idx = - GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)); - if (idx == GRPC_BATCH_CALLOUTS_COUNT) { - return GRPC_ERROR_NONE; - } - if (batch->idx.array[idx] == NULL) { - batch->idx.array[idx] = storage; - return GRPC_ERROR_NONE; - } - return grpc_attach_md_to_error( - GRPC_ERROR_CREATE("Unallowed duplicate metadata"), storage->md); -} - -static void maybe_unlink_callout(grpc_metadata_batch *batch, - grpc_linked_mdelem *storage) { - grpc_metadata_batch_callouts_index idx = - GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)); - if (idx == GRPC_BATCH_CALLOUTS_COUNT) { - return; - } - GPR_ASSERT(batch->idx.array[idx] != NULL); - batch->idx.array[idx] = NULL; -} - -grpc_error *grpc_metadata_batch_add_head(grpc_exec_ctx *exec_ctx, - grpc_metadata_batch *batch, - grpc_linked_mdelem *storage, - grpc_mdelem elem_to_add) { - GPR_ASSERT(!GRPC_MDISNULL(elem_to_add)); +void grpc_metadata_batch_add_head(grpc_metadata_batch *batch, + grpc_linked_mdelem *storage, + grpc_mdelem *elem_to_add) { + GPR_ASSERT(elem_to_add); storage->md = elem_to_add; - return grpc_metadata_batch_link_head(exec_ctx, batch, storage); + grpc_metadata_batch_link_head(batch, storage); } static void link_head(grpc_mdelem_list *list, grpc_linked_mdelem *storage) { assert_valid_list(list); - GPR_ASSERT(!GRPC_MDISNULL(storage->md)); + GPR_ASSERT(storage->md); storage->prev = NULL; storage->next = list->head; if (list->head != NULL) { @@ -160,36 +99,25 @@ static void link_head(grpc_mdelem_list *list, grpc_linked_mdelem *storage) { list->tail = storage; } list->head = storage; - list->count++; assert_valid_list(list); } -grpc_error *grpc_metadata_batch_link_head(grpc_exec_ctx *exec_ctx, - grpc_metadata_batch *batch, - grpc_linked_mdelem *storage) { - assert_valid_callouts(exec_ctx, batch); - grpc_error *err = maybe_link_callout(batch, storage); - if (err != GRPC_ERROR_NONE) { - assert_valid_callouts(exec_ctx, batch); - return err; - } +void grpc_metadata_batch_link_head(grpc_metadata_batch *batch, + grpc_linked_mdelem *storage) { link_head(&batch->list, storage); - assert_valid_callouts(exec_ctx, batch); - return GRPC_ERROR_NONE; } -grpc_error *grpc_metadata_batch_add_tail(grpc_exec_ctx *exec_ctx, - grpc_metadata_batch *batch, - grpc_linked_mdelem *storage, - grpc_mdelem elem_to_add) { - GPR_ASSERT(!GRPC_MDISNULL(elem_to_add)); +void grpc_metadata_batch_add_tail(grpc_metadata_batch *batch, + grpc_linked_mdelem *storage, + grpc_mdelem *elem_to_add) { + GPR_ASSERT(elem_to_add); storage->md = elem_to_add; - return grpc_metadata_batch_link_tail(exec_ctx, batch, storage); + grpc_metadata_batch_link_tail(batch, storage); } static void link_tail(grpc_mdelem_list *list, grpc_linked_mdelem *storage) { assert_valid_list(list); - GPR_ASSERT(!GRPC_MDISNULL(storage->md)); + GPR_ASSERT(storage->md); storage->prev = list->tail; storage->next = NULL; storage->reserved = NULL; @@ -199,82 +127,70 @@ static void link_tail(grpc_mdelem_list *list, grpc_linked_mdelem *storage) { list->head = storage; } list->tail = storage; - list->count++; assert_valid_list(list); } -grpc_error *grpc_metadata_batch_link_tail(grpc_exec_ctx *exec_ctx, - grpc_metadata_batch *batch, - grpc_linked_mdelem *storage) { - assert_valid_callouts(exec_ctx, batch); - grpc_error *err = maybe_link_callout(batch, storage); - if (err != GRPC_ERROR_NONE) { - assert_valid_callouts(exec_ctx, batch); - return err; - } +void grpc_metadata_batch_link_tail(grpc_metadata_batch *batch, + grpc_linked_mdelem *storage) { link_tail(&batch->list, storage); - assert_valid_callouts(exec_ctx, batch); - return GRPC_ERROR_NONE; } -static void unlink_storage(grpc_mdelem_list *list, - grpc_linked_mdelem *storage) { - assert_valid_list(list); - if (storage->prev != NULL) { - storage->prev->next = storage->next; - } else { - list->head = storage->next; - } - if (storage->next != NULL) { - storage->next->prev = storage->prev; - } else { - list->tail = storage->prev; - } - list->count--; - assert_valid_list(list); +void grpc_metadata_batch_move(grpc_metadata_batch *dst, + grpc_metadata_batch *src) { + *dst = *src; + memset(src, 0, sizeof(grpc_metadata_batch)); } -void grpc_metadata_batch_remove(grpc_exec_ctx *exec_ctx, +void grpc_metadata_batch_filter(grpc_exec_ctx *exec_ctx, grpc_metadata_batch *batch, - grpc_linked_mdelem *storage) { - assert_valid_callouts(exec_ctx, batch); - maybe_unlink_callout(batch, storage); - unlink_storage(&batch->list, storage); - GRPC_MDELEM_UNREF(exec_ctx, storage->md); - assert_valid_callouts(exec_ctx, batch); -} + grpc_mdelem *(*filter)(grpc_exec_ctx *exec_ctx, + void *user_data, + grpc_mdelem *elem), + void *user_data) { + grpc_linked_mdelem *l; + grpc_linked_mdelem *next; -void grpc_metadata_batch_set_value(grpc_exec_ctx *exec_ctx, - grpc_linked_mdelem *storage, - grpc_slice value) { - grpc_mdelem old = storage->md; - grpc_mdelem new = grpc_mdelem_from_slices( - exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(old)), value); - storage->md = new; - GRPC_MDELEM_UNREF(exec_ctx, old); -} + GPR_TIMER_BEGIN("grpc_metadata_batch_filter", 0); -grpc_error *grpc_metadata_batch_substitute(grpc_exec_ctx *exec_ctx, - grpc_metadata_batch *batch, - grpc_linked_mdelem *storage, - grpc_mdelem new) { - grpc_error *error = GRPC_ERROR_NONE; - grpc_mdelem old = storage->md; - if (!grpc_slice_eq(GRPC_MDKEY(new), GRPC_MDKEY(old))) { - maybe_unlink_callout(batch, storage); - storage->md = new; - error = maybe_link_callout(batch, storage); - } else { - storage->md = new; + assert_valid_list(&batch->list); + for (l = batch->list.head; l; l = next) { + grpc_mdelem *orig = l->md; + grpc_mdelem *filt = filter(exec_ctx, user_data, orig); + next = l->next; + if (filt == NULL) { + if (l->prev) { + l->prev->next = l->next; + } + if (l->next) { + l->next->prev = l->prev; + } + if (batch->list.head == l) { + batch->list.head = l->next; + } + if (batch->list.tail == l) { + batch->list.tail = l->prev; + } + assert_valid_list(&batch->list); + GRPC_MDELEM_UNREF(exec_ctx, l->md); + } else if (filt != orig) { + GRPC_MDELEM_UNREF(exec_ctx, orig); + l->md = filt; + } } - GRPC_MDELEM_UNREF(exec_ctx, old); - return error; + assert_valid_list(&batch->list); + + GPR_TIMER_END("grpc_metadata_batch_filter", 0); +} + +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_exec_ctx *exec_ctx, grpc_metadata_batch *batch) { - grpc_metadata_batch_destroy(exec_ctx, batch); - grpc_metadata_batch_init(batch); + batch->deadline = gpr_inf_future(GPR_CLOCK_REALTIME); + grpc_metadata_batch_filter(exec_ctx, batch, no_metadata_for_you, NULL); } bool grpc_metadata_batch_is_empty(grpc_metadata_batch *batch) { @@ -291,33 +207,3 @@ size_t grpc_metadata_batch_size(grpc_metadata_batch *batch) { } return size; } - -static void add_error(grpc_error **composite, grpc_error *error, - const char *composite_error_string) { - if (error == GRPC_ERROR_NONE) return; - if (*composite == GRPC_ERROR_NONE) { - *composite = GRPC_ERROR_CREATE(composite_error_string); - } - *composite = grpc_error_add_child(*composite, error); -} - -grpc_error *grpc_metadata_batch_filter(grpc_exec_ctx *exec_ctx, - grpc_metadata_batch *batch, - grpc_metadata_batch_filter_func func, - void *user_data, - const char *composite_error_string) { - grpc_linked_mdelem *l = batch->list.head; - grpc_error *error = GRPC_ERROR_NONE; - while (l) { - grpc_linked_mdelem *next = l->next; - grpc_filtered_mdelem new = func(exec_ctx, user_data, l->md); - add_error(&error, new.error, composite_error_string); - if (GRPC_MDISNULL(new.md)) { - grpc_metadata_batch_remove(exec_ctx, batch, l); - } else if (new.md.payload != l->md.payload) { - grpc_metadata_batch_substitute(exec_ctx, batch, l, new.md); - } - l = next; - } - return error; -} |