Share stream_group weight among streams marked as top

This commit is contained in:
Tatsuhiro Tsujikawa 2014-03-31 22:51:33 +09:00
parent f011bda377
commit b85e2ab7f7
4 changed files with 417 additions and 27 deletions

View File

@ -686,7 +686,7 @@ int nghttp2_session_add_frame(nghttp2_session *session,
stream = nghttp2_session_get_stream(session, data_frame->hd.stream_id); stream = nghttp2_session_get_stream(session, data_frame->hd.stream_id);
if(stream) { if(stream) {
item->weight = stream->stream_group->weight; item->weight = nghttp2_stream_group_shared_wait(stream->stream_group);
rv = nghttp2_stream_attach_data(stream, item, &session->ob_pq); rv = nghttp2_stream_attach_data(stream, item, &session->ob_pq);
} }
@ -2087,7 +2087,8 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
assert(stream); assert(stream);
next_item = nghttp2_session_get_next_ob_item(session); next_item = nghttp2_session_get_next_ob_item(session);
outbound_item_cycle_weight(aob->item, stream->stream_group->weight); outbound_item_cycle_weight
(aob->item, nghttp2_stream_group_shared_wait(stream->stream_group));
/* If priority of this stream is higher or equal to other stream /* If priority of this stream is higher or equal to other stream
waiting at the top of the queue, we continue to send this waiting at the top of the queue, we continue to send this

View File

@ -27,6 +27,8 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include "nghttp2_helper.h"
void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id, void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
uint8_t flags, uint8_t flags,
nghttp2_stream_state initial_state, nghttp2_stream_state initial_state,
@ -58,6 +60,7 @@ void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
stream->stream_group = NULL; stream->stream_group = NULL;
stream->dpri = NGHTTP2_STREAM_DPRI_NO_DATA; stream->dpri = NGHTTP2_STREAM_DPRI_NO_DATA;
stream->num_substreams = 1; stream->num_substreams = 1;
stream->num_subtop = 0;
} }
void nghttp2_stream_free(nghttp2_stream *stream) void nghttp2_stream_free(nghttp2_stream *stream)
@ -101,6 +104,23 @@ static nghttp2_stream* stream_update_dep_length(nghttp2_stream *stream,
return stream; return stream;
} }
static nghttp2_stream* stream_update_dep_both_length(nghttp2_stream *stream,
ssize_t delta_stream,
ssize_t delta_top)
{
stream->num_substreams += delta_stream;
stream->num_subtop += delta_top;
stream = stream_first_sib(stream);
if(stream->dep_prev) {
return stream_update_dep_both_length(stream->dep_prev, delta_stream,
delta_top);
}
return stream;
}
static void stream_update_dep_set_rest_stream_group static void stream_update_dep_set_rest_stream_group
(nghttp2_stream *stream, nghttp2_stream_group *stream_group) (nghttp2_stream *stream, nghttp2_stream_group *stream_group)
{ {
@ -129,6 +149,8 @@ static void stream_update_dep_set_rest(nghttp2_stream *stream)
return; return;
} }
stream->num_subtop = 0;
if(stream->dpri == NGHTTP2_STREAM_DPRI_TOP) { if(stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
stream->dpri = NGHTTP2_STREAM_DPRI_REST; stream->dpri = NGHTTP2_STREAM_DPRI_REST;
@ -145,22 +167,33 @@ static void stream_update_dep_set_rest(nghttp2_stream *stream)
* Performs dfs starting |stream|, search stream which can become * Performs dfs starting |stream|, search stream which can become
* NGHTTP2_STREAM_DPRI_TOP and queues its data. * NGHTTP2_STREAM_DPRI_TOP and queues its data.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns the number of stream marked as
* negative error codes: * NGHTTP2_STREAM_DPRI_TOP (including already marked as such) if it
* succeeds, or one of the following negative error codes:
* *
* NGHTTP2_ERR_NOMEM * NGHTTP2_ERR_NOMEM
* Out of memory. * Out of memory.
*/ */
static int stream_update_dep_set_top(nghttp2_stream *stream, nghttp2_pq *pq) static ssize_t stream_update_dep_set_top(nghttp2_stream *stream,
nghttp2_pq *pq)
{ {
int rv; ssize_t rv;
ssize_t num_top;
if(stream == NULL) { if(stream == NULL) {
return 0; return 0;
} }
if(stream->dpri == NGHTTP2_STREAM_DPRI_TOP) { if(stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
return stream_update_dep_set_top(stream->sib_next, pq); rv = stream_update_dep_set_top(stream->sib_next, pq);
if(rv < 0) {
return rv;
}
stream->num_subtop = 1;
return stream->num_subtop + rv;
} }
if(stream->dpri == NGHTTP2_STREAM_DPRI_REST) { if(stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
@ -180,25 +213,44 @@ static int stream_update_dep_set_top(nghttp2_stream *stream, nghttp2_pq *pq)
stream->dpri = NGHTTP2_STREAM_DPRI_TOP; stream->dpri = NGHTTP2_STREAM_DPRI_TOP;
return stream_update_dep_set_top(stream->sib_next, pq); rv = stream_update_dep_set_top(stream->sib_next, pq);
if(rv < 0) {
return rv;
}
stream->num_subtop = 1;
return stream->num_subtop + rv;
} }
assert(stream->dpri == NGHTTP2_STREAM_DPRI_NO_DATA); assert(stream->dpri == NGHTTP2_STREAM_DPRI_NO_DATA);
rv = stream_update_dep_set_top(stream->sib_next, pq); rv = stream_update_dep_set_top(stream->sib_next, pq);
if(rv != 0) { if(rv < 0) {
return rv; return rv;
} }
return stream_update_dep_set_top(stream->dep_next, pq); num_top = rv;
rv = stream_update_dep_set_top(stream->dep_next, pq);
if(rv < 0) {
return rv;
}
stream->num_subtop = rv;
return stream->num_subtop + num_top;
} }
static int stream_update_dep_on_attach_data(nghttp2_stream *stream, static ssize_t stream_update_dep_on_attach_data(nghttp2_stream *stream,
nghttp2_pq *pq) nghttp2_pq *pq)
{ {
int rv; ssize_t rv;
nghttp2_stream *root_stream; nghttp2_stream *root_stream;
ssize_t old_num_subtop;
stream->dpri = NGHTTP2_STREAM_DPRI_REST; stream->dpri = NGHTTP2_STREAM_DPRI_REST;
@ -208,18 +260,27 @@ static int stream_update_dep_on_attach_data(nghttp2_stream *stream,
DEBUGF(fprintf(stderr, "root=%p, stream=%p\n", root_stream, stream)); DEBUGF(fprintf(stderr, "root=%p, stream=%p\n", root_stream, stream));
old_num_subtop = root_stream->num_subtop;
rv = stream_update_dep_set_top(root_stream, pq); rv = stream_update_dep_set_top(root_stream, pq);
if(rv != 0) { if(rv < 0) {
return rv; return rv;
} }
nghttp2_stream_group_update_num_top
(root_stream->stream_group, root_stream->num_subtop - old_num_subtop);
return 0; return 0;
} }
static int stream_update_dep_on_detach_data(nghttp2_stream *stream, static int stream_update_dep_on_detach_data(nghttp2_stream *stream,
nghttp2_pq *pq) nghttp2_pq *pq)
{ {
ssize_t rv;
nghttp2_stream *root_stream;
ssize_t old_num_subtop;
if(stream->dpri != NGHTTP2_STREAM_DPRI_TOP) { if(stream->dpri != NGHTTP2_STREAM_DPRI_TOP) {
stream->dpri = NGHTTP2_STREAM_DPRI_NO_DATA; stream->dpri = NGHTTP2_STREAM_DPRI_NO_DATA;
@ -228,7 +289,20 @@ static int stream_update_dep_on_detach_data(nghttp2_stream *stream,
stream->dpri = NGHTTP2_STREAM_DPRI_NO_DATA; stream->dpri = NGHTTP2_STREAM_DPRI_NO_DATA;
return stream_update_dep_set_top(stream->dep_next, pq); root_stream = nghttp2_stream_get_dep_root(stream);
old_num_subtop = root_stream->num_subtop;
rv = stream_update_dep_set_top(root_stream, pq);
if(rv < 0) {
return rv;
}
nghttp2_stream_group_update_num_top
(root_stream->stream_group, root_stream->num_subtop - old_num_subtop);
return 0;
} }
int nghttp2_stream_attach_data(nghttp2_stream *stream, int nghttp2_stream_attach_data(nghttp2_stream *stream,
@ -509,6 +583,8 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
nghttp2_stream *root_stream; nghttp2_stream *root_stream;
nghttp2_stream *si; nghttp2_stream *si;
size_t delta_substreams; size_t delta_substreams;
ssize_t old_num_subtop;
ssize_t rv;
DEBUGF(fprintf(stderr, "stream: dep_insert_subtree dep_stream(%p)=%d " DEBUGF(fprintf(stderr, "stream: dep_insert_subtree dep_stream(%p)=%d "
"stream(%p)=%d\n", "stream(%p)=%d\n",
@ -517,6 +593,9 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
delta_substreams = stream->num_substreams; delta_substreams = stream->num_substreams;
nghttp2_stream_group_update_num_top
(stream->stream_group, -stream->num_subtop);
stream_update_dep_set_rest_stream_group(stream, dep_stream->stream_group); stream_update_dep_set_rest_stream_group(stream, dep_stream->stream_group);
if(dep_stream->dep_next) { if(dep_stream->dep_next) {
@ -549,7 +628,18 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
root_stream = stream_update_dep_length(dep_stream, delta_substreams); root_stream = stream_update_dep_length(dep_stream, delta_substreams);
return stream_update_dep_set_top(root_stream, pq); old_num_subtop = root_stream->num_subtop;
rv = stream_update_dep_set_top(root_stream, pq);
if(rv < 0) {
return rv;
}
nghttp2_stream_group_update_num_top
(root_stream->stream_group, root_stream->num_subtop - old_num_subtop);
return 0;
} }
int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream, int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
@ -558,12 +648,17 @@ int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
{ {
nghttp2_stream *last_sib; nghttp2_stream *last_sib;
nghttp2_stream *root_stream; nghttp2_stream *root_stream;
ssize_t old_num_subtop;
ssize_t rv;
DEBUGF(fprintf(stderr, "stream: dep_add_subtree dep_stream(%p)=%d " DEBUGF(fprintf(stderr, "stream: dep_add_subtree dep_stream(%p)=%d "
"stream(%p)=%d\n", "stream(%p)=%d\n",
dep_stream, dep_stream->stream_id, dep_stream, dep_stream->stream_id,
stream, stream->stream_id)); stream, stream->stream_id));
nghttp2_stream_group_update_num_top
(stream->stream_group, -stream->num_subtop);
stream_update_dep_set_rest_stream_group(stream, dep_stream->stream_group); stream_update_dep_set_rest_stream_group(stream, dep_stream->stream_group);
if(dep_stream->dep_next) { if(dep_stream->dep_next) {
@ -578,13 +673,29 @@ int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
root_stream = stream_update_dep_length(dep_stream, stream->num_substreams); root_stream = stream_update_dep_length(dep_stream, stream->num_substreams);
return stream_update_dep_set_top(root_stream, pq); old_num_subtop = root_stream->num_subtop;
rv = stream_update_dep_set_top(root_stream, pq);
if(rv < 0) {
return rv;
}
nghttp2_stream_group_update_num_top
(root_stream->stream_group, root_stream->num_subtop - old_num_subtop);
return 0;
} }
void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream) void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream)
{ {
nghttp2_stream *prev, *next; nghttp2_stream *prev, *next;
DEBUGF(fprintf(stderr, "stream: dep_remove_subtree stream(%p)=%d\n",
stream, stream->stream_id));
/* Removing subtree does not change stream_group->num_top */
if(stream->sib_prev) { if(stream->sib_prev) {
prev = stream->sib_prev; prev = stream->sib_prev;
@ -595,7 +706,8 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream)
prev = stream_first_sib(prev); prev = stream_first_sib(prev);
if(prev->dep_prev) { if(prev->dep_prev) {
stream_update_dep_length(prev->dep_prev, -stream->num_substreams); stream_update_dep_both_length(prev->dep_prev, -stream->num_substreams,
-stream->num_subtop);
} }
} else if(stream->dep_prev) { } else if(stream->dep_prev) {
prev = stream->dep_prev; prev = stream->dep_prev;
@ -609,7 +721,8 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream)
next->sib_prev = NULL; next->sib_prev = NULL;
} }
stream_update_dep_length(prev, -stream->num_substreams); stream_update_dep_both_length(prev, -stream->num_substreams,
-stream->num_subtop);
} }
stream->sib_prev = NULL; stream->sib_prev = NULL;
@ -621,9 +734,29 @@ int nghttp2_stream_dep_make_root(nghttp2_stream_group *stream_group,
nghttp2_stream *stream, nghttp2_stream *stream,
nghttp2_pq *pq) nghttp2_pq *pq)
{ {
ssize_t rv;
DEBUGF(fprintf(stderr, "stream: dep_make_root new_stream_group(%p)=%d, "
"old_stream_group(%p)=%d, stream(%p)=%d\n",
stream_group, stream_group->pri_group_id,
stream->stream_group, stream->stream_group->pri_group_id,
stream, stream->stream_id));
/* First update num_top of old stream_group */
nghttp2_stream_group_update_num_top
(stream->stream_group, -stream->num_subtop);
stream_update_dep_set_rest_stream_group(stream, stream_group); stream_update_dep_set_rest_stream_group(stream, stream_group);
return stream_update_dep_set_top(stream, pq); rv = stream_update_dep_set_top(stream, pq);
if(rv < 0) {
return rv;
}
nghttp2_stream_group_update_num_top(stream_group, stream->num_subtop);
return 0;
} }
void nghttp2_stream_group_init(nghttp2_stream_group *stream_group, void nghttp2_stream_group_init(nghttp2_stream_group *stream_group,
@ -633,6 +766,7 @@ void nghttp2_stream_group_init(nghttp2_stream_group *stream_group,
nghttp2_map_entry_init(&stream_group->map_entry, pri_group_id); nghttp2_map_entry_init(&stream_group->map_entry, pri_group_id);
stream_group->num_streams = 0; stream_group->num_streams = 0;
stream_group->num_top = 0;
stream_group->pri_group_id = pri_group_id; stream_group->pri_group_id = pri_group_id;
stream_group->weight = weight; stream_group->weight = weight;
} }
@ -665,3 +799,24 @@ void nghttp2_stream_group_remove_stream(nghttp2_stream_group *stream_group,
--stream_group->num_streams; --stream_group->num_streams;
} }
void nghttp2_stream_group_update_num_top(nghttp2_stream_group *stream_group,
ssize_t delta)
{
DEBUGF(fprintf(stderr, "stream_group: stream_group(%p)=%d "
"update num_top current=%zd, delta=%zd, after=%zd\n",
stream_group->num_top, delta, stream_group->num_top + delta));
stream_group->num_top += delta;
assert(stream_group->num_top >= 0);
}
size_t nghttp2_stream_group_shared_wait(nghttp2_stream_group *stream_group)
{
if(stream_group->num_top == 0) {
return 1;
}
return nghttp2_max(1, stream_group->weight / stream_group->num_top);
}

View File

@ -138,8 +138,11 @@ struct nghttp2_stream {
/* categorized priority of this stream. Only stream bearing /* categorized priority of this stream. Only stream bearing
NGHTTP2_STREAM_DPRI_TOP can send DATA frame. */ NGHTTP2_STREAM_DPRI_TOP can send DATA frame. */
nghttp2_stream_dpri dpri; nghttp2_stream_dpri dpri;
/* the number of nodes in subtree */ /* the number of streams in subtree */
size_t num_substreams; size_t num_substreams;
/* the number of streams marked as NGHTTP2_STREAM_DPRI_TOP in
subtree */
ssize_t num_subtop;
/* Current remote window size. This value is computed against the /* Current remote window size. This value is computed against the
current initial window size of remote endpoint. */ current initial window size of remote endpoint. */
int32_t remote_window_size; int32_t remote_window_size;
@ -322,7 +325,8 @@ int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
/* /*
* Removes subtree whose root stream is |stream|. Removing subtree * Removes subtree whose root stream is |stream|. Removing subtree
* does not change dpri values. * does not change dpri values and removed subtree is still in the
* same stream_group.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
@ -354,6 +358,8 @@ struct nghttp2_stream_group {
nghttp2_map_entry map_entry; nghttp2_map_entry map_entry;
/* The number of streams this priority group contains */ /* The number of streams this priority group contains */
size_t num_streams; size_t num_streams;
/* The number of streams marked as NGHTTP2_STREAM_DPRI_TOP */
ssize_t num_top;
/* The priority group ID */ /* The priority group ID */
int32_t pri_group_id; int32_t pri_group_id;
/* The weight of this group */ /* The weight of this group */
@ -378,4 +384,15 @@ void nghttp2_stream_group_add_stream(nghttp2_stream_group *stream_group,
void nghttp2_stream_group_remove_stream(nghttp2_stream_group *stream_group, void nghttp2_stream_group_remove_stream(nghttp2_stream_group *stream_group,
nghttp2_stream *stream); nghttp2_stream *stream);
/*
* Updates |stream_group->num_top| += |delta|
*/
void nghttp2_stream_group_update_num_top(nghttp2_stream_group *stream_group,
ssize_t delta);
/*
* Returns shared weight among the streams belongs to |stream_group|.
*/
size_t nghttp2_stream_group_shared_wait(nghttp2_stream_group *stream_group);
#endif /* NGHTTP2_STREAM */ #endif /* NGHTTP2_STREAM */

View File

@ -5224,6 +5224,12 @@ void test_nghttp2_session_stream_attach_data(void)
CU_ASSERT(1 == db->queued); CU_ASSERT(1 == db->queued);
CU_ASSERT(1 == a->stream_group->num_top);
CU_ASSERT(1 == a->num_subtop);
CU_ASSERT(1 == b->num_subtop);
CU_ASSERT(0 == c->num_subtop);
CU_ASSERT(0 == d->num_subtop);
dc = create_data_ob_item(); dc = create_data_ob_item();
nghttp2_stream_attach_data(c, dc, &session->ob_pq); nghttp2_stream_attach_data(c, dc, &session->ob_pq);
@ -5235,6 +5241,12 @@ void test_nghttp2_session_stream_attach_data(void)
CU_ASSERT(1 == dc->queued); CU_ASSERT(1 == dc->queued);
CU_ASSERT(2 == a->stream_group->num_top);
CU_ASSERT(2 == a->num_subtop);
CU_ASSERT(1 == b->num_subtop);
CU_ASSERT(1 == c->num_subtop);
CU_ASSERT(0 == d->num_subtop);
da = create_data_ob_item(); da = create_data_ob_item();
nghttp2_stream_attach_data(a, da, &session->ob_pq); nghttp2_stream_attach_data(a, da, &session->ob_pq);
@ -5246,6 +5258,12 @@ void test_nghttp2_session_stream_attach_data(void)
CU_ASSERT(1 == da->queued); CU_ASSERT(1 == da->queued);
CU_ASSERT(1 == a->stream_group->num_top);
CU_ASSERT(1 == a->num_subtop);
CU_ASSERT(0 == b->num_subtop);
CU_ASSERT(0 == c->num_subtop);
CU_ASSERT(0 == d->num_subtop);
nghttp2_stream_detach_data(a, &session->ob_pq); nghttp2_stream_detach_data(a, &session->ob_pq);
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri);
@ -5253,6 +5271,12 @@ void test_nghttp2_session_stream_attach_data(void)
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == c->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == c->dpri);
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == d->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == d->dpri);
CU_ASSERT(2 == a->stream_group->num_top);
CU_ASSERT(2 == a->num_subtop);
CU_ASSERT(1 == b->num_subtop);
CU_ASSERT(1 == c->num_subtop);
CU_ASSERT(0 == d->num_subtop);
dd = create_data_ob_item(); dd = create_data_ob_item();
nghttp2_stream_attach_data(d, dd, &session->ob_pq); nghttp2_stream_attach_data(d, dd, &session->ob_pq);
@ -5264,6 +5288,12 @@ void test_nghttp2_session_stream_attach_data(void)
CU_ASSERT(0 == dd->queued); CU_ASSERT(0 == dd->queued);
CU_ASSERT(2 == a->stream_group->num_top);
CU_ASSERT(2 == a->num_subtop);
CU_ASSERT(1 == b->num_subtop);
CU_ASSERT(1 == c->num_subtop);
CU_ASSERT(0 == d->num_subtop);
nghttp2_stream_detach_data(c, &session->ob_pq); nghttp2_stream_detach_data(c, &session->ob_pq);
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri);
@ -5273,6 +5303,12 @@ void test_nghttp2_session_stream_attach_data(void)
CU_ASSERT(1 == dd->queued); CU_ASSERT(1 == dd->queued);
CU_ASSERT(2 == a->stream_group->num_top);
CU_ASSERT(2 == a->num_subtop);
CU_ASSERT(1 == b->num_subtop);
CU_ASSERT(1 == c->num_subtop);
CU_ASSERT(1 == d->num_subtop);
nghttp2_session_del(session); nghttp2_session_del(session);
} }
@ -5280,8 +5316,8 @@ void test_nghttp2_session_stream_attach_data_subtree(void)
{ {
nghttp2_session *session; nghttp2_session *session;
nghttp2_session_callbacks callbacks; nghttp2_session_callbacks callbacks;
nghttp2_stream *a, *b, *c, *d, *e, *f; nghttp2_stream *a, *b, *c, *d, *e, *f, *g, *h;
nghttp2_outbound_item *db, *de; nghttp2_outbound_item *db, *dd, *de;
(void)d; (void)d;
@ -5296,8 +5332,9 @@ void test_nghttp2_session_stream_attach_data_subtree(void)
e = open_stream(session, 9); e = open_stream(session, 9);
f = open_stream_with_dep(session, 11, e); f = open_stream_with_dep(session, 11, e);
/* gr.1 gr.9
/* a e *
* a e
* | | * | |
* b--c f * b--c f
* | * |
@ -5312,9 +5349,16 @@ void test_nghttp2_session_stream_attach_data_subtree(void)
nghttp2_stream_attach_data(b, db, &session->ob_pq); nghttp2_stream_attach_data(b, db, &session->ob_pq);
CU_ASSERT(1 == a->stream_group->num_top);
CU_ASSERT(1 == e->stream_group->num_top);
/* Insert subtree e under a */
nghttp2_stream_dep_insert_subtree(a, e, &session->ob_pq); nghttp2_stream_dep_insert_subtree(a, e, &session->ob_pq);
/* a /* gr.1
*
* a
* | * |
* e * e
* | * |
@ -5327,12 +5371,185 @@ void test_nghttp2_session_stream_attach_data_subtree(void)
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == f->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == f->dpri);
CU_ASSERT(1 == a->stream_group->num_top);
CU_ASSERT(1 == a->num_subtop);
CU_ASSERT(1 == e->num_subtop);
CU_ASSERT(0 == f->num_subtop);
CU_ASSERT(0 == b->num_subtop);
CU_ASSERT(0 == c->num_subtop);
CU_ASSERT(0 == d->num_subtop);
/* Remove subtree b */
nghttp2_stream_dep_remove_subtree(b); nghttp2_stream_dep_remove_subtree(b);
nghttp2_stream_dep_make_root(b->stream_group, b, &session->ob_pq); nghttp2_stream_dep_make_root(b->stream_group, b, &session->ob_pq);
/* gr.1 gr.1
*
* a b
* |
* e
* |
* f--c
* |
* d
*/
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
/* a and b are still same group */
CU_ASSERT(b->stream_group == a->stream_group);
CU_ASSERT(2 == b->stream_group->num_top);
CU_ASSERT(1 == b->num_subtop);
CU_ASSERT(2 == a->stream_group->num_top);
CU_ASSERT(1 == a->num_subtop);
CU_ASSERT(1 == e->num_subtop);
CU_ASSERT(0 == f->num_subtop);
CU_ASSERT(0 == c->num_subtop);
CU_ASSERT(0 == d->num_subtop);
/* Remove subtree a */
nghttp2_stream_dep_remove_subtree(a);
nghttp2_stream_dep_make_root(a->stream_group, a, &session->ob_pq);
CU_ASSERT(2 == a->stream_group->num_top);
CU_ASSERT(1 == a->num_subtop);
CU_ASSERT(1 == e->num_subtop);
CU_ASSERT(0 == f->num_subtop);
CU_ASSERT(0 == c->num_subtop);
CU_ASSERT(0 == d->num_subtop);
/* Remove subtree c */
nghttp2_stream_dep_remove_subtree(c);
nghttp2_stream_dep_make_root(c->stream_group, c, &session->ob_pq);
/* gr.1 gr.1 gr.1
*
* a b c
* | |
* e d
* |
* f
*/
CU_ASSERT(2 == a->stream_group->num_top);
CU_ASSERT(1 == a->num_subtop);
CU_ASSERT(1 == e->num_subtop);
CU_ASSERT(0 == f->num_subtop);
CU_ASSERT(0 == c->num_subtop);
CU_ASSERT(0 == d->num_subtop);
dd = create_data_ob_item();
nghttp2_stream_attach_data(d, dd, &session->ob_pq);
CU_ASSERT(3 == a->stream_group->num_top);
CU_ASSERT(1 == c->num_subtop);
CU_ASSERT(1 == d->num_subtop);
/* Add subtree c to a */
nghttp2_stream_dep_add_subtree(a, c, &session->ob_pq);
/* gr.1 gr.1
*
* a b
* |
* e--c
* | |
* f d
*/
CU_ASSERT(3 == a->stream_group->num_top);
CU_ASSERT(2 == a->num_subtop);
CU_ASSERT(1 == e->num_subtop);
CU_ASSERT(0 == f->num_subtop);
CU_ASSERT(1 == c->num_subtop);
CU_ASSERT(1 == d->num_subtop);
/* Insert b under a */
nghttp2_stream_dep_insert_subtree(a, b, &session->ob_pq);
/* gr.1
*
* a
* |
* b
* |
* e--c
* | |
* f d
*/
CU_ASSERT(1 == a->stream_group->num_top);
CU_ASSERT(1 == a->num_subtop);
CU_ASSERT(1 == b->num_subtop);
CU_ASSERT(0 == e->num_subtop);
CU_ASSERT(0 == f->num_subtop);
CU_ASSERT(0 == c->num_subtop);
CU_ASSERT(0 == d->num_subtop);
g = open_stream(session, 13);
h = open_stream(session, 15);
nghttp2_stream_dep_make_root(a->stream_group, h, &session->ob_pq);
nghttp2_stream_dep_make_root(g->stream_group, a, &session->ob_pq);
/* gr.13 gr.13 gr.1
*
* a g h
* |
* b
* |
* e--c
* | |
* f d
*/
CU_ASSERT(g->stream_group == a->stream_group);
CU_ASSERT(0 == h->stream_group->num_top);
CU_ASSERT(1 == a->stream_group->num_top);
CU_ASSERT(1 == a->num_subtop);
CU_ASSERT(1 == b->num_subtop);
CU_ASSERT(0 == e->num_subtop);
CU_ASSERT(0 == f->num_subtop);
CU_ASSERT(0 == c->num_subtop);
CU_ASSERT(0 == d->num_subtop);
/* Remove subtree b */
nghttp2_stream_dep_remove_subtree(b);
/* gr.13 gr.13 gr.13 gr.1
*
* b a g h
* |
* e--c
* | |
* f d
*/
CU_ASSERT(1 == b->stream_group->num_top);
CU_ASSERT(1 == b->num_subtop);
CU_ASSERT(0 == e->num_subtop);
CU_ASSERT(0 == f->num_subtop);
CU_ASSERT(0 == c->num_subtop);
CU_ASSERT(0 == d->num_subtop);
CU_ASSERT(0 == a->num_subtop);
nghttp2_session_del(session); nghttp2_session_del(session);
} }