|
|
|
@ -48,6 +48,20 @@ |
|
|
|
|
#define INITIAL_STRTAB_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 { |
|
|
|
|
/* must be byte compatible with grpc_mdstr */ |
|
|
|
|
gpr_slice slice; |
|
|
|
@ -96,8 +110,8 @@ struct grpc_mdctx { |
|
|
|
|
size_t mdtab_capacity; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static void internal_string_ref(internal_string *s); |
|
|
|
|
static void internal_string_unref(internal_string *s); |
|
|
|
|
static void internal_string_ref(internal_string *s DEBUG_ARGS); |
|
|
|
|
static void internal_string_unref(internal_string *s DEBUG_ARGS); |
|
|
|
|
static void discard_metadata(grpc_mdctx *ctx); |
|
|
|
|
static void gc_mdtab(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); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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)) { |
|
|
|
|
md->context->mdtab_free--; |
|
|
|
|
} |
|
|
|
@ -173,8 +195,8 @@ static void discard_metadata(grpc_mdctx *ctx) { |
|
|
|
|
while (cur) { |
|
|
|
|
GPR_ASSERT(gpr_atm_acq_load(&cur->refcnt) == 0); |
|
|
|
|
next = cur->bucket_next; |
|
|
|
|
internal_string_unref(cur->key); |
|
|
|
|
internal_string_unref(cur->value); |
|
|
|
|
INTERNAL_STRING_UNREF(cur->key); |
|
|
|
|
INTERNAL_STRING_UNREF(cur->value); |
|
|
|
|
if (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); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
if (0 == --s->refs) { |
|
|
|
|
internal_destroy_string(s); |
|
|
|
@ -262,7 +294,7 @@ static void slice_ref(void *p) { |
|
|
|
|
(internal_string *)((char *)p - offsetof(internal_string, refcount)); |
|
|
|
|
grpc_mdctx *ctx = is->context; |
|
|
|
|
lock(ctx); |
|
|
|
|
internal_string_ref(is); |
|
|
|
|
INTERNAL_STRING_REF(is); |
|
|
|
|
unlock(ctx); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -271,7 +303,7 @@ static void slice_unref(void *p) { |
|
|
|
|
(internal_string *)((char *)p - offsetof(internal_string, refcount)); |
|
|
|
|
grpc_mdctx *ctx = is->context; |
|
|
|
|
lock(ctx); |
|
|
|
|
internal_string_unref(is); |
|
|
|
|
INTERNAL_STRING_UNREF(is); |
|
|
|
|
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) { |
|
|
|
|
if (s->hash == hash && GPR_SLICE_LENGTH(s->slice) == length && |
|
|
|
|
0 == memcmp(buf, GPR_SLICE_START_PTR(s->slice), length)) { |
|
|
|
|
internal_string_ref(s); |
|
|
|
|
INTERNAL_STRING_REF(s); |
|
|
|
|
unlock(ctx); |
|
|
|
|
return (grpc_mdstr *)s; |
|
|
|
|
} |
|
|
|
@ -353,8 +385,8 @@ static void gc_mdtab(grpc_mdctx *ctx) { |
|
|
|
|
for (md = ctx->mdtab[i]; md; md = next) { |
|
|
|
|
next = md->bucket_next; |
|
|
|
|
if (gpr_atm_acq_load(&md->refcnt) == 0) { |
|
|
|
|
internal_string_unref(md->key); |
|
|
|
|
internal_string_unref(md->value); |
|
|
|
|
INTERNAL_STRING_UNREF(md->key); |
|
|
|
|
INTERNAL_STRING_UNREF(md->value); |
|
|
|
|
if (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 */ |
|
|
|
|
for (md = ctx->mdtab[hash % ctx->mdtab_capacity]; md; md = md->bucket_next) { |
|
|
|
|
if (md->key == key && md->value == value) { |
|
|
|
|
ref_md_locked(md); |
|
|
|
|
internal_string_unref(key); |
|
|
|
|
internal_string_unref(value); |
|
|
|
|
REF_MD_LOCKED(md); |
|
|
|
|
INTERNAL_STRING_UNREF(key); |
|
|
|
|
INTERNAL_STRING_UNREF(value); |
|
|
|
|
unlock(ctx); |
|
|
|
|
return (grpc_mdelem *)md; |
|
|
|
|
} |
|
|
|
@ -435,6 +467,12 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdctx *ctx, |
|
|
|
|
md->user_data = NULL; |
|
|
|
|
md->destroy_user_data = NULL; |
|
|
|
|
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_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_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd) { |
|
|
|
|
grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd DEBUG_ARGS) { |
|
|
|
|
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
|
|
|
|
|
this function - meaning that no adjustment to mdtab_free is necessary, |
|
|
|
|
simplifying the logic here to be just an atomic increment */ |
|
|
|
@ -480,10 +526,18 @@ grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *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; |
|
|
|
|
grpc_mdctx *ctx = md->context; |
|
|
|
|
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); |
|
|
|
|
if (1 == gpr_atm_full_fetch_add(&md->refcnt, -1)) { |
|
|
|
|
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); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs) { |
|
|
|
|
grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs DEBUG_ARGS) { |
|
|
|
|
internal_string *s = (internal_string *)gs; |
|
|
|
|
grpc_mdctx *ctx = s->context; |
|
|
|
|
lock(ctx); |
|
|
|
|
internal_string_ref(s); |
|
|
|
|
internal_string_ref(s FWD_DEBUG_ARGS); |
|
|
|
|
unlock(ctx); |
|
|
|
|
return gs; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_mdstr_unref(grpc_mdstr *gs) { |
|
|
|
|
void grpc_mdstr_unref(grpc_mdstr *gs DEBUG_ARGS) { |
|
|
|
|
internal_string *s = (internal_string *)gs; |
|
|
|
|
grpc_mdctx *ctx = s->context; |
|
|
|
|
lock(ctx); |
|
|
|
|
internal_string_unref(s); |
|
|
|
|
internal_string_unref(s FWD_DEBUG_ARGS); |
|
|
|
|
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_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; |
|
|
|
|
grpc_mdctx *elem_ctx = md->context; |
|
|
|
|
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); |
|
|
|
|
if (1 == gpr_atm_full_fetch_add(&md->refcnt, -1)) { |
|
|
|
|
ctx->mdtab_free++; |
|
|
|
|