Merge pull request #2308 from ctiller/metadata-wants-to-be-debugged

Add metadata refcount debug helpers
pull/2346/head
Yang Gao 10 years ago
commit d130bdd176
  1. 2
      src/core/channel/census_filter.c
  2. 18
      src/core/channel/http_client_filter.c
  3. 30
      src/core/channel/http_server_filter.c
  4. 20
      src/core/security/client_auth_filter.c
  5. 20
      src/core/surface/call.c
  6. 34
      src/core/surface/channel.c
  7. 16
      src/core/surface/server.c
  8. 12
      src/core/transport/chttp2/hpack_parser.c
  9. 6
      src/core/transport/chttp2/hpack_table.c
  10. 2
      src/core/transport/chttp2/incoming_metadata.c
  11. 4
      src/core/transport/chttp2/parsing.c
  12. 26
      src/core/transport/chttp2/stream_encoder.c
  13. 2
      src/core/transport/chttp2_transport.c
  14. 107
      src/core/transport/metadata.c
  15. 26
      src/core/transport/metadata.h
  16. 6
      src/core/transport/stream_op.c
  17. 2
      src/core/transport/transport.c
  18. 2
      test/core/transport/chttp2/hpack_parser_test.c
  19. 2
      test/core/transport/chttp2/hpack_table_test.c
  20. 2
      test/core/transport/chttp2/stream_encoder_test.c
  21. 38
      test/core/transport/metadata_test.c

@ -197,7 +197,7 @@ static void destroy_channel_elem(grpc_channel_element* elem) {
channel_data* chand = elem->channel_data; channel_data* chand = elem->channel_data;
GPR_ASSERT(chand != NULL); GPR_ASSERT(chand != NULL);
if (chand->path_str != NULL) { if (chand->path_str != NULL) {
grpc_mdstr_unref(chand->path_str); GRPC_MDSTR_UNREF(chand->path_str);
} }
} }

@ -108,13 +108,13 @@ static void hc_mutate_op(grpc_call_element *elem,
/* Send : prefixed headers, which have to be before any application /* Send : prefixed headers, which have to be before any application
layer headers. */ layer headers. */
grpc_metadata_batch_add_head(&op->data.metadata, &calld->method, grpc_metadata_batch_add_head(&op->data.metadata, &calld->method,
grpc_mdelem_ref(channeld->method)); GRPC_MDELEM_REF(channeld->method));
grpc_metadata_batch_add_head(&op->data.metadata, &calld->scheme, grpc_metadata_batch_add_head(&op->data.metadata, &calld->scheme,
grpc_mdelem_ref(channeld->scheme)); GRPC_MDELEM_REF(channeld->scheme));
grpc_metadata_batch_add_tail(&op->data.metadata, &calld->te_trailers, grpc_metadata_batch_add_tail(&op->data.metadata, &calld->te_trailers,
grpc_mdelem_ref(channeld->te_trailers)); GRPC_MDELEM_REF(channeld->te_trailers));
grpc_metadata_batch_add_tail(&op->data.metadata, &calld->content_type, grpc_metadata_batch_add_tail(&op->data.metadata, &calld->content_type,
grpc_mdelem_ref(channeld->content_type)); GRPC_MDELEM_REF(channeld->content_type));
break; break;
} }
} }
@ -196,11 +196,11 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
/* grab pointers to our data from the channel element */ /* grab pointers to our data from the channel element */
channel_data *channeld = elem->channel_data; channel_data *channeld = elem->channel_data;
grpc_mdelem_unref(channeld->te_trailers); GRPC_MDELEM_UNREF(channeld->te_trailers);
grpc_mdelem_unref(channeld->method); GRPC_MDELEM_UNREF(channeld->method);
grpc_mdelem_unref(channeld->scheme); GRPC_MDELEM_UNREF(channeld->scheme);
grpc_mdelem_unref(channeld->content_type); GRPC_MDELEM_UNREF(channeld->content_type);
grpc_mdelem_unref(channeld->status); GRPC_MDELEM_UNREF(channeld->status);
} }
const grpc_channel_filter grpc_http_client_filter = { const grpc_channel_filter grpc_http_client_filter = {

@ -129,9 +129,9 @@ static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
/* translate host to :authority since :authority may be /* translate host to :authority since :authority may be
omitted */ omitted */
grpc_mdelem *authority = grpc_mdelem_from_metadata_strings( grpc_mdelem *authority = grpc_mdelem_from_metadata_strings(
channeld->mdctx, grpc_mdstr_ref(channeld->authority_key), channeld->mdctx, GRPC_MDSTR_REF(channeld->authority_key),
grpc_mdstr_ref(md->value)); GRPC_MDSTR_REF(md->value));
grpc_mdelem_unref(md); GRPC_MDELEM_UNREF(md);
return authority; return authority;
} else { } else {
return md; return md;
@ -193,7 +193,7 @@ static void hs_mutate_op(grpc_call_element *elem,
if (op->type != GRPC_OP_METADATA) continue; if (op->type != GRPC_OP_METADATA) continue;
calld->sent_status = 1; calld->sent_status = 1;
grpc_metadata_batch_add_head(&op->data.metadata, &calld->status, grpc_metadata_batch_add_head(&op->data.metadata, &calld->status,
grpc_mdelem_ref(channeld->status_ok)); GRPC_MDELEM_REF(channeld->status_ok));
break; break;
} }
} }
@ -264,17 +264,17 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
/* grab pointers to our data from the channel element */ /* grab pointers to our data from the channel element */
channel_data *channeld = elem->channel_data; channel_data *channeld = elem->channel_data;
grpc_mdelem_unref(channeld->te_trailers); GRPC_MDELEM_UNREF(channeld->te_trailers);
grpc_mdelem_unref(channeld->status_ok); GRPC_MDELEM_UNREF(channeld->status_ok);
grpc_mdelem_unref(channeld->status_not_found); GRPC_MDELEM_UNREF(channeld->status_not_found);
grpc_mdelem_unref(channeld->method_post); GRPC_MDELEM_UNREF(channeld->method_post);
grpc_mdelem_unref(channeld->http_scheme); GRPC_MDELEM_UNREF(channeld->http_scheme);
grpc_mdelem_unref(channeld->https_scheme); GRPC_MDELEM_UNREF(channeld->https_scheme);
grpc_mdelem_unref(channeld->grpc_scheme); GRPC_MDELEM_UNREF(channeld->grpc_scheme);
grpc_mdelem_unref(channeld->content_type); GRPC_MDELEM_UNREF(channeld->content_type);
grpc_mdstr_unref(channeld->path_key); GRPC_MDSTR_UNREF(channeld->path_key);
grpc_mdstr_unref(channeld->authority_key); GRPC_MDSTR_UNREF(channeld->authority_key);
grpc_mdstr_unref(channeld->host_key); GRPC_MDSTR_UNREF(channeld->host_key);
} }
const grpc_channel_filter grpc_http_server_filter = { const grpc_channel_filter grpc_http_server_filter = {

@ -219,11 +219,11 @@ static void auth_start_transport_op(grpc_call_element *elem,
/* Pointer comparison is OK for md_elems created from the same context. /* Pointer comparison is OK for md_elems created from the same context.
*/ */
if (md->key == chand->authority_string) { if (md->key == chand->authority_string) {
if (calld->host != NULL) grpc_mdstr_unref(calld->host); if (calld->host != NULL) GRPC_MDSTR_UNREF(calld->host);
calld->host = grpc_mdstr_ref(md->value); calld->host = GRPC_MDSTR_REF(md->value);
} else if (md->key == chand->path_string) { } else if (md->key == chand->path_string) {
if (calld->method != NULL) grpc_mdstr_unref(calld->method); if (calld->method != NULL) GRPC_MDSTR_UNREF(calld->method);
calld->method = grpc_mdstr_ref(md->value); calld->method = GRPC_MDSTR_REF(md->value);
} }
} }
if (calld->host != NULL) { if (calld->host != NULL) {
@ -272,10 +272,10 @@ static void destroy_call_elem(grpc_call_element *elem) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
grpc_credentials_unref(calld->creds); grpc_credentials_unref(calld->creds);
if (calld->host != NULL) { if (calld->host != NULL) {
grpc_mdstr_unref(calld->host); GRPC_MDSTR_UNREF(calld->host);
} }
if (calld->method != NULL) { if (calld->method != NULL) {
grpc_mdstr_unref(calld->method); GRPC_MDSTR_UNREF(calld->method);
} }
} }
@ -314,16 +314,16 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
if (ctx != NULL) if (ctx != NULL)
GRPC_SECURITY_CONNECTOR_UNREF(&ctx->base, "client_auth_filter"); GRPC_SECURITY_CONNECTOR_UNREF(&ctx->base, "client_auth_filter");
if (chand->authority_string != NULL) { if (chand->authority_string != NULL) {
grpc_mdstr_unref(chand->authority_string); GRPC_MDSTR_UNREF(chand->authority_string);
} }
if (chand->error_msg_key != NULL) { if (chand->error_msg_key != NULL) {
grpc_mdstr_unref(chand->error_msg_key); GRPC_MDSTR_UNREF(chand->error_msg_key);
} }
if (chand->status_key != NULL) { if (chand->status_key != NULL) {
grpc_mdstr_unref(chand->status_key); GRPC_MDSTR_UNREF(chand->status_key);
} }
if (chand->path_string != NULL) { if (chand->path_string != NULL) {
grpc_mdstr_unref(chand->path_string); GRPC_MDSTR_UNREF(chand->path_string);
} }
} }

