grpc_mdstr *grpc_mdstr_from_buffer(grpc_mdctx *ctx, const gpr_uint8 *buf, size_t length) { gpr_uint32 hash = gpr_murmur_hash3(buf, length, ctx->hash_seed); internal_string *s; lock(ctx); /* search for an existing string */ 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); unlock(ctx); return (grpc_mdstr *)s; } } /* not found: create a new string */ if (length + 1 < GPR_SLICE_INLINED_SIZE) { /* string data goes directly into the slice */ s = gpr_malloc(sizeof(internal_string)); s->refs = 1; s->slice.refcount = NULL; memcpy(s->slice.data.inlined.bytes, buf, length); s->slice.data.inlined.bytes[length] = 0; s->slice.data.inlined.length = length; } else { /* string data goes after the internal_string header, and we +1 for null terminator */ s = gpr_malloc(sizeof(internal_string) + length + 1); s->refs = 1; s->refcount.ref = slice_ref; s->refcount.unref = slice_unref; s->slice.refcount = &s->refcount; s->slice.data.refcounted.bytes = (gpr_uint8 *)(s + 1); s->slice.data.refcounted.length = length; memcpy(s->slice.data.refcounted.bytes, buf, length); /* add a null terminator for cheap c string conversion when desired */ s->slice.data.refcounted.bytes[length] = 0; } s->has_base64_and_huffman_encoded = 0; s->hash = hash; s->context = ctx; s->bucket_next = ctx->strtab[hash % ctx->strtab_capacity]; ctx->strtab[hash % ctx->strtab_capacity] = s; ctx->strtab_count++; if (ctx->strtab_count > ctx->strtab_capacity * 2) { grow_strtab(ctx); } unlock(ctx); return (grpc_mdstr *)s; }
void grpc_mdctx_global_init(void) { size_t i, j; if (!g_forced_hash_seed) { g_hash_seed = (uint32_t)gpr_now(GPR_CLOCK_REALTIME).tv_nsec; } g_static_strtab_maxprobe = 0; g_static_mdtab_maxprobe = 0; /* build static tables */ memset(g_static_mdtab, 0, sizeof(g_static_mdtab)); memset(g_static_strtab, 0, sizeof(g_static_strtab)); for (i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) { grpc_mdstr *elem = &grpc_static_mdstr_table[i]; const char *str = grpc_static_metadata_strings[i]; uint32_t hash = gpr_murmur_hash3(str, strlen(str), g_hash_seed); *(gpr_slice *)&elem->slice = gpr_slice_from_static_string(str); *(uint32_t *)&elem->hash = hash; for (j = 0;; j++) { size_t idx = (hash + j) % GPR_ARRAY_SIZE(g_static_strtab); if (g_static_strtab[idx] == NULL) { g_static_strtab[idx] = &grpc_static_mdstr_table[i]; break; } } if (j > g_static_strtab_maxprobe) { g_static_strtab_maxprobe = j; } } for (i = 0; i < GRPC_STATIC_MDELEM_COUNT; i++) { grpc_mdelem *elem = &grpc_static_mdelem_table[i]; grpc_mdstr *key = &grpc_static_mdstr_table[grpc_static_metadata_elem_indices[2 * i + 0]]; grpc_mdstr *value = &grpc_static_mdstr_table[grpc_static_metadata_elem_indices[2 * i + 1]]; uint32_t hash = GRPC_MDSTR_KV_HASH(key->hash, value->hash); *(grpc_mdstr **)&elem->key = key; *(grpc_mdstr **)&elem->value = value; for (j = 0;; j++) { size_t idx = (hash + j) % GPR_ARRAY_SIZE(g_static_mdtab); if (g_static_mdtab[idx] == NULL) { g_static_mdtab[idx] = elem; break; } } if (j > g_static_mdtab_maxprobe) { g_static_mdtab_maxprobe = j; } } /* initialize shards */ for (i = 0; i < STRTAB_SHARD_COUNT; i++) { strtab_shard *shard = &g_strtab_shard[i]; gpr_mu_init(&shard->mu); shard->count = 0; shard->capacity = INITIAL_STRTAB_CAPACITY; shard->strs = gpr_malloc(sizeof(*shard->strs) * shard->capacity); memset(shard->strs, 0, sizeof(*shard->strs) * shard->capacity); } for (i = 0; i < MDTAB_SHARD_COUNT; i++) { mdtab_shard *shard = &g_mdtab_shard[i]; gpr_mu_init(&shard->mu); shard->count = 0; gpr_atm_no_barrier_store(&shard->free_estimate, 0); shard->capacity = INITIAL_MDTAB_CAPACITY; shard->elems = gpr_malloc(sizeof(*shard->elems) * shard->capacity); memset(shard->elems, 0, sizeof(*shard->elems) * shard->capacity); } }
static uint64_t hash64(const void *k) { size_t len = strlen(k); uint64_t higher = gpr_murmur_hash3((const char *)k, len / 2, 0); return higher << 32 | gpr_murmur_hash3((const char *)(k) + len / 2, len - len / 2, 0); }
static void assert_passthrough(grpc_slice value, grpc_compression_algorithm algorithm, grpc_slice_split_mode uncompressed_split_mode, grpc_slice_split_mode compressed_split_mode, compressability compress_result_check) { grpc_slice_buffer input; grpc_slice_buffer compressed_raw; grpc_slice_buffer compressed; grpc_slice_buffer output; grpc_slice final; int was_compressed; char *algorithm_name; GPR_ASSERT(grpc_compression_algorithm_name(algorithm, &algorithm_name) != 0); gpr_log( GPR_INFO, "assert_passthrough: value_length=%" PRIuPTR " value_hash=0x%08x " "algorithm='%s' uncompressed_split='%s' compressed_split='%s'", GRPC_SLICE_LENGTH(value), gpr_murmur_hash3(GRPC_SLICE_START_PTR(value), GRPC_SLICE_LENGTH(value), 0), algorithm_name, grpc_slice_split_mode_name(uncompressed_split_mode), grpc_slice_split_mode_name(compressed_split_mode)); grpc_slice_buffer_init(&input); grpc_slice_buffer_init(&compressed_raw); grpc_slice_buffer_init(&compressed); grpc_slice_buffer_init(&output); grpc_split_slices_to_buffer(uncompressed_split_mode, &value, 1, &input); { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; was_compressed = grpc_msg_compress(&exec_ctx, algorithm, &input, &compressed_raw); grpc_exec_ctx_finish(&exec_ctx); } GPR_ASSERT(input.count > 0); switch (compress_result_check) { case SHOULD_NOT_COMPRESS: GPR_ASSERT(was_compressed == 0); break; case SHOULD_COMPRESS: GPR_ASSERT(was_compressed == 1); break; case MAYBE_COMPRESSES: /* no check */ break; } grpc_split_slice_buffer(compressed_split_mode, &compressed_raw, &compressed); { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GPR_ASSERT(grpc_msg_decompress( &exec_ctx, was_compressed ? algorithm : GRPC_COMPRESS_NONE, &compressed, &output)); grpc_exec_ctx_finish(&exec_ctx); } final = grpc_slice_merge(output.slices, output.count);
/* TODO(hongyu): replace it with cityhash64 */ static gpr_uint64 simple_hash(const void* k) { size_t len = strlen(k); gpr_uint64 higher = gpr_murmur_hash3((const char*)k, len / 2, 0); return higher << 32 | gpr_murmur_hash3((const char*)k + len / 2, len - len / 2, 0); }
uint32_t grpc_slice_default_hash_impl(grpc_slice s) { return gpr_murmur_hash3(GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s), g_hash_seed); }