void grpc_chttp2_stream_map_add(grpc_chttp2_stream_map *map, uint32_t key, void *value) { size_t count = map->count; size_t capacity = map->capacity; uint32_t *keys = map->keys; void **values = map->values; GPR_ASSERT(count == 0 || keys[count - 1] < key); GPR_ASSERT(value); GPR_ASSERT(grpc_chttp2_stream_map_find(map, key) == NULL); if (count == capacity) { if (map->free > capacity / 4) { count = compact(keys, values, count); map->free = 0; } else { /* resize when less than 25% of the table is free, because compaction won't help much */ map->capacity = capacity = 3 * capacity / 2; map->keys = keys = gpr_realloc(keys, capacity * sizeof(uint32_t)); map->values = values = gpr_realloc(values, capacity * sizeof(void *)); } } keys[count] = key; values[count] = value; map->count = count + 1; }
grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream( grpc_chttp2_transport_parsing *transport_parsing, gpr_uint32 id) { grpc_chttp2_transport *t = TRANSPORT_FROM_PARSING(transport_parsing); grpc_chttp2_stream *s = grpc_chttp2_stream_map_find(&t->parsing_stream_map, id); return s ? &s->parsing : NULL; }
/* test lookup on an empty map */ static void test_empty_find(void) { grpc_chttp2_stream_map map; LOG_TEST("test_empty_find"); grpc_chttp2_stream_map_init(&map, 8); GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, 39128)); grpc_chttp2_stream_map_destroy(&map); }
/* test it's safe to delete twice */ static void test_double_deletion(void) { grpc_chttp2_stream_map map; LOG_TEST("test_double_deletion"); grpc_chttp2_stream_map_init(&map, 8); GPR_ASSERT(0 == grpc_chttp2_stream_map_size(&map)); grpc_chttp2_stream_map_add(&map, 1, (void *)1); GPR_ASSERT((void *)1 == grpc_chttp2_stream_map_find(&map, 1)); GPR_ASSERT(1 == grpc_chttp2_stream_map_size(&map)); GPR_ASSERT((void *)1 == grpc_chttp2_stream_map_delete(&map, 1)); GPR_ASSERT(0 == grpc_chttp2_stream_map_size(&map)); GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, 1)); GPR_ASSERT(NULL == grpc_chttp2_stream_map_delete(&map, 1)); GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, 1)); GPR_ASSERT(NULL == grpc_chttp2_stream_map_delete(&map, 1)); GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, 1)); GPR_ASSERT(NULL == grpc_chttp2_stream_map_delete(&map, 1)); GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, 1)); grpc_chttp2_stream_map_destroy(&map); }
/* test add & lookup */ static void test_basic_add_find(uint32_t n) { grpc_chttp2_stream_map map; uint32_t i; size_t got; LOG_TEST("test_basic_add_find"); gpr_log(GPR_INFO, "n = %d", n); grpc_chttp2_stream_map_init(&map, 8); GPR_ASSERT(0 == grpc_chttp2_stream_map_size(&map)); for (i = 1; i <= n; i++) { grpc_chttp2_stream_map_add(&map, i, (void *)(uintptr_t)i); } GPR_ASSERT(n == grpc_chttp2_stream_map_size(&map)); GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, 0)); GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(&map, n + 1)); for (i = 1; i <= n; i++) { got = (uintptr_t)grpc_chttp2_stream_map_find(&map, i); GPR_ASSERT(i == got); } grpc_chttp2_stream_map_destroy(&map); }
static void check_delete_evens(grpc_chttp2_stream_map *map, uint32_t n) { uint32_t for_each_check = 1; uint32_t i; size_t got; GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(map, 0)); GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(map, n + 1)); for (i = 1; i <= n; i++) { if (i & 1) { got = (uintptr_t)grpc_chttp2_stream_map_find(map, i); GPR_ASSERT(i == got); } else { GPR_ASSERT(NULL == grpc_chttp2_stream_map_find(map, i)); } } grpc_chttp2_stream_map_for_each(map, verify_for_each, &for_each_check); if (n & 1) { GPR_ASSERT(for_each_check == n + 2); } else { GPR_ASSERT(for_each_check == n + 1); } }
void *grpc_chttp2_stream_map_delete(grpc_chttp2_stream_map *map, uint32_t key) { void **pvalue = find(map, key); void *out = NULL; if (pvalue != NULL) { out = *pvalue; *pvalue = NULL; map->free += (out != NULL); /* recognize complete emptyness and ensure we can skip * defragmentation later */ if (map->free == map->count) { map->free = map->count = 0; } GPR_ASSERT(grpc_chttp2_stream_map_find(map, key) == NULL); } return out; }
static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; int i; gpr_mu_lock(&t->mu); GPR_ASSERT(s->global.published_state == GRPC_STREAM_CLOSED || s->global.id == 0); GPR_ASSERT(!s->global.in_stream_map); if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) { close_transport_locked(exec_ctx, t); } if (!t->parsing_active && s->global.id) { GPR_ASSERT(grpc_chttp2_stream_map_find(&t->parsing_stream_map, s->global.id) == NULL); } grpc_chttp2_list_remove_incoming_window_updated(&t->global, &s->global); grpc_chttp2_list_remove_writable_stream(&t->global, &s->global); gpr_mu_unlock(&t->mu); for (i = 0; i < STREAM_LIST_COUNT; i++) { if (s->included[i]) { gpr_log(GPR_ERROR, "%s stream %d still included in list %d", t->global.is_client ? "client" : "server", s->global.id, i); abort(); } } GPR_ASSERT(s->global.outgoing_sopb == NULL); GPR_ASSERT(s->global.publish_sopb == NULL); grpc_sopb_destroy(&s->writing.sopb); grpc_sopb_destroy(&s->global.incoming_sopb); grpc_chttp2_data_parser_destroy(&s->parsing.data_parser); grpc_chttp2_incoming_metadata_buffer_destroy(&s->parsing.incoming_metadata); grpc_chttp2_incoming_metadata_buffer_destroy(&s->global.incoming_metadata); grpc_chttp2_incoming_metadata_live_op_buffer_end( &s->global.outstanding_metadata); UNREF_TRANSPORT(exec_ctx, t, "stream"); }
static void destroy_stream(grpc_transport *gt, grpc_stream *gs) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; int i; gpr_mu_lock(&t->mu); GPR_ASSERT(s->global.published_state == GRPC_STREAM_CLOSED || s->global.id == 0); GPR_ASSERT(!s->global.in_stream_map); grpc_chttp2_unregister_stream(t, s); if (!t->parsing_active && s->global.id) { GPR_ASSERT(grpc_chttp2_stream_map_find(&t->parsing_stream_map, s->global.id) == NULL); } grpc_chttp2_list_remove_incoming_window_updated(&t->global, &s->global); grpc_chttp2_list_remove_writable_window_update_stream(&t->global, &s->global); gpr_mu_unlock(&t->mu); for (i = 0; i < STREAM_LIST_COUNT; i++) { GPR_ASSERT(!s->included[i]); } GPR_ASSERT(s->global.outgoing_sopb == NULL); GPR_ASSERT(s->global.publish_sopb == NULL); grpc_sopb_destroy(&s->writing.sopb); grpc_sopb_destroy(&s->global.incoming_sopb); grpc_chttp2_data_parser_destroy(&s->parsing.data_parser); grpc_chttp2_incoming_metadata_buffer_destroy(&s->parsing.incoming_metadata); grpc_chttp2_incoming_metadata_buffer_destroy(&s->global.incoming_metadata); grpc_chttp2_incoming_metadata_live_op_buffer_end( &s->global.outstanding_metadata); UNREF_TRANSPORT(t, "stream"); }