@ -367,18 +367,18 @@ static void destroy_call(void *call, int ignored_success) {
gpr_mu_destroy(&c->mu); gpr_mu_destroy(&c->mu);
for (i = 0; i < STATUS_SOURCE_COUNT; i++) { for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
if (c->status[i].details) { if (c->status[i].details) {
grpc_mdstr_unref(c->status[i].details); GRPC_MDSTR_UNREF(c->status[i].details);
} }
} }
for (i = 0; i < c->owned_metadata_count; i++) { for (i = 0; i < c->owned_metadata_count; i++) {
grpc_mdelem_unref(c->owned_metadata[i]); GRPC_MDELEM_UNREF(c->owned_metadata[i]);
} }
gpr_free(c->owned_metadata); gpr_free(c->owned_metadata);
for (i = 0; i < GPR_ARRAY_SIZE(c->buffered_metadata); i++) { for (i = 0; i < GPR_ARRAY_SIZE(c->buffered_metadata); i++) {
gpr_free(c->buffered_metadata[i].metadata); gpr_free(c->buffered_metadata[i].metadata);
} }
for (i = 0; i < c->send_initial_metadata_count; i++) { for (i = 0; i < c->send_initial_metadata_count; i++) {
grpc_mdelem_unref(c->send_initial_metadata[i].md); GRPC_MDELEM_UNREF(c->send_initial_metadata[i].md);
} }
for (i = 0; i < GRPC_CONTEXT_COUNT; i++) { for (i = 0; i < GRPC_CONTEXT_COUNT; i++) {
if (c->context[i].destroy) { if (c->context[i].destroy) {
@ -435,7 +435,7 @@ static void set_decode_compression_level(grpc_call *call,
static void set_status_details(grpc_call *call, status_source source, static void set_status_details(grpc_call *call, status_source source,
grpc_mdstr *status) { grpc_mdstr *status) {
if (call->status[source].details != NULL) { if (call->status[source].details != NULL) {
grpc_mdstr_unref(call->status[source].details); GRPC_MDSTR_UNREF(call->status[source].details);
} }
call->status[source].details = status; call->status[source].details = status;
} }
@ -614,7 +614,7 @@ static void finish_live_ioreq_op(grpc_call *call, grpc_ioreq_op op,
case GRPC_IOREQ_SEND_STATUS: case GRPC_IOREQ_SEND_STATUS:
if (call->request_data[GRPC_IOREQ_SEND_STATUS].send_status.details != if (call->request_data[GRPC_IOREQ_SEND_STATUS].send_status.details !=
NULL) { NULL) {
grpc_mdstr_unref( GRPC_MDSTR_UNREF(
call->request_data[GRPC_IOREQ_SEND_STATUS].send_status.details); call->request_data[GRPC_IOREQ_SEND_STATUS].send_status.details);
call->request_data[GRPC_IOREQ_SEND_STATUS].send_status.details = call->request_data[GRPC_IOREQ_SEND_STATUS].send_status.details =
NULL; NULL;
@ -943,7 +943,7 @@ static int fill_send_ops(grpc_call *call, grpc_transport_stream_op *op) {
&mdb, &call->details_link, &mdb, &call->details_link,
grpc_mdelem_from_metadata_strings( grpc_mdelem_from_metadata_strings(
call->metadata_context, call->metadata_context,
grpc_mdstr_ref( GRPC_MDSTR_REF(
grpc_channel_get_message_string(call->channel)), grpc_channel_get_message_string(call->channel)),
data.send_status.details)); data.send_status.details));
call->request_data[GRPC_IOREQ_SEND_STATUS].send_status.details = call->request_data[GRPC_IOREQ_SEND_STATUS].send_status.details =
@ -1051,7 +1051,7 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs,
reqs[i].data.send_status.code); reqs[i].data.send_status.code);
if (reqs[i].data.send_status.details) { if (reqs[i].data.send_status.details) {
set_status_details(call, STATUS_FROM_SERVER_STATUS, set_status_details(call, STATUS_FROM_SERVER_STATUS,
grpc_mdstr_ref(reqs[i].data.send_status.details)); GRPC_MDSTR_REF(reqs[i].data.send_status.details));
} }
} }
have_ops |= 1u << op; have_ops |= 1u << op;
@ -1255,7 +1255,7 @@ static void recv_metadata(grpc_call *call, grpc_metadata_batch *md) {
if (key == grpc_channel_get_status_string(call->channel)) { if (key == grpc_channel_get_status_string(call->channel)) {
set_status_code(call, STATUS_FROM_WIRE, decode_status(md)); set_status_code(call, STATUS_FROM_WIRE, decode_status(md));
} else if (key == grpc_channel_get_message_string(call->channel)) { } else if (key == grpc_channel_get_message_string(call->channel)) {
set_status_details(call, STATUS_FROM_WIRE, grpc_mdstr_ref(md->value)); set_status_details(call, STATUS_FROM_WIRE, GRPC_MDSTR_REF(md->value));
} else if (key == } else if (key ==
grpc_channel_get_compresssion_level_string(call->channel)) { grpc_channel_get_compresssion_level_string(call->channel)) {
set_decode_compression_level(call, decode_compression(md)); set_decode_compression_level(call, decode_compression(md));
@ -1291,10 +1291,10 @@ static void recv_metadata(grpc_call *call, grpc_metadata_batch *md) {
grpc_mdctx_lock(mdctx); grpc_mdctx_lock(mdctx);
for (l = md->list.head; l; l = l->next) { for (l = md->list.head; l; l = l->next) {
if (l->md) grpc_mdctx_locked_mdelem_unref(mdctx, l->md); if (l->md) GRPC_MDCTX_LOCKED_MDELEM_UNREF(mdctx, l->md);
} }
for (l = md->garbage.head; l; l = l->next) { for (l = md->garbage.head; l; l = l->next) {
grpc_mdctx_locked_mdelem_unref(mdctx, l->md); GRPC_MDCTX_LOCKED_MDELEM_UNREF(mdctx, l->md);
} }
grpc_mdctx_unlock(mdctx); grpc_mdctx_unlock(mdctx);
} }

@ -104,7 +104,7 @@ grpc_channel *grpc_channel_create_from_filters(
char buf[GPR_LTOA_MIN_BUFSIZE]; char buf[GPR_LTOA_MIN_BUFSIZE];
gpr_ltoa(i, buf); gpr_ltoa(i, buf);
channel->grpc_status_elem[i] = grpc_mdelem_from_metadata_strings( channel->grpc_status_elem[i] = grpc_mdelem_from_metadata_strings(
mdctx, grpc_mdstr_ref(channel->grpc_status_string), mdctx, GRPC_MDSTR_REF(channel->grpc_status_string),
grpc_mdstr_from_string(mdctx, buf)); grpc_mdstr_from_string(mdctx, buf));
} }
channel->path_string = grpc_mdstr_from_string(mdctx, ":path"); channel->path_string = grpc_mdstr_from_string(mdctx, ":path");
@ -157,10 +157,10 @@ grpc_call *grpc_channel_create_call(grpc_channel *channel,
return grpc_channel_create_call_internal( return grpc_channel_create_call_internal(
channel, cq, channel, cq,
grpc_mdelem_from_metadata_strings( grpc_mdelem_from_metadata_strings(
channel->metadata_context, grpc_mdstr_ref(channel->path_string), channel->metadata_context, GRPC_MDSTR_REF(channel->path_string),
grpc_mdstr_from_string(channel->metadata_context, method)), grpc_mdstr_from_string(channel->metadata_context, method)),
grpc_mdelem_from_metadata_strings( grpc_mdelem_from_metadata_strings(
channel->metadata_context, grpc_mdstr_ref(channel->authority_string), channel->metadata_context, GRPC_MDSTR_REF(channel->authority_string),
grpc_mdstr_from_string(channel->metadata_context, host)), grpc_mdstr_from_string(channel->metadata_context, host)),
deadline); deadline);
} }
@ -169,10 +169,10 @@ void *grpc_channel_register_call(grpc_channel *channel, const char *method,
const char *host) { const char *host) {
registered_call *rc = gpr_malloc(sizeof(registered_call)); registered_call *rc = gpr_malloc(sizeof(registered_call));
rc->path = grpc_mdelem_from_metadata_strings( rc->path = grpc_mdelem_from_metadata_strings(
channel->metadata_context, grpc_mdstr_ref(channel->path_string), channel->metadata_context, GRPC_MDSTR_REF(channel->path_string),
grpc_mdstr_from_string(channel->metadata_context, method)); grpc_mdstr_from_string(channel->metadata_context, method));
rc->authority = grpc_mdelem_from_metadata_strings( rc->authority = grpc_mdelem_from_metadata_strings(
channel->metadata_context, grpc_mdstr_ref(channel->authority_string), channel->metadata_context, GRPC_MDSTR_REF(channel->authority_string),
grpc_mdstr_from_string(channel->metadata_context, host)); grpc_mdstr_from_string(channel->metadata_context, host));
gpr_mu_lock(&channel->registered_call_mu); gpr_mu_lock(&channel->registered_call_mu);
rc->next = channel->registered_calls; rc->next = channel->registered_calls;
@ -186,8 +186,8 @@ grpc_call *grpc_channel_create_registered_call(
void *registered_call_handle, gpr_timespec deadline) { void *registered_call_handle, gpr_timespec deadline) {
registered_call *rc = registered_call_handle; registered_call *rc = registered_call_handle;
return grpc_channel_create_call_internal( return grpc_channel_create_call_internal(
channel, completion_queue, grpc_mdelem_ref(rc->path), channel, completion_queue, GRPC_MDELEM_REF(rc->path),
grpc_mdelem_ref(rc->authority), deadline); GRPC_MDELEM_REF(rc->authority), deadline);
} }
#ifdef GRPC_CHANNEL_REF_COUNT_DEBUG #ifdef GRPC_CHANNEL_REF_COUNT_DEBUG
@ -205,18 +205,18 @@ static void destroy_channel(void *p, int ok) {
size_t i; size_t i;
grpc_channel_stack_destroy(CHANNEL_STACK_FROM_CHANNEL(channel)); grpc_channel_stack_destroy(CHANNEL_STACK_FROM_CHANNEL(channel));
for (i = 0; i < NUM_CACHED_STATUS_ELEMS; i++) { for (i = 0; i < NUM_CACHED_STATUS_ELEMS; i++) {
grpc_mdelem_unref(channel->grpc_status_elem[i]); GRPC_MDELEM_UNREF(channel->grpc_status_elem[i]);
} }
grpc_mdstr_unref(channel->grpc_status_string); GRPC_MDSTR_UNREF(channel->grpc_status_string);
grpc_mdstr_unref(channel->grpc_compression_level_string); GRPC_MDSTR_UNREF(channel->grpc_compression_level_string);
grpc_mdstr_unref(channel->grpc_message_string); GRPC_MDSTR_UNREF(channel->grpc_message_string);
grpc_mdstr_unref(channel->path_string); GRPC_MDSTR_UNREF(channel->path_string);
grpc_mdstr_unref(channel->authority_string); GRPC_MDSTR_UNREF(channel->authority_string);
while (channel->registered_calls) { while (channel->registered_calls) {
registered_call *rc = channel->registered_calls; registered_call *rc = channel->registered_calls;
channel->registered_calls = rc->next; channel->registered_calls = rc->next;
grpc_mdelem_unref(rc->path); GRPC_MDELEM_UNREF(rc->path);
grpc_mdelem_unref(rc->authority); GRPC_MDELEM_UNREF(rc->authority);
gpr_free(rc); gpr_free(rc);
} }
grpc_mdctx_unref(channel->metadata_context); grpc_mdctx_unref(channel->metadata_context);
@ -267,12 +267,12 @@ grpc_mdstr *grpc_channel_get_compresssion_level_string(grpc_channel *channel) {
grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_channel *channel, int i) { grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_channel *channel, int i) {
if (i >= 0 && i < NUM_CACHED_STATUS_ELEMS) { if (i >= 0 && i < NUM_CACHED_STATUS_ELEMS) {
return grpc_mdelem_ref(channel->grpc_status_elem[i]); return GRPC_MDELEM_REF(channel->grpc_status_elem[i]);
} else { } else {
char tmp[GPR_LTOA_MIN_BUFSIZE]; char tmp[GPR_LTOA_MIN_BUFSIZE];
gpr_ltoa(i, tmp); gpr_ltoa(i, tmp);
return grpc_mdelem_from_metadata_strings( return grpc_mdelem_from_metadata_strings(
channel->metadata_context, grpc_mdstr_ref(channel->grpc_status_string), channel->metadata_context, GRPC_MDSTR_REF(channel->grpc_status_string),
grpc_mdstr_from_string(channel->metadata_context, tmp)); grpc_mdstr_from_string(channel->metadata_context, tmp));
} }
} }

@ -504,10 +504,10 @@ static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
if (md->key == chand->path_key) { if (md->key == chand->path_key) {
calld->path = grpc_mdstr_ref(md->value); calld->path = GRPC_MDSTR_REF(md->value);
return NULL; return NULL;
} else if (md->key == chand->authority_key) { } else if (md->key == chand->authority_key) {
calld->host = grpc_mdstr_ref(md->value); calld->host = GRPC_MDSTR_REF(md->value);
return NULL; return NULL;
} }
return md; return md;
@ -643,10 +643,10 @@ static void destroy_call_elem(grpc_call_element *elem) {
gpr_mu_unlock(&chand->server->mu_call); gpr_mu_unlock(&chand->server->mu_call);
if (calld->host) { if (calld->host) {
grpc_mdstr_unref(calld->host); GRPC_MDSTR_UNREF(calld->host);
} }
if (calld->path) { if (calld->path) {
grpc_mdstr_unref(calld->path); GRPC_MDSTR_UNREF(calld->path);
} }
server_unref(chand->server); server_unref(chand->server);
@ -676,10 +676,10 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
if (chand->registered_methods) { if (chand->registered_methods) {
for (i = 0; i < chand->registered_method_slots; i++) { for (i = 0; i < chand->registered_method_slots; i++) {
if (chand->registered_methods[i].method) { if (chand->registered_methods[i].method) {
grpc_mdstr_unref(chand->registered_methods[i].method); GRPC_MDSTR_UNREF(chand->registered_methods[i].method);
} }
if (chand->registered_methods[i].host) { if (chand->registered_methods[i].host) {
grpc_mdstr_unref(chand->registered_methods[i].host); GRPC_MDSTR_UNREF(chand->registered_methods[i].host);
} }
} }
gpr_free(chand->registered_methods); gpr_free(chand->registered_methods);
@ -691,8 +691,8 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
chand->next = chand->prev = chand; chand->next = chand->prev = chand;
maybe_finish_shutdown(chand->server); maybe_finish_shutdown(chand->server);
gpr_mu_unlock(&chand->server->mu_global); gpr_mu_unlock(&chand->server->mu_global);
grpc_mdstr_unref(chand->path_key); GRPC_MDSTR_UNREF(chand->path_key);
grpc_mdstr_unref(chand->authority_key); GRPC_MDSTR_UNREF(chand->authority_key);
server_unref(chand->server); server_unref(chand->server);
} }
} }

@ -622,7 +622,7 @@ static const gpr_uint8 inverse_base64[256] = {
static void on_hdr(grpc_chttp2_hpack_parser *p, grpc_mdelem *md, static void on_hdr(grpc_chttp2_hpack_parser *p, grpc_mdelem *md,
int add_to_table) { int add_to_table) {
if (add_to_table) { if (add_to_table) {
grpc_mdelem_ref(md); GRPC_MDELEM_REF(md);
grpc_chttp2_hptbl_add(&p->table, md); grpc_chttp2_hptbl_add(&p->table, md);
} }
p->on_header(p->on_header_user_data, md); p->on_header(p->on_header_user_data, md);
@ -711,7 +711,7 @@ static int parse_stream_dep0(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
static int finish_indexed_field(grpc_chttp2_hpack_parser *p, static int finish_indexed_field(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) { const gpr_uint8 *cur, const gpr_uint8 *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index); grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
grpc_mdelem_ref(md); GRPC_MDELEM_REF(md);
on_hdr(p, md, 0); on_hdr(p, md, 0);
return parse_begin(p, cur, end); return parse_begin(p, cur, end);
} }
@ -740,7 +740,7 @@ static int finish_lithdr_incidx(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) { const gpr_uint8 *cur, const gpr_uint8 *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index); grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx, on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
grpc_mdstr_ref(md->key), GRPC_MDSTR_REF(md->key),
take_string(p, &p->value)), take_string(p, &p->value)),
1); 1);
return parse_begin(p, cur, end); return parse_begin(p, cur, end);
@ -793,7 +793,7 @@ static int finish_lithdr_notidx(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) { const gpr_uint8 *cur, const gpr_uint8 *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index); grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx, on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
grpc_mdstr_ref(md->key), GRPC_MDSTR_REF(md->key),
take_string(p, &p->value)), take_string(p, &p->value)),
0); 0);
return parse_begin(p, cur, end); return parse_begin(p, cur, end);
@ -846,7 +846,7 @@ static int finish_lithdr_nvridx(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) { const gpr_uint8 *cur, const gpr_uint8 *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index); grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx, on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
grpc_mdstr_ref(md->key), GRPC_MDSTR_REF(md->key),
take_string(p, &p->value)), take_string(p, &p->value)),
0); 0);
return parse_begin(p, cur, end); return parse_begin(p, cur, end);
@ -1336,7 +1336,7 @@ static void on_header_not_set(void *user_data, grpc_mdelem *md) {
valuehex); valuehex);
gpr_free(keyhex); gpr_free(keyhex);
gpr_free(valuehex); gpr_free(valuehex);
grpc_mdelem_unref(md); GRPC_MDELEM_UNREF(md);
abort(); abort();
} }

