aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/grpc/impl/codegen/grpc_types.h3
-rw-r--r--src/core/ext/lb_policy/grpclb/grpclb.c16
-rw-r--r--src/core/lib/slice/slice_intern.c5
-rw-r--r--src/core/lib/slice/slice_internal.h3
-rw-r--r--src/core/lib/transport/metadata.c268
-rw-r--r--src/core/lib/transport/metadata.h51
-rw-r--r--src/core/lib/transport/static_metadata.c3
-rw-r--r--src/core/lib/transport/static_metadata.h204
-rw-r--r--test/core/transport/metadata_test.c38
-rwxr-xr-xtools/codegen/core/gen_static_metadata.py6
10 files changed, 413 insertions, 184 deletions
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index 5170621bbb..ac9a007641 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -292,8 +292,11 @@ typedef enum grpc_call_error {
/** A single metadata element */
typedef struct grpc_metadata {
+ /* the key, value values are expected to line up with grpc_mdelem: if changing
+ them, update metadata.h at the same time. */
grpc_slice key;
grpc_slice value;
+
uint32_t flags;
/** The following fields are reserved for grpc internal use.
diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c
index b10b980331..795d68d5e7 100644
--- a/src/core/ext/lb_policy/grpclb/grpclb.c
+++ b/src/core/ext/lb_policy/grpclb/grpclb.c
@@ -381,10 +381,14 @@ static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
/* vtable for LB tokens in grpc_lb_addresses. */
static void *lb_token_copy(void *token) {
- return token == NULL ? NULL : GRPC_MDELEM_REF((grpc_mdelem){token}).payload;
+ return token == NULL
+ ? NULL
+ : (void *)GRPC_MDELEM_REF((grpc_mdelem){(uintptr_t)token}).payload;
}
static void lb_token_destroy(grpc_exec_ctx *exec_ctx, void *token) {
- if (token != NULL) GRPC_MDELEM_UNREF(exec_ctx, (grpc_mdelem){token});
+ if (token != NULL) {
+ GRPC_MDELEM_UNREF(exec_ctx, (grpc_mdelem){(uintptr_t)token});
+ }
}
static int lb_token_cmp(void *token1, void *token2) {
if (token1 > token2) return 1;
@@ -454,9 +458,9 @@ static grpc_lb_addresses *process_serverlist_locked(
strnlen(server->load_balance_token, lb_token_max_length);
grpc_slice lb_token_mdstr = grpc_slice_from_copied_buffer(
server->load_balance_token, lb_token_length);
- user_data =
- grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_LB_TOKEN, lb_token_mdstr)
- .payload;
+ user_data = (void *)grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_LB_TOKEN,
+ lb_token_mdstr)
+ .payload;
} else {
char *uri = grpc_sockaddr_to_uri(&addr);
gpr_log(GPR_INFO,
@@ -464,7 +468,7 @@ static grpc_lb_addresses *process_serverlist_locked(
"be used instead",
uri);
gpr_free(uri);
- user_data = GRPC_MDELEM_LB_TOKEN_EMPTY.payload;
+ user_data = (void *)GRPC_MDELEM_LB_TOKEN_EMPTY.payload;
}
grpc_lb_addresses_set_address(lb_addresses, addr_idx, &addr.addr, addr.len,
diff --git a/src/core/lib/slice/slice_intern.c b/src/core/lib/slice/slice_intern.c
index 6f65a3dcc8..2d93284926 100644
--- a/src/core/lib/slice/slice_intern.c
+++ b/src/core/lib/slice/slice_intern.c
@@ -193,6 +193,11 @@ void grpc_slice_static_intern(grpc_slice *slice) {
}
}
+bool grpc_slice_is_interned(grpc_slice slice) {
+ return (slice.refcount && slice.refcount->vtable == &interned_slice_vtable) ||
+ grpc_is_static_metadata_string(slice);
+}
+
grpc_slice grpc_slice_intern(grpc_slice slice) {
if (grpc_is_static_metadata_string(slice)) {
return slice;
diff --git a/src/core/lib/slice/slice_internal.h b/src/core/lib/slice/slice_internal.h
index 695bd308ad..211d5f06be 100644
--- a/src/core/lib/slice/slice_internal.h
+++ b/src/core/lib/slice/slice_internal.h
@@ -46,6 +46,9 @@ void grpc_slice_buffer_reset_and_unref_internal(grpc_exec_ctx *exec_ctx,
void grpc_slice_buffer_destroy_internal(grpc_exec_ctx *exec_ctx,
grpc_slice_buffer *sb);
+/* Check if a slice is interned */
+bool grpc_slice_is_interned(grpc_slice slice);
+
void grpc_slice_intern_init(void);
void grpc_slice_intern_shutdown(void);
void grpc_test_only_set_slice_hash_seed(uint32_t key);
diff --git a/src/core/lib/transport/metadata.c b/src/core/lib/transport/metadata.c
index c114cf9a30..f3f6b1311f 100644
--- a/src/core/lib/transport/metadata.c
+++ b/src/core/lib/transport/metadata.c
@@ -80,9 +80,9 @@
typedef void (*destroy_user_data_func)(void *user_data);
-/* Shadow structure for grpc_mdelem_data for non-static elements */
-typedef struct internal_metadata {
- /* must be byte compatible with grpc_mdelem */
+/* Shadow structure for grpc_mdelem_data for interned elements */
+typedef struct interned_metadata {
+ /* must be byte compatible with grpc_mdelem_data */
grpc_slice key;
grpc_slice value;
@@ -93,12 +93,22 @@ typedef struct internal_metadata {
gpr_atm destroy_user_data;
gpr_atm user_data;
- struct internal_metadata *bucket_next;
-} internal_metadata;
+ struct interned_metadata *bucket_next;
+} interned_metadata;
+
+/* Shadow structure for grpc_mdelem_data for allocated elements */
+typedef struct allocated_metadata {
+ /* must be byte compatible with grpc_mdelem_data */
+ grpc_slice key;
+ grpc_slice value;
+
+ /* private only data */
+ gpr_atm refcnt;
+} allocated_metadata;
typedef struct mdtab_shard {
gpr_mu mu;
- internal_metadata **elems;
+ interned_metadata **elems;
size_t count;
size_t capacity;
/** Estimate of the number of unreferenced mdelems in the hash table.
@@ -142,12 +152,13 @@ void grpc_mdctx_global_shutdown(grpc_exec_ctx *exec_ctx) {
}
static int is_mdelem_static(grpc_mdelem e) {
- return e.payload >= &grpc_static_mdelem_table[0] &&
- e.payload < &grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
+ return GRPC_MDELEM_DATA(e) >= &grpc_static_mdelem_table[0] &&
+ GRPC_MDELEM_DATA(e) <
+ &grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
}
static void ref_md_locked(mdtab_shard *shard,
- internal_metadata *md DEBUG_ARGS) {
+ interned_metadata *md DEBUG_ARGS) {
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"ELM REF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
@@ -163,8 +174,8 @@ static void ref_md_locked(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;
+ interned_metadata **prev_next;
+ interned_metadata *md, *next;
gpr_atm num_freed = 0;
GPR_TIMER_BEGIN("gc_mdtab", 0);
@@ -196,14 +207,14 @@ static void gc_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard) {
static void grow_mdtab(mdtab_shard *shard) {
size_t capacity = shard->capacity * 2;
size_t i;
- internal_metadata **mdtab;
- internal_metadata *md, *next;
+ interned_metadata **mdtab;
+ interned_metadata *md, *next;
uint32_t hash;
GPR_TIMER_BEGIN("grow_mdtab", 0);
- mdtab = gpr_malloc(sizeof(internal_metadata *) * capacity);
- memset(mdtab, 0, sizeof(internal_metadata *) * capacity);
+ mdtab = gpr_malloc(sizeof(interned_metadata *) * capacity);
+ memset(mdtab, 0, sizeof(interned_metadata *) * capacity);
for (i = 0; i < shard->capacity; i++) {
for (md = shard->elems[i]; md; md = next) {
@@ -233,10 +244,21 @@ static void rehash_mdtab(grpc_exec_ctx *exec_ctx, mdtab_shard *shard) {
}
}
-grpc_mdelem grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key,
- grpc_slice value) {
- grpc_slice_static_intern(&key);
- grpc_slice_static_intern(&value);
+grpc_mdelem grpc_mdelem_create(
+ grpc_exec_ctx *exec_ctx, grpc_slice key, grpc_slice value,
+ grpc_mdelem_data *compatible_external_backing_store) {
+ if (!grpc_slice_is_interned(key) || !grpc_slice_is_interned(value)) {
+ if (compatible_external_backing_store != NULL) {
+ return GRPC_MAKE_MDELEM(compatible_external_backing_store,
+ GRPC_MDELEM_STORAGE_EXTERNAL);
+ }
+
+ allocated_metadata *allocated = gpr_malloc(sizeof(*allocated));
+ allocated->key = grpc_slice_ref_internal(key);
+ allocated->value = grpc_slice_ref_internal(value);
+ gpr_atm_rel_store(&allocated->refcnt, 1);
+ return GRPC_MAKE_MDELEM(allocated, GRPC_MDELEM_STORAGE_ALLOCATED);
+ }
grpc_mdelem static_elem = grpc_static_mdelem_for_static_strings(
grpc_static_metadata_index(key), grpc_static_metadata_index(value));
@@ -246,7 +268,7 @@ grpc_mdelem grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key,
uint32_t hash =
GRPC_MDSTR_KV_HASH(grpc_slice_hash(key), grpc_slice_hash(value));
- internal_metadata *md;
+ interned_metadata *md;
mdtab_shard *shard = &g_shards[SHARD_IDX(hash)];
size_t idx;
@@ -261,18 +283,16 @@ grpc_mdelem grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key,
grpc_slice_cmp(value, md->value) == 0) {
REF_MD_LOCKED(shard, md);
gpr_mu_unlock(&shard->mu);
- grpc_slice_unref_internal(exec_ctx, key);
- grpc_slice_unref_internal(exec_ctx, value);
GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0);
- return (grpc_mdelem){(grpc_mdelem_data *)md};
+ return GRPC_MAKE_MDELEM(md, GRPC_MDELEM_STORAGE_INTERNED);
}
}
/* not found: create a new pair */
- md = gpr_malloc(sizeof(internal_metadata));
+ md = gpr_malloc(sizeof(interned_metadata));
gpr_atm_rel_store(&md->refcnt, 1);
- md->key = key;
- md->value = value;
+ md->key = grpc_slice_ref_internal(key);
+ md->value = grpc_slice_ref_internal(value);
md->user_data = 0;
md->destroy_user_data = 0;
md->bucket_next = shard->elems[idx];
@@ -294,7 +314,21 @@ grpc_mdelem grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key,
GPR_TIMER_END("grpc_mdelem_from_metadata_strings", 0);
- return (grpc_mdelem){(grpc_mdelem_data *)md};
+ return GRPC_MAKE_MDELEM(md, GRPC_MDELEM_STORAGE_INTERNED);
+}
+
+grpc_mdelem grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key,
+ grpc_slice value) {
+ grpc_mdelem out = grpc_mdelem_create(exec_ctx, key, value, NULL);
+ grpc_slice_unref_internal(exec_ctx, key);
+ grpc_slice_unref_internal(exec_ctx, value);
+ return out;
+}
+
+grpc_mdelem grpc_mdelem_from_grpc_metadata(grpc_exec_ctx *exec_ctx,
+ grpc_metadata *metadata) {
+ return grpc_mdelem_create(exec_ctx, metadata->key, metadata->value,
+ (grpc_mdelem_data *)metadata);
}
static size_t get_base64_encoded_size(size_t raw_length) {
@@ -313,81 +347,151 @@ size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem elem) {
}
grpc_mdelem grpc_mdelem_ref(grpc_mdelem gmd DEBUG_ARGS) {
- if (gmd.payload == NULL || is_mdelem_static(gmd)) return gmd;
- internal_metadata *md = (internal_metadata *)gmd.payload;
+ switch (GRPC_MDELEM_STORAGE(gmd)) {
+ case GRPC_MDELEM_STORAGE_EXTERNAL:
+ case GRPC_MDELEM_STORAGE_STATIC:
+ break;
+ case GRPC_MDELEM_STORAGE_INTERNED: {
+ interned_metadata *md = (interned_metadata *)GRPC_MDELEM_DATA(gmd);
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
- gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
- "ELM REF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
- gpr_atm_no_barrier_load(&md->refcnt),
- gpr_atm_no_barrier_load(&md->refcnt) + 1,
- grpc_mdstr_as_c_string((grpc_slice)md->key),
- grpc_mdstr_as_c_string((grpc_slice)md->value));
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+ "ELM REF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
+ gpr_atm_no_barrier_load(&md->refcnt),
+ gpr_atm_no_barrier_load(&md->refcnt) + 1,
+ grpc_mdstr_as_c_string((grpc_slice)md->key),
+ grpc_mdstr_as_c_string((grpc_slice)md->value));
+#endif
+ /* we can assume the ref count is >= 1 as the application is calling
+ this function - meaning that no adjustment to mdtab_free is necessary,
+ simplifying the logic here to be just an atomic increment */
+ /* use C assert to have this removed in opt builds */
+ GPR_ASSERT(gpr_atm_no_barrier_load(&md->refcnt) >= 1);
+ gpr_atm_no_barrier_fetch_add(&md->refcnt, 1);
+ break;
+ }
+ case GRPC_MDELEM_STORAGE_ALLOCATED: {
+ allocated_metadata *md = (allocated_metadata *)GRPC_MDELEM_DATA(gmd);
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+ "ELM REF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
+ gpr_atm_no_barrier_load(&md->refcnt),
+ gpr_atm_no_barrier_load(&md->refcnt) + 1,
+ grpc_mdstr_as_c_string((grpc_slice)md->key),
+ grpc_mdstr_as_c_string((grpc_slice)md->value));
#endif
- /* we can assume the ref count is >= 1 as the application is calling
- this function - meaning that no adjustment to mdtab_free is necessary,
- simplifying the logic here to be just an atomic increment */
- /* use C assert to have this removed in opt builds */
- GPR_ASSERT(gpr_atm_no_barrier_load(&md->refcnt) >= 1);
- gpr_atm_no_barrier_fetch_add(&md->refcnt, 1);
+ /* we can assume the ref count is >= 1 as the application is calling
+ this function - meaning that no adjustment to mdtab_free is necessary,
+ simplifying the logic here to be just an atomic increment */
+ /* use C assert to have this removed in opt builds */
+ gpr_atm_no_barrier_fetch_add(&md->refcnt, 1);
+ break;
+ }
+ }
return gmd;
}
void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem gmd DEBUG_ARGS) {
- if (gmd.payload == NULL || is_mdelem_static(gmd)) return;
- internal_metadata *md = (internal_metadata *)gmd.payload;
+ switch (GRPC_MDELEM_STORAGE(gmd)) {
+ case GRPC_MDELEM_STORAGE_EXTERNAL:
+ case GRPC_MDELEM_STORAGE_STATIC:
+ break;
+ case GRPC_MDELEM_STORAGE_INTERNED: {
+ interned_metadata *md = (interned_metadata *)GRPC_MDELEM_DATA(gmd);
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
- gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
- "ELM UNREF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
- gpr_atm_no_barrier_load(&md->refcnt),
- gpr_atm_no_barrier_load(&md->refcnt) - 1,
- grpc_mdstr_as_c_string((grpc_slice)md->key),
- grpc_mdstr_as_c_string((grpc_slice)md->value));
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+ "ELM UNREF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
+ gpr_atm_no_barrier_load(&md->refcnt),
+ gpr_atm_no_barrier_load(&md->refcnt) - 1,
+ grpc_mdstr_as_c_string((grpc_slice)md->key),
+ grpc_mdstr_as_c_string((grpc_slice)md->value));
#endif
- uint32_t hash =
- GRPC_MDSTR_KV_HASH(grpc_slice_hash(md->key), grpc_slice_hash(md->value));
- const gpr_atm prev_refcount = gpr_atm_full_fetch_add(&md->refcnt, -1);
- GPR_ASSERT(prev_refcount >= 1);
- if (1 == prev_refcount) {
- /* once the refcount hits zero, some other thread can come along and
- free md at any time: it's unsafe from this point on to access it */
- mdtab_shard *shard = &g_shards[SHARD_IDX(hash)];
- gpr_atm_no_barrier_fetch_add(&shard->free_estimate, 1);
+ uint32_t hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(md->key),
+ grpc_slice_hash(md->value));
+ const gpr_atm prev_refcount = gpr_atm_full_fetch_add(&md->refcnt, -1);
+ GPR_ASSERT(prev_refcount >= 1);
+ if (1 == prev_refcount) {
+ /* once the refcount hits zero, some other thread can come along and
+ free md at any time: it's unsafe from this point on to access it */
+ mdtab_shard *shard = &g_shards[SHARD_IDX(hash)];
+ gpr_atm_no_barrier_fetch_add(&shard->free_estimate, 1);
+ }
+ break;
+ }
+ case GRPC_MDELEM_STORAGE_ALLOCATED: {
+ allocated_metadata *md = (allocated_metadata *)GRPC_MDELEM_DATA(gmd);
+#ifdef GRPC_METADATA_REFCOUNT_DEBUG
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+ "ELM UNREF:%p:%zu->%zu: '%s' = '%s'", (void *)md,
+ gpr_atm_no_barrier_load(&md->refcnt),
+ gpr_atm_no_barrier_load(&md->refcnt) - 1,
+ grpc_mdstr_as_c_string((grpc_slice)md->key),
+ grpc_mdstr_as_c_string((grpc_slice)md->value));
+#endif
+ const gpr_atm prev_refcount = gpr_atm_full_fetch_add(&md->refcnt, -1);
+ GPR_ASSERT(prev_refcount >= 1);
+ if (1 == prev_refcount) {
+ grpc_slice_unref_internal(exec_ctx, md->key);
+ grpc_slice_unref_internal(exec_ctx, md->value);
+ gpr_free(md);
+ }
+ break;
+ }
}
}
void *grpc_mdelem_get_user_data(grpc_mdelem md, void (*destroy_func)(void *)) {
- internal_metadata *im = (internal_metadata *)md.payload;
- void *result;
- if (is_mdelem_static(md)) {
- return (void *)
- grpc_static_mdelem_user_data[md.payload - grpc_static_mdelem_table];
- }
- if (gpr_atm_acq_load(&im->destroy_user_data) == (gpr_atm)destroy_func) {
- return (void *)gpr_atm_no_barrier_load(&im->user_data);
- } else {
- return NULL;
+ switch (GRPC_MDELEM_STORAGE(md)) {
+ case GRPC_MDELEM_STORAGE_EXTERNAL:
+ case GRPC_MDELEM_STORAGE_ALLOCATED:
+ return NULL;
+ case GRPC_MDELEM_STORAGE_STATIC:
+ return (void *)grpc_static_mdelem_user_data[GRPC_MDELEM_DATA(md) -
+ grpc_static_mdelem_table];
+ case GRPC_MDELEM_STORAGE_INTERNED: {
+ interned_metadata *im = (interned_metadata *)GRPC_MDELEM_DATA(md);
+ void *result;
+ if (gpr_atm_acq_load(&im->destroy_user_data) == (gpr_atm)destroy_func) {
+ return (void *)gpr_atm_no_barrier_load(&im->user_data);
+ } else {
+ return NULL;
+ }
+ return result;
+ }
}
- return result;
+ GPR_UNREACHABLE_CODE(return NULL);
}
void *grpc_mdelem_set_user_data(grpc_mdelem md, void (*destroy_func)(void *),
void *user_data) {
- internal_metadata *im = (internal_metadata *)md.payload;
- GPR_ASSERT(!is_mdelem_static(md));
- GPR_ASSERT((user_data == NULL) == (destroy_func == NULL));
- gpr_mu_lock(&im->mu_user_data);
- if (gpr_atm_no_barrier_load(&im->destroy_user_data)) {
- /* user data can only be set once */
- gpr_mu_unlock(&im->mu_user_data);
- if (destroy_func != NULL) {
+ switch (GRPC_MDELEM_STORAGE(md)) {
+ case GRPC_MDELEM_STORAGE_EXTERNAL:
+ case GRPC_MDELEM_STORAGE_ALLOCATED:
destroy_func(user_data);
+ return NULL;
+ case GRPC_MDELEM_STORAGE_STATIC:
+ destroy_func(user_data);
+ return (void *)grpc_static_mdelem_user_data[GRPC_MDELEM_DATA(md) -
+ grpc_static_mdelem_table];
+ case GRPC_MDELEM_STORAGE_INTERNED: {
+ interned_metadata *im = (interned_metadata *)GRPC_MDELEM_DATA(md);
+ GPR_ASSERT(!is_mdelem_static(md));
+ GPR_ASSERT((user_data == NULL) == (destroy_func == NULL));
+ gpr_mu_lock(&im->mu_user_data);
+ if (gpr_atm_no_barrier_load(&im->destroy_user_data)) {
+ /* user data can only be set once */
+ gpr_mu_unlock(&im->mu_user_data);
+ if (destroy_func != NULL) {
+ destroy_func(user_data);
+ }
+ return (void *)gpr_atm_no_barrier_load(&im->user_data);
+ }
+ gpr_atm_no_barrier_store(&im->user_data, (gpr_atm)user_data);
+ gpr_atm_rel_store(&im->destroy_user_data, (gpr_atm)destroy_func);
+ gpr_mu_unlock(&im->mu_user_data);
+ return user_data;
}
- return (void *)gpr_atm_no_barrier_load(&im->user_data);
}
- gpr_atm_no_barrier_store(&im->user_data, (gpr_atm)user_data);
- gpr_atm_rel_store(&im->destroy_user_data, (gpr_atm)destroy_func);
- gpr_mu_unlock(&im->mu_user_data);
- return user_data;
+ GPR_UNREACHABLE_CODE(return NULL);
}
bool grpc_mdelem_eq(grpc_mdelem a, grpc_mdelem b) {
diff --git a/src/core/lib/transport/metadata.h b/src/core/lib/transport/metadata.h
index da5416bf76..6d0afbe789 100644
--- a/src/core/lib/transport/metadata.h
+++ b/src/core/lib/transport/metadata.h
@@ -34,6 +34,7 @@
#ifndef GRPC_CORE_LIB_TRANSPORT_METADATA_H
#define GRPC_CORE_LIB_TRANSPORT_METADATA_H
+#include <grpc/grpc.h>
#include <grpc/slice.h>
#include <grpc/support/useful.h>
@@ -76,22 +77,58 @@ extern "C" {
/* Forward declarations */
typedef struct grpc_mdelem grpc_mdelem;
-/* if changing this, make identical changes in internal_metadata in
- metadata.c */
+/* if changing this, make identical changes in:
+ - interned_metadata, allocated_metadata in metadata.c
+ - grpc_metadata in grpc_types.h */
typedef struct grpc_mdelem_data {
const grpc_slice key;
const grpc_slice value;
/* there is a private part to this in metadata.c */
} grpc_mdelem_data;
+typedef enum {
+ /* memory pointed to by grpc_mdelem::payload is owned by an external system */
+ GRPC_MDELEM_STORAGE_EXTERNAL = 0,
+ /* memory pointed to by grpc_mdelem::payload is interned by the metadata
+ system */
+ GRPC_MDELEM_STORAGE_INTERNED = 1,
+ /* memory pointed to by grpc_mdelem::payload is allocated by the metadata
+ system */
+ GRPC_MDELEM_STORAGE_ALLOCATED = 2,
+ /* memory is in the static metadata table */
+ GRPC_MDELEM_STORAGE_STATIC = 3,
+} grpc_mdelem_data_storage;
+
struct grpc_mdelem {
- grpc_mdelem_data *payload;
+ /* a grpc_mdelem_data* generally, with the two lower bits signalling memory
+ ownership as per grpc_mdelem_data_storage */
+ uintptr_t payload;
};
+#define GRPC_MDELEM_DATA(md) \
+ ((grpc_mdelem_data *)((md).payload & ~(uintptr_t)3))
+#define GRPC_MDELEM_STORAGE(md) \
+ ((grpc_mdelem_data_storage)((md).payload & (uintptr_t)3))
+#define GRPC_MAKE_MDELEM(data, storage) \
+ ((grpc_mdelem){((uintptr_t)(data)) | ((uintptr_t)storage)})
+
/* Unrefs the slices. */
grpc_mdelem grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key,
grpc_slice value);
+/* Cheaply convert a grpc_metadata to a grpc_mdelem; may use the grpc_metadata
+ object as backing storage (so lifetimes should align) */
+grpc_mdelem grpc_mdelem_from_grpc_metadata(grpc_exec_ctx *exec_ctx,
+ grpc_metadata *metadata);
+
+/* Does not unref the slices; if a new non-interned mdelem is needed, allocates
+ one if compatible_external_backing_store is NULL, or uses
+ compatible_external_backing_store if it is non-NULL (in which case it's the
+ users responsibility to ensure that it outlives usage) */
+grpc_mdelem grpc_mdelem_create(
+ grpc_exec_ctx *exec_ctx, grpc_slice key, grpc_slice value,
+ grpc_mdelem_data *compatible_external_backing_store);
+
bool grpc_mdelem_eq(grpc_mdelem a, grpc_mdelem b);
size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem elem);
@@ -119,11 +156,11 @@ grpc_mdelem grpc_mdelem_ref(grpc_mdelem md);
void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem md);
#endif
-#define GRPC_MDKEY(md) ((md).payload->key)
-#define GRPC_MDVALUE(md) ((md).payload->value)
+#define GRPC_MDKEY(md) (GRPC_MDELEM_DATA(md)->key)
+#define GRPC_MDVALUE(md) (GRPC_MDELEM_DATA(md)->value)
-#define GRPC_MDNULL ((grpc_mdelem){NULL})
-#define GRPC_MDISNULL(md) ((md).payload == NULL)
+#define GRPC_MDNULL GRPC_MAKE_MDELEM(NULL, GRPC_MDELEM_STORAGE_EXTERNAL)
+#define GRPC_MDISNULL(md) (GRPC_MDELEM_DATA(md) == NULL)
/* We add 32 bytes of padding as per RFC-7540 section 6.5.2. */
#define GRPC_MDELEM_LENGTH(e) \
diff --git a/src/core/lib/transport/static_metadata.c b/src/core/lib/transport/static_metadata.c
index 42daabfd89..575f442a9b 100644
--- a/src/core/lib/transport/static_metadata.c
+++ b/src/core/lib/transport/static_metadata.c
@@ -459,7 +459,8 @@ grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b) {
uint32_t k = (uint32_t)(a * 98 + b);
uint32_t h = elems_phash(k);
return elem_keys[h] == k
- ? (grpc_mdelem){&grpc_static_mdelem_table[elem_idxs[h]]}
+ ? GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[elem_idxs[h]],
+ GRPC_MDELEM_STORAGE_STATIC)
: GRPC_MDNULL;
}
diff --git a/src/core/lib/transport/static_metadata.h b/src/core/lib/transport/static_metadata.h
index f5ef5d6dd7..3d3911de16 100644
--- a/src/core/lib/transport/static_metadata.h
+++ b/src/core/lib/transport/static_metadata.h
@@ -255,216 +255,252 @@ extern grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];
/* "accept-charset": "" */
#define GRPC_MDELEM_ACCEPT_CHARSET_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[0]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[0], GRPC_MDELEM_STORAGE_STATIC))
/* "accept": "" */
-#define GRPC_MDELEM_ACCEPT_EMPTY ((grpc_mdelem){&grpc_static_mdelem_table[1]})
+#define GRPC_MDELEM_ACCEPT_EMPTY \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[1], GRPC_MDELEM_STORAGE_STATIC))
/* "accept-encoding": "" */
#define GRPC_MDELEM_ACCEPT_ENCODING_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[2]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[2], GRPC_MDELEM_STORAGE_STATIC))
/* "accept-encoding": "gzip, deflate" */
#define GRPC_MDELEM_ACCEPT_ENCODING_GZIP_COMMA_DEFLATE \
- ((grpc_mdelem){&grpc_static_mdelem_table[3]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[3], GRPC_MDELEM_STORAGE_STATIC))
/* "accept-language": "" */
#define GRPC_MDELEM_ACCEPT_LANGUAGE_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[4]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[4], GRPC_MDELEM_STORAGE_STATIC))
/* "accept-ranges": "" */
#define GRPC_MDELEM_ACCEPT_RANGES_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[5]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[5], GRPC_MDELEM_STORAGE_STATIC))
/* "access-control-allow-origin": "" */
#define GRPC_MDELEM_ACCESS_CONTROL_ALLOW_ORIGIN_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[6]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[6], GRPC_MDELEM_STORAGE_STATIC))
/* "age": "" */
-#define GRPC_MDELEM_AGE_EMPTY ((grpc_mdelem){&grpc_static_mdelem_table[7]})
+#define GRPC_MDELEM_AGE_EMPTY \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[7], GRPC_MDELEM_STORAGE_STATIC))
/* "allow": "" */
-#define GRPC_MDELEM_ALLOW_EMPTY ((grpc_mdelem){&grpc_static_mdelem_table[8]})
+#define GRPC_MDELEM_ALLOW_EMPTY \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[8], GRPC_MDELEM_STORAGE_STATIC))
/* ":authority": "" */
#define GRPC_MDELEM_AUTHORITY_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[9]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[9], GRPC_MDELEM_STORAGE_STATIC))
/* "authorization": "" */
#define GRPC_MDELEM_AUTHORIZATION_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[10]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[10], GRPC_MDELEM_STORAGE_STATIC))
/* "cache-control": "" */
#define GRPC_MDELEM_CACHE_CONTROL_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[11]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[11], GRPC_MDELEM_STORAGE_STATIC))
/* "content-disposition": "" */
#define GRPC_MDELEM_CONTENT_DISPOSITION_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[12]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[12], GRPC_MDELEM_STORAGE_STATIC))
/* "content-encoding": "" */
#define GRPC_MDELEM_CONTENT_ENCODING_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[13]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[13], GRPC_MDELEM_STORAGE_STATIC))
/* "content-language": "" */
#define GRPC_MDELEM_CONTENT_LANGUAGE_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[14]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[14], GRPC_MDELEM_STORAGE_STATIC))
/* "content-length": "" */
#define GRPC_MDELEM_CONTENT_LENGTH_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[15]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[15], GRPC_MDELEM_STORAGE_STATIC))
/* "content-location": "" */
#define GRPC_MDELEM_CONTENT_LOCATION_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[16]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[16], GRPC_MDELEM_STORAGE_STATIC))
/* "content-range": "" */
#define GRPC_MDELEM_CONTENT_RANGE_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[17]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[17], GRPC_MDELEM_STORAGE_STATIC))
/* "content-type": "application/grpc" */
#define GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC \
- ((grpc_mdelem){&grpc_static_mdelem_table[18]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[18], GRPC_MDELEM_STORAGE_STATIC))
/* "content-type": "" */
#define GRPC_MDELEM_CONTENT_TYPE_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[19]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[19], GRPC_MDELEM_STORAGE_STATIC))
/* "cookie": "" */
-#define GRPC_MDELEM_COOKIE_EMPTY ((grpc_mdelem){&grpc_static_mdelem_table[20]})
+#define GRPC_MDELEM_COOKIE_EMPTY \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[20], GRPC_MDELEM_STORAGE_STATIC))
/* "date": "" */
-#define GRPC_MDELEM_DATE_EMPTY ((grpc_mdelem){&grpc_static_mdelem_table[21]})
+#define GRPC_MDELEM_DATE_EMPTY \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[21], GRPC_MDELEM_STORAGE_STATIC))
/* "etag": "" */
-#define GRPC_MDELEM_ETAG_EMPTY ((grpc_mdelem){&grpc_static_mdelem_table[22]})
+#define GRPC_MDELEM_ETAG_EMPTY \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[22], GRPC_MDELEM_STORAGE_STATIC))
/* "expect": "" */
-#define GRPC_MDELEM_EXPECT_EMPTY ((grpc_mdelem){&grpc_static_mdelem_table[23]})
+#define GRPC_MDELEM_EXPECT_EMPTY \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[23], GRPC_MDELEM_STORAGE_STATIC))
/* "expires": "" */
-#define GRPC_MDELEM_EXPIRES_EMPTY ((grpc_mdelem){&grpc_static_mdelem_table[24]})
+#define GRPC_MDELEM_EXPIRES_EMPTY \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[24], GRPC_MDELEM_STORAGE_STATIC))
/* "from": "" */
-#define GRPC_MDELEM_FROM_EMPTY ((grpc_mdelem){&grpc_static_mdelem_table[25]})
+#define GRPC_MDELEM_FROM_EMPTY \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[25], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "deflate" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE \
- ((grpc_mdelem){&grpc_static_mdelem_table[26]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[26], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "deflate,gzip" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE_COMMA_GZIP \
- ((grpc_mdelem){&grpc_static_mdelem_table[27]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[27], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "gzip" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_GZIP \
- ((grpc_mdelem){&grpc_static_mdelem_table[28]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[28], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "identity" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY \
- ((grpc_mdelem){&grpc_static_mdelem_table[29]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[29], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "identity,deflate" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE \
- ((grpc_mdelem){&grpc_static_mdelem_table[30]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[30], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "identity,deflate,gzip" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
- ((grpc_mdelem){&grpc_static_mdelem_table[31]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[31], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "identity,gzip" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \
- ((grpc_mdelem){&grpc_static_mdelem_table[32]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[32], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-encoding": "deflate" */
#define GRPC_MDELEM_GRPC_ENCODING_DEFLATE \
- ((grpc_mdelem){&grpc_static_mdelem_table[33]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[33], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-encoding": "gzip" */
#define GRPC_MDELEM_GRPC_ENCODING_GZIP \
- ((grpc_mdelem){&grpc_static_mdelem_table[34]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[34], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-encoding": "identity" */
#define GRPC_MDELEM_GRPC_ENCODING_IDENTITY \
- ((grpc_mdelem){&grpc_static_mdelem_table[35]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[35], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-status": "0" */
-#define GRPC_MDELEM_GRPC_STATUS_0 ((grpc_mdelem){&grpc_static_mdelem_table[36]})
+#define GRPC_MDELEM_GRPC_STATUS_0 \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[36], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-status": "1" */
-#define GRPC_MDELEM_GRPC_STATUS_1 ((grpc_mdelem){&grpc_static_mdelem_table[37]})
+#define GRPC_MDELEM_GRPC_STATUS_1 \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[37], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-status": "2" */
-#define GRPC_MDELEM_GRPC_STATUS_2 ((grpc_mdelem){&grpc_static_mdelem_table[38]})
+#define GRPC_MDELEM_GRPC_STATUS_2 \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[38], GRPC_MDELEM_STORAGE_STATIC))
/* "host": "" */
-#define GRPC_MDELEM_HOST_EMPTY ((grpc_mdelem){&grpc_static_mdelem_table[39]})
+#define GRPC_MDELEM_HOST_EMPTY \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[39], GRPC_MDELEM_STORAGE_STATIC))
/* "if-match": "" */
#define GRPC_MDELEM_IF_MATCH_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[40]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[40], GRPC_MDELEM_STORAGE_STATIC))
/* "if-modified-since": "" */
#define GRPC_MDELEM_IF_MODIFIED_SINCE_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[41]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[41], GRPC_MDELEM_STORAGE_STATIC))
/* "if-none-match": "" */
#define GRPC_MDELEM_IF_NONE_MATCH_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[42]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[42], GRPC_MDELEM_STORAGE_STATIC))
/* "if-range": "" */
#define GRPC_MDELEM_IF_RANGE_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[43]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[43], GRPC_MDELEM_STORAGE_STATIC))
/* "if-unmodified-since": "" */
#define GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[44]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[44], GRPC_MDELEM_STORAGE_STATIC))
/* "last-modified": "" */
#define GRPC_MDELEM_LAST_MODIFIED_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[45]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[45], GRPC_MDELEM_STORAGE_STATIC))
/* "lb-cost-bin": "" */
#define GRPC_MDELEM_LB_COST_BIN_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[46]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[46], GRPC_MDELEM_STORAGE_STATIC))
/* "lb-token": "" */
#define GRPC_MDELEM_LB_TOKEN_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[47]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[47], GRPC_MDELEM_STORAGE_STATIC))
/* "link": "" */
-#define GRPC_MDELEM_LINK_EMPTY ((grpc_mdelem){&grpc_static_mdelem_table[48]})
+#define GRPC_MDELEM_LINK_EMPTY \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[48], GRPC_MDELEM_STORAGE_STATIC))
/* "location": "" */
#define GRPC_MDELEM_LOCATION_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[49]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[49], GRPC_MDELEM_STORAGE_STATIC))
/* "max-forwards": "" */
#define GRPC_MDELEM_MAX_FORWARDS_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[50]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[50], GRPC_MDELEM_STORAGE_STATIC))
/* ":method": "GET" */
-#define GRPC_MDELEM_METHOD_GET ((grpc_mdelem){&grpc_static_mdelem_table[51]})
+#define GRPC_MDELEM_METHOD_GET \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[51], GRPC_MDELEM_STORAGE_STATIC))
/* ":method": "POST" */
-#define GRPC_MDELEM_METHOD_POST ((grpc_mdelem){&grpc_static_mdelem_table[52]})
+#define GRPC_MDELEM_METHOD_POST \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[52], GRPC_MDELEM_STORAGE_STATIC))
/* ":method": "PUT" */
-#define GRPC_MDELEM_METHOD_PUT ((grpc_mdelem){&grpc_static_mdelem_table[53]})
+#define GRPC_MDELEM_METHOD_PUT \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[53], GRPC_MDELEM_STORAGE_STATIC))
/* ":path": "/" */
-#define GRPC_MDELEM_PATH_SLASH ((grpc_mdelem){&grpc_static_mdelem_table[54]})
+#define GRPC_MDELEM_PATH_SLASH \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[54], GRPC_MDELEM_STORAGE_STATIC))
/* ":path": "/index.html" */
#define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML \
- ((grpc_mdelem){&grpc_static_mdelem_table[55]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[55], GRPC_MDELEM_STORAGE_STATIC))
/* "proxy-authenticate": "" */
#define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[56]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[56], GRPC_MDELEM_STORAGE_STATIC))
/* "proxy-authorization": "" */
#define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[57]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[57], GRPC_MDELEM_STORAGE_STATIC))
/* "range": "" */
-#define GRPC_MDELEM_RANGE_EMPTY ((grpc_mdelem){&grpc_static_mdelem_table[58]})
+#define GRPC_MDELEM_RANGE_EMPTY \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[58], GRPC_MDELEM_STORAGE_STATIC))
/* "referer": "" */
-#define GRPC_MDELEM_REFERER_EMPTY ((grpc_mdelem){&grpc_static_mdelem_table[59]})
+#define GRPC_MDELEM_REFERER_EMPTY \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[59], GRPC_MDELEM_STORAGE_STATIC))
/* "refresh": "" */
-#define GRPC_MDELEM_REFRESH_EMPTY ((grpc_mdelem){&grpc_static_mdelem_table[60]})
+#define GRPC_MDELEM_REFRESH_EMPTY \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[60], GRPC_MDELEM_STORAGE_STATIC))
/* "retry-after": "" */
#define GRPC_MDELEM_RETRY_AFTER_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[61]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[61], GRPC_MDELEM_STORAGE_STATIC))
/* ":scheme": "grpc" */
-#define GRPC_MDELEM_SCHEME_GRPC ((grpc_mdelem){&grpc_static_mdelem_table[62]})
+#define GRPC_MDELEM_SCHEME_GRPC \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[62], GRPC_MDELEM_STORAGE_STATIC))
/* ":scheme": "http" */
-#define GRPC_MDELEM_SCHEME_HTTP ((grpc_mdelem){&grpc_static_mdelem_table[63]})
+#define GRPC_MDELEM_SCHEME_HTTP \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[63], GRPC_MDELEM_STORAGE_STATIC))
/* ":scheme": "https" */
-#define GRPC_MDELEM_SCHEME_HTTPS ((grpc_mdelem){&grpc_static_mdelem_table[64]})
+#define GRPC_MDELEM_SCHEME_HTTPS \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[64], GRPC_MDELEM_STORAGE_STATIC))
/* "server": "" */
-#define GRPC_MDELEM_SERVER_EMPTY ((grpc_mdelem){&grpc_static_mdelem_table[65]})
+#define GRPC_MDELEM_SERVER_EMPTY \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[65], GRPC_MDELEM_STORAGE_STATIC))
/* "set-cookie": "" */
#define GRPC_MDELEM_SET_COOKIE_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[66]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[66], GRPC_MDELEM_STORAGE_STATIC))
/* ":status": "200" */
-#define GRPC_MDELEM_STATUS_200 ((grpc_mdelem){&grpc_static_mdelem_table[67]})
+#define GRPC_MDELEM_STATUS_200 \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[67], GRPC_MDELEM_STORAGE_STATIC))
/* ":status": "204" */
-#define GRPC_MDELEM_STATUS_204 ((grpc_mdelem){&grpc_static_mdelem_table[68]})
+#define GRPC_MDELEM_STATUS_204 \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[68], GRPC_MDELEM_STORAGE_STATIC))
/* ":status": "206" */
-#define GRPC_MDELEM_STATUS_206 ((grpc_mdelem){&grpc_static_mdelem_table[69]})
+#define GRPC_MDELEM_STATUS_206 \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[69], GRPC_MDELEM_STORAGE_STATIC))
/* ":status": "304" */
-#define GRPC_MDELEM_STATUS_304 ((grpc_mdelem){&grpc_static_mdelem_table[70]})
+#define GRPC_MDELEM_STATUS_304 \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[70], GRPC_MDELEM_STORAGE_STATIC))
/* ":status": "400" */
-#define GRPC_MDELEM_STATUS_400 ((grpc_mdelem){&grpc_static_mdelem_table[71]})
+#define GRPC_MDELEM_STATUS_400 \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[71], GRPC_MDELEM_STORAGE_STATIC))
/* ":status": "404" */
-#define GRPC_MDELEM_STATUS_404 ((grpc_mdelem){&grpc_static_mdelem_table[72]})
+#define GRPC_MDELEM_STATUS_404 \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[72], GRPC_MDELEM_STORAGE_STATIC))
/* ":status": "500" */
-#define GRPC_MDELEM_STATUS_500 ((grpc_mdelem){&grpc_static_mdelem_table[73]})
+#define GRPC_MDELEM_STATUS_500 \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[73], GRPC_MDELEM_STORAGE_STATIC))
/* "strict-transport-security": "" */
#define GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[74]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[74], GRPC_MDELEM_STORAGE_STATIC))
/* "te": "trailers" */
-#define GRPC_MDELEM_TE_TRAILERS ((grpc_mdelem){&grpc_static_mdelem_table[75]})
+#define GRPC_MDELEM_TE_TRAILERS \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[75], GRPC_MDELEM_STORAGE_STATIC))
/* "transfer-encoding": "" */
#define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[76]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[76], GRPC_MDELEM_STORAGE_STATIC))
/* "user-agent": "" */
#define GRPC_MDELEM_USER_AGENT_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[77]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[77], GRPC_MDELEM_STORAGE_STATIC))
/* "vary": "" */
-#define GRPC_MDELEM_VARY_EMPTY ((grpc_mdelem){&grpc_static_mdelem_table[78]})
+#define GRPC_MDELEM_VARY_EMPTY \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[78], GRPC_MDELEM_STORAGE_STATIC))
/* "via": "" */
-#define GRPC_MDELEM_VIA_EMPTY ((grpc_mdelem){&grpc_static_mdelem_table[79]})
+#define GRPC_MDELEM_VIA_EMPTY \
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[79], GRPC_MDELEM_STORAGE_STATIC))
/* "www-authenticate": "" */
#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY \
- ((grpc_mdelem){&grpc_static_mdelem_table[80]})
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[80], GRPC_MDELEM_STORAGE_STATIC))
grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b);
extern const uint8_t grpc_static_accept_encoding_metadata[8];
-#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) \
- ((grpc_mdelem){&grpc_static_mdelem_table \
- [grpc_static_accept_encoding_metadata[(algs)]]})
+#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) \
+ (GRPC_MAKE_MDELEM( \
+ &grpc_static_mdelem_table[grpc_static_accept_encoding_metadata[(algs)]], \
+ GRPC_MDELEM_STORAGE_STATIC))
#endif /* GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H */
diff --git a/test/core/transport/metadata_test.c b/test/core/transport/metadata_test.c
index d31bc1eedf..ce8f1813ff 100644
--- a/test/core/transport/metadata_test.c
+++ b/test/core/transport/metadata_test.c
@@ -189,8 +189,39 @@ static void test_spin_creating_the_same_thing(bool intern_keys,
&exec_ctx,
maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
maybe_intern(grpc_slice_from_static_string("b"), intern_values)));
+ if (intern_keys && intern_values) {
+ GPR_ASSERT(a.payload == b.payload);
+ GPR_ASSERT(a.payload == c.payload);
+ }
+ grpc_exec_ctx_finish(&exec_ctx);
+ grpc_shutdown();
+}
+
+static void test_identity_laws(bool intern_keys, bool intern_values) {
+ gpr_log(GPR_INFO, "test_identity_laws: intern_keys=%d intern_values=%d",
+ intern_keys, intern_values);
+
+ grpc_init();
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_mdelem a, b, c;
+ a = grpc_mdelem_from_slices(
+ &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+ maybe_intern(grpc_slice_from_static_string("b"), intern_values));
+ b = grpc_mdelem_from_slices(
+ &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+ maybe_intern(grpc_slice_from_static_string("b"), intern_values));
+ c = grpc_mdelem_from_slices(
+ &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+ maybe_intern(grpc_slice_from_static_string("b"), intern_values));
+ GPR_ASSERT(grpc_mdelem_eq(a, a));
+ GPR_ASSERT(grpc_mdelem_eq(b, b));
+ GPR_ASSERT(grpc_mdelem_eq(c, c));
GPR_ASSERT(grpc_mdelem_eq(a, b));
+ GPR_ASSERT(grpc_mdelem_eq(b, c));
GPR_ASSERT(grpc_mdelem_eq(a, c));
+ GPR_ASSERT(grpc_mdelem_eq(b, a));
+ GPR_ASSERT(grpc_mdelem_eq(c, b));
+ GPR_ASSERT(grpc_mdelem_eq(c, a));
if (intern_keys && intern_values) {
GPR_ASSERT(a.payload == b.payload);
GPR_ASSERT(a.payload == c.payload);
@@ -199,6 +230,9 @@ static void test_spin_creating_the_same_thing(bool intern_keys,
GPR_ASSERT(a.payload != c.payload);
GPR_ASSERT(b.payload != c.payload);
}
+ GRPC_MDELEM_UNREF(&exec_ctx, a);
+ GRPC_MDELEM_UNREF(&exec_ctx, b);
+ GRPC_MDELEM_UNREF(&exec_ctx, c);
grpc_exec_ctx_finish(&exec_ctx);
grpc_shutdown();
}
@@ -344,7 +378,8 @@ static void test_copied_static_metadata(bool dup_key, bool dup_value) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
for (size_t i = 0; i < GRPC_STATIC_MDELEM_COUNT; i++) {
- grpc_mdelem p = (grpc_mdelem){&grpc_static_mdelem_table[i]};
+ grpc_mdelem p = GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[i],
+ GRPC_MDELEM_STORAGE_STATIC);
grpc_mdelem q =
grpc_mdelem_from_slices(&exec_ctx, maybe_dup(GRPC_MDKEY(p), dup_key),
maybe_dup(GRPC_MDVALUE(p), dup_value));
@@ -367,6 +402,7 @@ int main(int argc, char **argv) {
for (int v = 0; v <= 1; v++) {
test_create_metadata(k, v);
test_create_many_ephemeral_metadata(k, v);
+ test_identity_laws(k, v);
test_spin_creating_the_same_thing(k, v);
test_mdelem_sizes_in_hpack(k, v);
test_copied_static_metadata(k, v);
diff --git a/tools/codegen/core/gen_static_metadata.py b/tools/codegen/core/gen_static_metadata.py
index e1acdc12c6..b1b7840cfd 100755
--- a/tools/codegen/core/gen_static_metadata.py
+++ b/tools/codegen/core/gen_static_metadata.py
@@ -359,7 +359,7 @@ print >>H, 'extern grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_
print >>H, 'extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];'
for i, elem in enumerate(all_elems):
print >>H, '/* "%s": "%s" */' % elem
- print >>H, '#define %s ((grpc_mdelem){&grpc_static_mdelem_table[%d]})' % (mangle(elem).upper(), i)
+ print >>H, '#define %s (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[%d], GRPC_MDELEM_STORAGE_STATIC))' % (mangle(elem).upper(), i)
print >>H
print >>C, 'uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = {'
print >>C, ' %s' % ','.join('%d' % static_userdata.get(elem, 0) for elem in all_elems)
@@ -440,7 +440,7 @@ print >>C, 'grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b) {'
print >>C, ' if (a == -1 || b == -1) return GRPC_MDNULL;'
print >>C, ' uint32_t k = (uint32_t)(a * %d + b);' % len(all_strs)
print >>C, ' uint32_t h = elems_phash(k);'
-print >>C, ' return elem_keys[h] == k ? (grpc_mdelem){&grpc_static_mdelem_table[elem_idxs[h]]} : GRPC_MDNULL;'
+print >>C, ' return elem_keys[h] == k ? GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[elem_idxs[h]], GRPC_MDELEM_STORAGE_STATIC) : GRPC_MDNULL;'
print >>C, '}'
print >>C
@@ -455,7 +455,7 @@ print >>C, '0,%s' % ','.join('%d' % md_idx(elem) for elem in compression_elems)
print >>C, '};'
print >>C
-print >>H, '#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) ((grpc_mdelem){&grpc_static_mdelem_table[grpc_static_accept_encoding_metadata[(algs)]]})'
+print >>H, '#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[grpc_static_accept_encoding_metadata[(algs)]], GRPC_MDELEM_STORAGE_STATIC))'
print >>H, '#endif /* GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H */'