@ -122,10 +122,10 @@ void grpc_chttp2_hptbl_init(grpc_chttp2_hptbl *tbl, grpc_mdctx *mdctx) {
void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl *tbl) { void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl *tbl) {
size_t i; size_t i;
for (i = 0; i < GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) { for (i = 0; i < GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
grpc_mdelem_unref(tbl->static_ents[i]); GRPC_MDELEM_UNREF(tbl->static_ents[i]);
} }
for (i = 0; i < tbl->num_ents; i++) { for (i = 0; i < tbl->num_ents; i++) {
grpc_mdelem_unref( GRPC_MDELEM_UNREF(
tbl->ents[(tbl->first_ent + i) % GRPC_CHTTP2_MAX_TABLE_COUNT]); tbl->ents[(tbl->first_ent + i) % GRPC_CHTTP2_MAX_TABLE_COUNT]);
} }
} }
@ -155,7 +155,7 @@ static void evict1(grpc_chttp2_hptbl *tbl) {
GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD; GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
tbl->first_ent = (tbl->first_ent + 1) % GRPC_CHTTP2_MAX_TABLE_COUNT; tbl->first_ent = (tbl->first_ent + 1) % GRPC_CHTTP2_MAX_TABLE_COUNT;
tbl->num_ents--; tbl->num_ents--;
grpc_mdelem_unref(first_ent); GRPC_MDELEM_UNREF(first_ent);
} }
void grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) { void grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {

@ -49,7 +49,7 @@ void grpc_chttp2_incoming_metadata_buffer_destroy(
grpc_chttp2_incoming_metadata_buffer *buffer) { grpc_chttp2_incoming_metadata_buffer *buffer) {
size_t i; size_t i;
for (i = 0; i < buffer->count; i++) { for (i = 0; i < buffer->count; i++) {
grpc_mdelem_unref(buffer->elems[i].md); GRPC_MDELEM_UNREF(buffer->elems[i].md);
} }
gpr_free(buffer->elems); gpr_free(buffer->elems);
} }

@ -463,7 +463,7 @@ static grpc_chttp2_parse_error skip_parser(
return GRPC_CHTTP2_PARSE_OK; return GRPC_CHTTP2_PARSE_OK;
} }
static void skip_header(void *tp, grpc_mdelem *md) { grpc_mdelem_unref(md); } static void skip_header(void *tp, grpc_mdelem *md) { GRPC_MDELEM_UNREF(md); }
static int init_skip_frame_parser( static int init_skip_frame_parser(
grpc_chttp2_transport_parsing *transport_parsing, int is_header) { grpc_chttp2_transport_parsing *transport_parsing, int is_header) {
@ -600,7 +600,7 @@ static void on_header(void *tp, grpc_mdelem *md) {
grpc_chttp2_incoming_metadata_buffer_set_deadline( grpc_chttp2_incoming_metadata_buffer_set_deadline(
&stream_parsing->incoming_metadata, &stream_parsing->incoming_metadata,
gpr_time_add(gpr_now(), *cached_timeout)); gpr_time_add(gpr_now(), *cached_timeout));
grpc_mdelem_unref(md); GRPC_MDELEM_UNREF(md);
} else { } else {
grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->incoming_metadata, grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->incoming_metadata,
md); md);

@ -247,19 +247,19 @@ static grpc_mdelem *add_elem(grpc_chttp2_hpack_compressor *c,
} else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == elem->key) { } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == elem->key) {
c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index; c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
} else if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == NULL) { } else if (c->entries_keys[HASH_FRAGMENT_2(key_hash)] == NULL) {
c->entries_keys[HASH_FRAGMENT_2(key_hash)] = grpc_mdstr_ref(elem->key); c->entries_keys[HASH_FRAGMENT_2(key_hash)] = GRPC_MDSTR_REF(elem->key);
c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index; c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
} else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == NULL) { } else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)] == NULL) {
c->entries_keys[HASH_FRAGMENT_3(key_hash)] = grpc_mdstr_ref(elem->key); c->entries_keys[HASH_FRAGMENT_3(key_hash)] = GRPC_MDSTR_REF(elem->key);
c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index; c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
} else if (c->indices_keys[HASH_FRAGMENT_2(key_hash)] < } else if (c->indices_keys[HASH_FRAGMENT_2(key_hash)] <
c->indices_keys[HASH_FRAGMENT_3(key_hash)]) { c->indices_keys[HASH_FRAGMENT_3(key_hash)]) {
grpc_mdstr_unref(c->entries_keys[HASH_FRAGMENT_2(key_hash)]); GRPC_MDSTR_UNREF(c->entries_keys[HASH_FRAGMENT_2(key_hash)]);
c->entries_keys[HASH_FRAGMENT_2(key_hash)] = grpc_mdstr_ref(elem->key); c->entries_keys[HASH_FRAGMENT_2(key_hash)] = GRPC_MDSTR_REF(elem->key);
c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index; c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
} else { } else {
grpc_mdstr_unref(c->entries_keys[HASH_FRAGMENT_3(key_hash)]); GRPC_MDSTR_UNREF(c->entries_keys[HASH_FRAGMENT_3(key_hash)]);
c->entries_keys[HASH_FRAGMENT_3(key_hash)] = grpc_mdstr_ref(elem->key); c->entries_keys[HASH_FRAGMENT_3(key_hash)] = GRPC_MDSTR_REF(elem->key);
c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index; c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
} }
@ -439,10 +439,10 @@ static void deadline_enc(grpc_chttp2_hpack_compressor *c, gpr_timespec deadline,
grpc_mdelem *mdelem; grpc_mdelem *mdelem;
grpc_chttp2_encode_timeout(gpr_time_sub(deadline, gpr_now()), timeout_str); grpc_chttp2_encode_timeout(gpr_time_sub(deadline, gpr_now()), timeout_str);
mdelem = grpc_mdelem_from_metadata_strings( mdelem = grpc_mdelem_from_metadata_strings(
c->mdctx, grpc_mdstr_ref(c->timeout_key_str), c->mdctx, GRPC_MDSTR_REF(c->timeout_key_str),
grpc_mdstr_from_string(c->mdctx, timeout_str)); grpc_mdstr_from_string(c->mdctx, timeout_str));
mdelem = hpack_enc(c, mdelem, st); mdelem = hpack_enc(c, mdelem, st);
if (mdelem) grpc_mdelem_unref(mdelem); if (mdelem) GRPC_MDELEM_UNREF(mdelem);
} }
gpr_slice grpc_chttp2_data_frame_create_empty_close(gpr_uint32 id) { gpr_slice grpc_chttp2_data_frame_create_empty_close(gpr_uint32 id) {
@ -461,10 +461,10 @@ void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c,
void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c) { void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c) {
int i; int i;
for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_VALUES; i++) { for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_VALUES; i++) {
if (c->entries_keys[i]) grpc_mdstr_unref(c->entries_keys[i]); if (c->entries_keys[i]) GRPC_MDSTR_UNREF(c->entries_keys[i]);
if (c->entries_elems[i]) grpc_mdelem_unref(c->entries_elems[i]); if (c->entries_elems[i]) GRPC_MDELEM_UNREF(c->entries_elems[i]);
} }
grpc_mdstr_unref(c->timeout_key_str); GRPC_MDSTR_UNREF(c->timeout_key_str);
} }
gpr_uint32 grpc_chttp2_preencode(grpc_stream_op *inops, size_t *inops_count, gpr_uint32 grpc_chttp2_preencode(grpc_stream_op *inops, size_t *inops_count,
@ -620,10 +620,10 @@ void grpc_chttp2_encode(grpc_stream_op *ops, size_t ops_count, int eof,
op = &ops[unref_op]; op = &ops[unref_op];
if (op->type != GRPC_OP_METADATA) continue; if (op->type != GRPC_OP_METADATA) continue;
for (l = op->data.metadata.list.head; l; l = l->next) { for (l = op->data.metadata.list.head; l; l = l->next) {
if (l->md) grpc_mdctx_locked_mdelem_unref(mdctx, l->md); if (l->md) GRPC_MDCTX_LOCKED_MDELEM_UNREF(mdctx, l->md);
} }
for (l = op->data.metadata.garbage.head; l; l = l->next) { for (l = op->data.metadata.garbage.head; l; l = l->next) {
grpc_mdctx_locked_mdelem_unref(mdctx, l->md); GRPC_MDCTX_LOCKED_MDELEM_UNREF(mdctx, l->md);
} }
} }
grpc_mdctx_unlock(mdctx); grpc_mdctx_unlock(mdctx);

@ -139,7 +139,7 @@ static void destruct_transport(grpc_chttp2_transport *t) {
grpc_chttp2_hpack_parser_destroy(&t->parsing.hpack_parser); grpc_chttp2_hpack_parser_destroy(&t->parsing.hpack_parser);
grpc_chttp2_goaway_parser_destroy(&t->parsing.goaway_parser); grpc_chttp2_goaway_parser_destroy(&t->parsing.goaway_parser);
grpc_mdstr_unref(t->parsing.str_grpc_timeout); GRPC_MDSTR_UNREF(t->parsing.str_grpc_timeout);
for (i = 0; i < STREAM_LIST_COUNT; i++) { for (i = 0; i < STREAM_LIST_COUNT; i++) {
GPR_ASSERT(t->lists[i].head == NULL); GPR_ASSERT(t->lists[i].head == NULL);

@ -48,6 +48,20 @@
#define INITIAL_STRTAB_CAPACITY 4 #define INITIAL_STRTAB_CAPACITY 4
#define INITIAL_MDTAB_CAPACITY 4 #define INITIAL_MDTAB_CAPACITY 4
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
#define DEBUG_ARGS , const char *file, int line
#define FWD_DEBUG_ARGS , file, line
#define INTERNAL_STRING_REF(s) internal_string_ref((s), __FILE__, __LINE__)
#define INTERNAL_STRING_UNREF(s) internal_string_unref((s), __FILE__, __LINE__)
#define REF_MD_LOCKED(s) ref_md_locked((s), __FILE__, __LINE__)
#else
#define DEBUG_ARGS
#define FWD_DEBUG_ARGS
#define INTERNAL_STRING_REF(s) internal_string_ref((s))
#define INTERNAL_STRING_UNREF(s) internal_string_unref((s))
#define REF_MD_LOCKED(s) ref_md_locked((s))
#endif
typedef struct internal_string { typedef struct internal_string {
/* must be byte compatible with grpc_mdstr */ /* must be byte compatible with grpc_mdstr */
gpr_slice slice; gpr_slice slice;
@ -96,8 +110,8 @@ struct grpc_mdctx {
size_t mdtab_capacity; size_t mdtab_capacity;
}; };
static void internal_string_ref(internal_string *s); static void internal_string_ref(internal_string *s DEBUG_ARGS);
static void internal_string_unref(internal_string *s); static void internal_string_unref(internal_string *s DEBUG_ARGS);
static void discard_metadata(grpc_mdctx *ctx); static void discard_metadata(grpc_mdctx *ctx);
static void gc_mdtab(grpc_mdctx *ctx); static void gc_mdtab(grpc_mdctx *ctx);
static void metadata_context_destroy_locked(grpc_mdctx *ctx); static void metadata_context_destroy_locked(grpc_mdctx *ctx);
@ -132,7 +146,15 @@ static void unlock(grpc_mdctx *ctx) {
gpr_mu_unlock(&ctx->mu); gpr_mu_unlock(&ctx->mu);
} }
static void ref_md_locked(internal_metadata *md) { static void ref_md_locked(internal_metadata *md DEBUG_ARGS) {
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"ELM REF:%p:%d->%d: '%s' = '%s'", md,
gpr_atm_no_barrier_load(&md->refcnt),
gpr_atm_no_barrier_load(&md->refcnt) + 1,
grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
#endif
if (0 == gpr_atm_no_barrier_fetch_add(&md->refcnt, 1)) { if (0 == gpr_atm_no_barrier_fetch_add(&md->refcnt, 1)) {
md->context->mdtab_free--; md->context->mdtab_free--;
} }
@ -173,8 +195,8 @@ static void discard_metadata(grpc_mdctx *ctx) {
while (cur) { while (cur) {
GPR_ASSERT(gpr_atm_acq_load(&cur->refcnt) == 0); GPR_ASSERT(gpr_atm_acq_load(&cur->refcnt) == 0);
next = cur->bucket_next; next = cur->bucket_next;
internal_string_unref(cur->key); INTERNAL_STRING_UNREF(cur->key);
internal_string_unref(cur->value); INTERNAL_STRING_UNREF(cur->value);
if (cur->user_data) { if (cur->user_data) {
cur->destroy_user_data(cur->user_data); cur->destroy_user_data(cur->user_data);
} }
@ -248,9 +270,19 @@ static void internal_destroy_string(internal_string *is) {
gpr_free(is); gpr_free(is);
} }
static void internal_string_ref(internal_string *s) { ++s->refs; } static void internal_string_ref(internal_string *s DEBUG_ARGS) {
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "STR REF:%p:%d->%d: '%s'", s,
s->refs, s->refs + 1, grpc_mdstr_as_c_string((grpc_mdstr *)s));
#endif
++s->refs;
}
static void internal_string_unref(internal_string *s) { static void internal_string_unref(internal_string *s DEBUG_ARGS) {
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "STR UNREF:%p:%d->%d: '%s'", s,
s->refs, s->refs - 1, grpc_mdstr_as_c_string((grpc_mdstr *)s));
#endif
GPR_ASSERT(s->refs > 0); GPR_ASSERT(s->refs > 0);
if (0 == --s->refs) { if (0 == --s->refs) {
internal_destroy_string(s); internal_destroy_string(s);
@ -262,7 +294,7 @@ static void slice_ref(void *p) {
(internal_string *)((char *)p - offsetof(internal_string, refcount)); (internal_string *)((char *)p - offsetof(internal_string, refcount));
grpc_mdctx *ctx = is->context; grpc_mdctx *ctx = is->context;
lock(ctx); lock(ctx);
internal_string_ref(is); INTERNAL_STRING_REF(is);
unlock(ctx); unlock(ctx);
} }
@ -271,7 +303,7 @@ static void slice_unref(void *p) {
(internal_string *)((char *)p - offsetof(internal_string, refcount)); (internal_string *)((char *)p - offsetof(internal_string, refcount));
grpc_mdctx *ctx = is->context; grpc_mdctx *ctx = is->context;
lock(ctx); lock(ctx);
internal_string_unref(is); INTERNAL_STRING_UNREF(is);
unlock(ctx); unlock(ctx);
} }
@ -297,7 +329,7 @@ grpc_mdstr *grpc_mdstr_from_buffer(grpc_mdctx *ctx, const gpr_uint8 *buf,
for (s = ctx->strtab[hash % ctx->strtab_capacity]; s; s = s->bucket_next) { for (s = ctx->strtab[hash % ctx->strtab_capacity]; s; s = s->bucket_next) {
if (s->hash == hash && GPR_SLICE_LENGTH(s->slice) == length && if (s->hash == hash && GPR_SLICE_LENGTH(s->slice) == length &&
0 == memcmp(buf, GPR_SLICE_START_PTR(s->slice), length)) { 0 == memcmp(buf, GPR_SLICE_START_PTR(s->slice), length)) {
internal_string_ref(s); INTERNAL_STRING_REF(s);
unlock(ctx); unlock(ctx);
return (grpc_mdstr *)s; return (grpc_mdstr *)s;
} }
@ -353,8 +385,8 @@ static void gc_mdtab(grpc_mdctx *ctx) {
for (md = ctx->mdtab[i]; md; md = next) { for (md = ctx->mdtab[i]; md; md = next) {
next = md->bucket_next; next = md->bucket_next;
if (gpr_atm_acq_load(&md->refcnt) == 0) { if (gpr_atm_acq_load(&md->refcnt) == 0) {
internal_string_unref(md->key); INTERNAL_STRING_UNREF(md->key);
internal_string_unref(md->value); INTERNAL_STRING_UNREF(md->value);
if (md->user_data) { if (md->user_data) {
md->destroy_user_data(md->user_data); md->destroy_user_data(md->user_data);
} }
@ -418,9 +450,9 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdctx *ctx,
/* search for an existing pair */ /* search for an existing pair */
for (md = ctx->mdtab[hash % ctx->mdtab_capacity]; md; md = md->bucket_next) { for (md = ctx->mdtab[hash % ctx->mdtab_capacity]; md; md = md->bucket_next) {
if (md->key == key && md->value == value) { if (md->key == key && md->value == value) {
ref_md_locked(md); REF_MD_LOCKED(md);
internal_string_unref(key); INTERNAL_STRING_UNREF(key);
internal_string_unref(value); INTERNAL_STRING_UNREF(value);
unlock(ctx); unlock(ctx);
return (grpc_mdelem *)md; return (grpc_mdelem *)md;
} }
@ -435,6 +467,12 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdctx *ctx,
md->user_data = NULL; md->user_data = NULL;
md->destroy_user_data = NULL; md->destroy_user_data = NULL;
md->bucket_next = ctx->mdtab[hash % ctx->mdtab_capacity]; md->bucket_next = ctx->mdtab[hash % ctx->mdtab_capacity];
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
gpr_log(GPR_DEBUG, "ELM NEW:%p:%d: '%s' = '%s'", md,
gpr_atm_no_barrier_load(&md->refcnt),
grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
#endif
ctx->mdtab[hash % ctx->mdtab_capacity] = md; ctx->mdtab[hash % ctx->mdtab_capacity] = md;
ctx->mdtab_count++; ctx->mdtab_count++;
@ -469,8 +507,16 @@ grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_mdctx *ctx,
grpc_mdstr_from_buffer(ctx, value, value_length)); grpc_mdstr_from_buffer(ctx, value, value_length));
} }
grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd) { grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd DEBUG_ARGS) {
internal_metadata *md = (internal_metadata *)gmd; internal_metadata *md = (internal_metadata *)gmd;
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"ELM REF:%p:%d->%d: '%s' = '%s'", md,
gpr_atm_no_barrier_load(&md->refcnt),
gpr_atm_no_barrier_load(&md->refcnt) + 1,
grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
#endif
/* we can assume the ref count is >= 1 as the application is calling /* we can assume the ref count is >= 1 as the application is calling
this function - meaning that no adjustment to mdtab_free is necessary, this function - meaning that no adjustment to mdtab_free is necessary,
simplifying the logic here to be just an atomic increment */ simplifying the logic here to be just an atomic increment */
@ -480,10 +526,18 @@ grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd) {
return gmd; return gmd;
} }
void grpc_mdelem_unref(grpc_mdelem *gmd) { void grpc_mdelem_unref(grpc_mdelem *gmd DEBUG_ARGS) {
internal_metadata *md = (internal_metadata *)gmd; internal_metadata *md = (internal_metadata *)gmd;
grpc_mdctx *ctx = md->context; grpc_mdctx *ctx = md->context;
lock(ctx); lock(ctx);
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"ELM UNREF:%p:%d->%d: '%s' = '%s'", md,
gpr_atm_no_barrier_load(&md->refcnt),
gpr_atm_no_barrier_load(&md->refcnt) - 1,
grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
#endif
assert(gpr_atm_no_barrier_load(&md->refcnt) >= 1); assert(gpr_atm_no_barrier_load(&md->refcnt) >= 1);
if (1 == gpr_atm_full_fetch_add(&md->refcnt, -1)) { if (1 == gpr_atm_full_fetch_add(&md->refcnt, -1)) {
ctx->mdtab_free++; ctx->mdtab_free++;
@ -495,20 +549,20 @@ const char *grpc_mdstr_as_c_string(grpc_mdstr *s) {
return (const char *)GPR_SLICE_START_PTR(s->slice); return (const char *)GPR_SLICE_START_PTR(s->slice);
} }
grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs) { grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs DEBUG_ARGS) {
internal_string *s = (internal_string *)gs; internal_string *s = (internal_string *)gs;
grpc_mdctx *ctx = s->context; grpc_mdctx *ctx = s->context;
lock(ctx); lock(ctx);
internal_string_ref(s); internal_string_ref(s FWD_DEBUG_ARGS);
unlock(ctx); unlock(ctx);
return gs; return gs;
} }
void grpc_mdstr_unref(grpc_mdstr *gs) { void grpc_mdstr_unref(grpc_mdstr *gs DEBUG_ARGS) {
internal_string *s = (internal_string *)gs; internal_string *s = (internal_string *)gs;
grpc_mdctx *ctx = s->context; grpc_mdctx *ctx = s->context;
lock(ctx); lock(ctx);
internal_string_unref(s); internal_string_unref(s FWD_DEBUG_ARGS);
unlock(ctx); unlock(ctx);
} }
@ -558,10 +612,19 @@ gpr_slice grpc_mdstr_as_base64_encoded_and_huffman_compressed(grpc_mdstr *gs) {
void grpc_mdctx_lock(grpc_mdctx *ctx) { lock(ctx); } void grpc_mdctx_lock(grpc_mdctx *ctx) { lock(ctx); }
void grpc_mdctx_locked_mdelem_unref(grpc_mdctx *ctx, grpc_mdelem *gmd) { void grpc_mdctx_locked_mdelem_unref(grpc_mdctx *ctx,
grpc_mdelem *gmd DEBUG_ARGS) {
internal_metadata *md = (internal_metadata *)gmd; internal_metadata *md = (internal_metadata *)gmd;
grpc_mdctx *elem_ctx = md->context; grpc_mdctx *elem_ctx = md->context;
GPR_ASSERT(ctx == elem_ctx); GPR_ASSERT(ctx == elem_ctx);
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"ELM UNREF:%p:%d->%d: '%s' = '%s'", md,
gpr_atm_no_barrier_load(&md->refcnt),
gpr_atm_no_barrier_load(&md->refcnt) - 1,
grpc_mdstr_as_c_string((grpc_mdstr *)md->key),
grpc_mdstr_as_c_string((grpc_mdstr *)md->value));
#endif
assert(gpr_atm_no_barrier_load(&md->refcnt) >= 1); assert(gpr_atm_no_barrier_load(&md->refcnt) >= 1);
if (1 == gpr_atm_full_fetch_add(&md->refcnt, -1)) { if (1 == gpr_atm_full_fetch_add(&md->refcnt, -1)) {
ctx->mdtab_free++; ctx->mdtab_free++;

@ -127,11 +127,25 @@ void grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *),
void *user_data); void *user_data);
/* Reference counting */ /* Reference counting */
#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_MDELEM_REF(s) grpc_mdelem_ref((s), __FILE__, __LINE__)
#define GRPC_MDELEM_UNREF(s) grpc_mdelem_unref((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);
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);
#else
#define GRPC_MDSTR_REF(s) grpc_mdstr_ref((s))
#define GRPC_MDSTR_UNREF(s) grpc_mdstr_unref((s))
#define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s))
#define GRPC_MDELEM_UNREF(s) grpc_mdelem_unref((s))
grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *s); grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *s);
void grpc_mdstr_unref(grpc_mdstr *s); void grpc_mdstr_unref(grpc_mdstr *s);
grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *md); grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *md);
void grpc_mdelem_unref(grpc_mdelem *md); void grpc_mdelem_unref(grpc_mdelem *md);
#endif
/* Recover a char* from a grpc_mdstr. The returned string is null terminated. /* Recover a char* from a grpc_mdstr. The returned string is null terminated.
Does not promise that the returned string has no embedded nulls however. */ Does not promise that the returned string has no embedded nulls however. */
@ -147,8 +161,18 @@ int grpc_mdstr_is_bin_suffixed(grpc_mdstr *s);
/* Lock the metadata context: it's only safe to call _locked_ functions against /* Lock the metadata context: it's only safe to call _locked_ functions against
this context from the calling thread until grpc_mdctx_unlock is called */ this context from the calling thread until grpc_mdctx_unlock is called */
void grpc_mdctx_lock(grpc_mdctx *ctx); void grpc_mdctx_lock(grpc_mdctx *ctx);
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
#define GRPC_MDCTX_LOCKED_MDELEM_UNREF(ctx, elem) \
grpc_mdctx_locked_mdelem_unref((ctx), (elem), __FILE__, __LINE__)
/* Unref a metadata element */
void grpc_mdctx_locked_mdelem_unref(grpc_mdctx *ctx, grpc_mdelem *elem,
const char *file, int line);
#else
#define GRPC_MDCTX_LOCKED_MDELEM_UNREF(ctx, elem) \
grpc_mdctx_locked_mdelem_unref((ctx), (elem))
/* Unref a metadata element */ /* Unref a metadata element */
void grpc_mdctx_locked_mdelem_unref(grpc_mdctx *ctx, grpc_mdelem *elem); void grpc_mdctx_locked_mdelem_unref(grpc_mdctx *ctx, grpc_mdelem *elem);
#endif
/* Unlock the metadata context */ /* Unlock the metadata context */
void grpc_mdctx_unlock(grpc_mdctx *ctx); void grpc_mdctx_unlock(grpc_mdctx *ctx);

@ -211,10 +211,10 @@ void grpc_metadata_batch_init(grpc_metadata_batch *batch) {
void grpc_metadata_batch_destroy(grpc_metadata_batch *batch) { void grpc_metadata_batch_destroy(grpc_metadata_batch *batch) {
grpc_linked_mdelem *l; grpc_linked_mdelem *l;
for (l = batch->list.head; l; l = l->next) { for (l = batch->list.head; l; l = l->next) {
grpc_mdelem_unref(l->md); GRPC_MDELEM_UNREF(l->md);
} }
for (l = batch->garbage.head; l; l = l->next) { for (l = batch->garbage.head; l; l = l->next) {
grpc_mdelem_unref(l->md); GRPC_MDELEM_UNREF(l->md);
} }
} }
@ -315,7 +315,7 @@ void grpc_metadata_batch_filter(grpc_metadata_batch *batch,
assert_valid_list(&batch->list); assert_valid_list(&batch->list);
link_head(&batch->garbage, l); link_head(&batch->garbage, l);
} else if (filt != orig) { } else if (filt != orig) {
grpc_mdelem_unref(orig); GRPC_MDELEM_UNREF(orig);
l->md = filt; l->md = filt;
} }
} }

@ -85,6 +85,6 @@ void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
op->cancel_with_status = status; op->cancel_with_status = status;
} }
if (message) { if (message) {
grpc_mdstr_unref(message); GRPC_MDSTR_UNREF(message);
} }
} }

@ -53,7 +53,7 @@ static void onhdr(void *ud, grpc_mdelem *md) {
GPR_ASSERT(evalue); GPR_ASSERT(evalue);
GPR_ASSERT(gpr_slice_str_cmp(md->key->slice, ekey) == 0); GPR_ASSERT(gpr_slice_str_cmp(md->key->slice, ekey) == 0);
GPR_ASSERT(gpr_slice_str_cmp(md->value->slice, evalue) == 0); GPR_ASSERT(gpr_slice_str_cmp(md->value->slice, evalue) == 0);
grpc_mdelem_unref(md); GRPC_MDELEM_UNREF(md);
} }
static void test_vector(grpc_chttp2_hpack_parser *parser, static void test_vector(grpc_chttp2_hpack_parser *parser,

@ -167,7 +167,7 @@ static grpc_chttp2_hptbl_find_result find_simple(grpc_chttp2_hptbl *tbl,
const char *value) { const char *value) {
grpc_mdelem *md = grpc_mdelem_from_strings(tbl->mdctx, key, value); grpc_mdelem *md = grpc_mdelem_from_strings(tbl->mdctx, key, value);
grpc_chttp2_hptbl_find_result r = grpc_chttp2_hptbl_find(tbl, md); grpc_chttp2_hptbl_find_result r = grpc_chttp2_hptbl_find(tbl, md);
grpc_mdelem_unref(md); GRPC_MDELEM_UNREF(md);
return r; return r;
} }

@ -262,7 +262,7 @@ static void chk_hdr(void *p, grpc_mdelem *el) {
GPR_ASSERT(0 == gpr_slice_str_cmp(el->key->slice, st->key)); GPR_ASSERT(0 == gpr_slice_str_cmp(el->key->slice, st->key));
GPR_ASSERT(0 == gpr_slice_str_cmp(el->value->slice, st->value)); GPR_ASSERT(0 == gpr_slice_str_cmp(el->value->slice, st->value));
st->got_hdr = 1; st->got_hdr = 1;
grpc_mdelem_unref(el); GRPC_MDELEM_UNREF(el);
} }
static void test_decode_random_headers_inner(int max_len) { static void test_decode_random_headers_inner(int max_len) {

@ -70,10 +70,10 @@ static void test_create_string(void) {
GPR_ASSERT(s3 != s1); GPR_ASSERT(s3 != s1);
GPR_ASSERT(gpr_slice_str_cmp(s1->slice, "hello") == 0); GPR_ASSERT(gpr_slice_str_cmp(s1->slice, "hello") == 0);
GPR_ASSERT(gpr_slice_str_cmp(s3->slice, "very much not hello") == 0); GPR_ASSERT(gpr_slice_str_cmp(s3->slice, "very much not hello") == 0);
grpc_mdstr_unref(s1); GRPC_MDSTR_UNREF(s1);
grpc_mdstr_unref(s2); GRPC_MDSTR_UNREF(s2);
grpc_mdctx_unref(ctx); grpc_mdctx_unref(ctx);
grpc_mdstr_unref(s3); GRPC_MDSTR_UNREF(s3);
} }
static void test_create_metadata(void) { static void test_create_metadata(void) {
@ -93,9 +93,9 @@ static void test_create_metadata(void) {
GPR_ASSERT(gpr_slice_str_cmp(m1->key->slice, "a") == 0); GPR_ASSERT(gpr_slice_str_cmp(m1->key->slice, "a") == 0);
GPR_ASSERT(gpr_slice_str_cmp(m1->value->slice, "b") == 0); GPR_ASSERT(gpr_slice_str_cmp(m1->value->slice, "b") == 0);
GPR_ASSERT(gpr_slice_str_cmp(m3->value->slice, "c") == 0); GPR_ASSERT(gpr_slice_str_cmp(m3->value->slice, "c") == 0);
grpc_mdelem_unref(m1); GRPC_MDELEM_UNREF(m1);
grpc_mdelem_unref(m2); GRPC_MDELEM_UNREF(m2);
grpc_mdelem_unref(m3); GRPC_MDELEM_UNREF(m3);
grpc_mdctx_unref(ctx); grpc_mdctx_unref(ctx);
} }
@ -112,7 +112,7 @@ static void test_create_many_ephemeral_metadata(void) {
/* add, and immediately delete a bunch of different elements */ /* add, and immediately delete a bunch of different elements */
for (i = 0; i < MANY; i++) { for (i = 0; i < MANY; i++) {
gpr_ltoa(i, buffer); gpr_ltoa(i, buffer);
grpc_mdelem_unref(grpc_mdelem_from_strings(ctx, "a", buffer)); GRPC_MDELEM_UNREF(grpc_mdelem_from_strings(ctx, "a", buffer));
} }
/* capacity should not grow */ /* capacity should not grow */
GPR_ASSERT(mdtab_capacity_before == GPR_ASSERT(mdtab_capacity_before ==
@ -140,11 +140,11 @@ static void test_create_many_persistant_metadata(void) {
gpr_ltoa(i, buffer); gpr_ltoa(i, buffer);
md = grpc_mdelem_from_strings(ctx, "a", buffer); md = grpc_mdelem_from_strings(ctx, "a", buffer);
GPR_ASSERT(md == created[i]); GPR_ASSERT(md == created[i]);
grpc_mdelem_unref(md); GRPC_MDELEM_UNREF(md);
} }
/* cleanup phase */ /* cleanup phase */
for (i = 0; i < MANY; i++) { for (i = 0; i < MANY; i++) {
grpc_mdelem_unref(created[i]); GRPC_MDELEM_UNREF(created[i]);
} }
grpc_mdctx_unref(ctx); grpc_mdctx_unref(ctx);
@ -160,15 +160,15 @@ static void test_spin_creating_the_same_thing(void) {
GPR_ASSERT(grpc_mdctx_get_mdtab_count_test_only(ctx) == 0); GPR_ASSERT(grpc_mdctx_get_mdtab_count_test_only(ctx) == 0);
GPR_ASSERT(grpc_mdctx_get_mdtab_free_test_only(ctx) == 0); GPR_ASSERT(grpc_mdctx_get_mdtab_free_test_only(ctx) == 0);
grpc_mdelem_unref(grpc_mdelem_from_strings(ctx, "a", "b")); GRPC_MDELEM_UNREF(grpc_mdelem_from_strings(ctx, "a", "b"));
GPR_ASSERT(grpc_mdctx_get_mdtab_count_test_only(ctx) == 1); GPR_ASSERT(grpc_mdctx_get_mdtab_count_test_only(ctx) == 1);
GPR_ASSERT(grpc_mdctx_get_mdtab_free_test_only(ctx) == 1); GPR_ASSERT(grpc_mdctx_get_mdtab_free_test_only(ctx) == 1);
grpc_mdelem_unref(grpc_mdelem_from_strings(ctx, "a", "b")); GRPC_MDELEM_UNREF(grpc_mdelem_from_strings(ctx, "a", "b"));
GPR_ASSERT(grpc_mdctx_get_mdtab_count_test_only(ctx) == 1); GPR_ASSERT(grpc_mdctx_get_mdtab_count_test_only(ctx) == 1);
GPR_ASSERT(grpc_mdctx_get_mdtab_free_test_only(ctx) == 1); GPR_ASSERT(grpc_mdctx_get_mdtab_free_test_only(ctx) == 1);
grpc_mdelem_unref(grpc_mdelem_from_strings(ctx, "a", "b")); GRPC_MDELEM_UNREF(grpc_mdelem_from_strings(ctx, "a", "b"));
GPR_ASSERT(grpc_mdctx_get_mdtab_count_test_only(ctx) == 1); GPR_ASSERT(grpc_mdctx_get_mdtab_count_test_only(ctx) == 1);
GPR_ASSERT(grpc_mdctx_get_mdtab_free_test_only(ctx) == 1); GPR_ASSERT(grpc_mdctx_get_mdtab_free_test_only(ctx) == 1);
@ -196,8 +196,8 @@ static void test_things_stick_around(void) {
} }
for (i = 0; i < nstrs; i++) { for (i = 0; i < nstrs; i++) {
grpc_mdstr_ref(strs[i]); GRPC_MDSTR_REF(strs[i]);
grpc_mdstr_unref(strs[i]); GRPC_MDSTR_UNREF(strs[i]);
} }
for (i = 0; i < nstrs; i++) { for (i = 0; i < nstrs; i++) {
@ -209,12 +209,12 @@ static void test_things_stick_around(void) {
} }
for (i = 0; i < nstrs; i++) { for (i = 0; i < nstrs; i++) {
grpc_mdstr_unref(strs[shuf[i]]); GRPC_MDSTR_UNREF(strs[shuf[i]]);
for (j = i + 1; j < nstrs; j++) { for (j = i + 1; j < nstrs; j++) {
gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%dx", shuf[j]); gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%dx", shuf[j]);
test = grpc_mdstr_from_string(ctx, buffer); test = grpc_mdstr_from_string(ctx, buffer);
GPR_ASSERT(test == strs[shuf[j]]); GPR_ASSERT(test == strs[shuf[j]]);
grpc_mdstr_unref(test); GRPC_MDSTR_UNREF(test);
gpr_free(buffer); gpr_free(buffer);
} }
} }
@ -237,14 +237,14 @@ static void test_slices_work(void) {
str = grpc_mdstr_from_string( str = grpc_mdstr_from_string(
ctx, "123456789012345678901234567890123456789012345678901234567890"); ctx, "123456789012345678901234567890123456789012345678901234567890");
slice = gpr_slice_ref(str->slice); slice = gpr_slice_ref(str->slice);
grpc_mdstr_unref(str); GRPC_MDSTR_UNREF(str);
gpr_slice_unref(slice); gpr_slice_unref(slice);
str = grpc_mdstr_from_string( str = grpc_mdstr_from_string(
ctx, "123456789012345678901234567890123456789012345678901234567890"); ctx, "123456789012345678901234567890123456789012345678901234567890");
slice = gpr_slice_ref(str->slice); slice = gpr_slice_ref(str->slice);
gpr_slice_unref(slice); gpr_slice_unref(slice);
grpc_mdstr_unref(str); GRPC_MDSTR_UNREF(str);
grpc_mdctx_unref(ctx); grpc_mdctx_unref(ctx);
} }
@ -264,7 +264,7 @@ static void test_base64_and_huffman_works(void) {
GPR_ASSERT(0 == gpr_slice_cmp(slice1, slice2)); GPR_ASSERT(0 == gpr_slice_cmp(slice1, slice2));
gpr_slice_unref(slice2); gpr_slice_unref(slice2);
grpc_mdstr_unref(str); GRPC_MDSTR_UNREF(str);
grpc_mdctx_unref(ctx); grpc_mdctx_unref(ctx);
} }

Loading…
Cancel
Save