Allow exclusive dependency to stream 0
This commit is contained in:
parent
ac86b51e37
commit
aa4d43f31e
|
@ -2105,8 +2105,6 @@ void nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec);
|
|||
* @function
|
||||
*
|
||||
* Returns nonzero if the |pri_spec| is filled with default values.
|
||||
* `pri_spec->exclusive` is ignored since it is irrelevant when
|
||||
* `pri_spec->stream_id == 0`.
|
||||
*/
|
||||
int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec);
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ void nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec)
|
|||
|
||||
int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec)
|
||||
{
|
||||
/* Ignore exclusive flag */
|
||||
return pri_spec->stream_id == 0 &&
|
||||
pri_spec->weight == NGHTTP2_DEFAULT_WEIGHT;
|
||||
pri_spec->weight == NGHTTP2_DEFAULT_WEIGHT &&
|
||||
pri_spec->exclusive == 0;
|
||||
}
|
||||
|
|
|
@ -280,6 +280,8 @@ static int nghttp2_session_new(nghttp2_session **session_ptr,
|
|||
goto fail_map;
|
||||
}
|
||||
|
||||
nghttp2_stream_roots_init(&(*session_ptr)->roots);
|
||||
|
||||
(*session_ptr)->next_seq = 0;
|
||||
|
||||
(*session_ptr)->remote_window_size = NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
|
||||
|
@ -436,6 +438,8 @@ void nghttp2_session_del(nghttp2_session *session)
|
|||
}
|
||||
free(session->inflight_iv);
|
||||
|
||||
nghttp2_stream_roots_free(&session->roots);
|
||||
|
||||
/* Have to free streams first, so that we can check
|
||||
stream->data_item->queued */
|
||||
nghttp2_map_each_free(&session->streams, nghttp2_free_streams, NULL);
|
||||
|
@ -470,14 +474,21 @@ int nghttp2_session_reprioritize_stream
|
|||
/* We have to update weight after removing stream from tree */
|
||||
stream->weight = pri_spec->weight;
|
||||
|
||||
if(pri_spec->exclusive &&
|
||||
session->roots.num_streams <= NGHTTP2_MAX_DEP_TREE_LENGTH) {
|
||||
|
||||
rv = nghttp2_stream_dep_all_your_stream_are_belong_to_us
|
||||
(stream, &session->ob_pq);
|
||||
} else {
|
||||
rv = nghttp2_stream_dep_make_root(stream, &session->ob_pq);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id);
|
||||
|
||||
if(dep_stream == NULL) {
|
||||
if(!dep_stream || !nghttp2_stream_in_dep_tree(dep_stream)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -711,7 +722,7 @@ nghttp2_stream* nghttp2_session_open_stream(nghttp2_session *session,
|
|||
}
|
||||
|
||||
nghttp2_stream_init(stream, stream_id, flags, initial_state,
|
||||
pri_spec->weight,
|
||||
pri_spec->weight, &session->roots,
|
||||
session->remote_settings
|
||||
[NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
|
||||
session->local_settings
|
||||
|
@ -747,9 +758,29 @@ nghttp2_stream* nghttp2_session_open_stream(nghttp2_session *session,
|
|||
return stream;
|
||||
}
|
||||
|
||||
if(pri_spec->stream_id == 0) {
|
||||
|
||||
++session->roots.num_streams;
|
||||
|
||||
if(pri_spec->exclusive &&
|
||||
session->roots.num_streams <= NGHTTP2_MAX_DEP_TREE_LENGTH) {
|
||||
rv = nghttp2_stream_dep_all_your_stream_are_belong_to_us
|
||||
(stream, &session->ob_pq);
|
||||
|
||||
/* Since no dpri is changed in dependency tree, the above
|
||||
function call never fail. */
|
||||
assert(rv == 0);
|
||||
} else {
|
||||
nghttp2_stream_roots_add(&session->roots, stream);
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id);
|
||||
|
||||
if(!dep_stream) {
|
||||
/* If dep_stream is not part of dependency tree, we don't use it. */
|
||||
if(!dep_stream || !nghttp2_stream_in_dep_tree(dep_stream)) {
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
@ -831,7 +862,9 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id,
|
|||
/* Closes both directions just in case they are not closed yet */
|
||||
stream->flags |= NGHTTP2_STREAM_FLAG_CLOSED;
|
||||
|
||||
if(session->server && !nghttp2_session_is_my_stream_id(session, stream_id)) {
|
||||
if(session->server &&
|
||||
nghttp2_stream_in_dep_tree(stream) &&
|
||||
!nghttp2_session_is_my_stream_id(session, stream_id)) {
|
||||
/* On server side, retain incoming stream object at most
|
||||
MAX_CONCURRENT_STREAMS combined with the current active streams
|
||||
to make dependency tree work better. */
|
||||
|
|
|
@ -117,6 +117,7 @@ typedef enum {
|
|||
|
||||
struct nghttp2_session {
|
||||
nghttp2_map /* <nghttp2_stream*> */ streams;
|
||||
nghttp2_stream_roots roots;
|
||||
/* Queue for outbound frames other than stream-creating HEADERS */
|
||||
nghttp2_pq /* <nghttp2_outbound_item*> */ ob_pq;
|
||||
/* Queue for outbound stream-creating HEADERS frame */
|
||||
|
|
|
@ -33,6 +33,7 @@ void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
|
|||
uint8_t flags,
|
||||
nghttp2_stream_state initial_state,
|
||||
int32_t weight,
|
||||
nghttp2_stream_roots *roots,
|
||||
int32_t remote_initial_window_size,
|
||||
int32_t local_initial_window_size,
|
||||
void *stream_user_data)
|
||||
|
@ -61,6 +62,10 @@ void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
|
|||
stream->weight = weight;
|
||||
stream->effective_weight = stream->weight;
|
||||
stream->sum_dep_weight = 0;
|
||||
|
||||
stream->roots = roots;
|
||||
stream->root_prev = NULL;
|
||||
stream->root_next = NULL;
|
||||
}
|
||||
|
||||
void nghttp2_stream_free(nghttp2_stream *stream)
|
||||
|
@ -474,6 +479,8 @@ void nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
|
|||
|
||||
stream_update_dep_length(dep_stream, 1);
|
||||
stream_update_dep_effective_weight(dep_stream);
|
||||
|
||||
++stream->roots->num_streams;
|
||||
}
|
||||
|
||||
void nghttp2_stream_dep_add(nghttp2_stream *dep_stream,
|
||||
|
@ -502,6 +509,8 @@ void nghttp2_stream_dep_add(nghttp2_stream *dep_stream,
|
|||
}
|
||||
|
||||
stream_update_dep_effective_weight(dep_stream);
|
||||
|
||||
++stream->roots->num_streams;
|
||||
}
|
||||
|
||||
void nghttp2_stream_dep_remove(nghttp2_stream *stream)
|
||||
|
@ -568,6 +577,8 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream)
|
|||
dep_next = NULL;
|
||||
}
|
||||
} else {
|
||||
nghttp2_stream_roots_remove(stream->roots, stream);
|
||||
|
||||
dep_next = NULL;
|
||||
|
||||
/* stream is a root of tree. Removing stream makes its
|
||||
|
@ -583,6 +594,8 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream)
|
|||
/* We already distributed weight of |stream| to this. */
|
||||
si->effective_weight = si->weight;
|
||||
|
||||
nghttp2_stream_roots_add(si->roots, si);
|
||||
|
||||
si = next;
|
||||
}
|
||||
}
|
||||
|
@ -606,6 +619,8 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream)
|
|||
stream->dep_next = NULL;
|
||||
stream->sib_prev = NULL;
|
||||
stream->sib_next = NULL;
|
||||
|
||||
--stream->roots->num_streams;
|
||||
}
|
||||
|
||||
int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
|
||||
|
@ -748,6 +763,8 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream)
|
|||
}
|
||||
|
||||
} else {
|
||||
nghttp2_stream_roots_remove(stream->roots, stream);
|
||||
|
||||
dep_prev = NULL;
|
||||
}
|
||||
|
||||
|
@ -771,6 +788,8 @@ int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq)
|
|||
DEBUGF(fprintf(stderr, "stream: dep_make_root stream(%p)=%d\n",
|
||||
stream, stream->stream_id));
|
||||
|
||||
nghttp2_stream_roots_add(stream->roots, stream);
|
||||
|
||||
stream_update_dep_set_rest(stream);
|
||||
|
||||
stream->effective_weight = stream->weight;
|
||||
|
@ -785,3 +804,141 @@ int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_stream_dep_all_your_stream_are_belong_to_us
|
||||
(nghttp2_stream *stream, nghttp2_pq *pq)
|
||||
{
|
||||
nghttp2_stream *first, *si;
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: ALL YOUR STREAM ARE BELONG TO US "
|
||||
"stream(%p)=%d\n",
|
||||
stream, stream->stream_id));
|
||||
|
||||
first = stream->roots->head;
|
||||
|
||||
/* stream must not be include in stream->roots->head list */
|
||||
assert(first != stream);
|
||||
|
||||
if(first) {
|
||||
nghttp2_stream *prev;
|
||||
|
||||
prev = first;
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: root stream(%p)=%d\n",
|
||||
first, first->stream_id));
|
||||
|
||||
stream->sum_dep_weight += first->weight;
|
||||
stream->num_substreams += first->num_substreams;
|
||||
|
||||
for(si = first->root_next; si; si = si->root_next) {
|
||||
|
||||
assert(si != stream);
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: root stream(%p)=%d\n",
|
||||
si, si->stream_id));
|
||||
|
||||
fprintf(stderr, "w=%d, sum=%d\n",
|
||||
si->weight, stream->sum_dep_weight);
|
||||
stream->sum_dep_weight += si->weight;
|
||||
stream->num_substreams += si->num_substreams;
|
||||
|
||||
si->sib_prev = prev;
|
||||
prev->sib_next = si;
|
||||
|
||||
prev = si;
|
||||
}
|
||||
|
||||
if(stream->dep_next) {
|
||||
nghttp2_stream *last_sib;
|
||||
|
||||
last_sib = stream_last_sib(stream->dep_next);
|
||||
|
||||
last_sib->sib_next = first;
|
||||
first->sib_prev = last_sib;
|
||||
} else {
|
||||
stream->dep_next = first;
|
||||
first->dep_prev = stream;
|
||||
}
|
||||
}
|
||||
|
||||
nghttp2_stream_roots_remove_all(stream->roots);
|
||||
|
||||
return nghttp2_stream_dep_make_root(stream, pq);
|
||||
}
|
||||
|
||||
int nghttp2_stream_in_dep_tree(nghttp2_stream *stream)
|
||||
{
|
||||
return stream->dep_prev || stream->dep_next ||
|
||||
stream->sib_prev || stream->sib_next ||
|
||||
stream->root_next || stream->root_prev ||
|
||||
stream->roots->head == stream;
|
||||
}
|
||||
|
||||
void nghttp2_stream_roots_init(nghttp2_stream_roots *roots)
|
||||
{
|
||||
roots->head = NULL;
|
||||
roots->num_streams = 0;
|
||||
}
|
||||
|
||||
void nghttp2_stream_roots_free(nghttp2_stream_roots *roots)
|
||||
{}
|
||||
|
||||
void nghttp2_stream_roots_add(nghttp2_stream_roots *roots,
|
||||
nghttp2_stream *stream)
|
||||
{
|
||||
if(roots->head) {
|
||||
nghttp2_stream *si;
|
||||
for(si = roots->head; si; si = si->root_next) {
|
||||
if(si == stream) {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
stream->root_next = roots->head;
|
||||
roots->head->root_prev = stream;
|
||||
}
|
||||
|
||||
roots->head = stream;
|
||||
}
|
||||
|
||||
void nghttp2_stream_roots_remove(nghttp2_stream_roots *roots,
|
||||
nghttp2_stream *stream)
|
||||
{
|
||||
nghttp2_stream *root_prev, *root_next;
|
||||
|
||||
root_prev = stream->root_prev;
|
||||
root_next = stream->root_next;
|
||||
|
||||
if(root_prev) {
|
||||
root_prev->root_next = root_next;
|
||||
|
||||
if(root_next) {
|
||||
root_next->root_prev = root_prev;
|
||||
}
|
||||
} else {
|
||||
if(root_next) {
|
||||
root_next->root_prev = NULL;
|
||||
}
|
||||
|
||||
roots->head = root_next;
|
||||
}
|
||||
|
||||
stream->root_prev = NULL;
|
||||
stream->root_next = NULL;
|
||||
}
|
||||
|
||||
void nghttp2_stream_roots_remove_all(nghttp2_stream_roots *roots)
|
||||
{
|
||||
nghttp2_stream *si, *next;
|
||||
|
||||
for(si = roots->head; si;) {
|
||||
next = si->root_next;
|
||||
|
||||
si->root_prev = NULL;
|
||||
si->root_next = NULL;
|
||||
|
||||
si = next;
|
||||
}
|
||||
|
||||
roots->head = NULL;
|
||||
}
|
||||
|
|
|
@ -102,6 +102,10 @@ typedef enum {
|
|||
NGHTTP2_STREAM_DPRI_REST = 0x04
|
||||
} nghttp2_stream_dpri;
|
||||
|
||||
struct nghttp2_stream_roots;
|
||||
|
||||
typedef struct nghttp2_stream_roots nghttp2_stream_roots;
|
||||
|
||||
struct nghttp2_stream;
|
||||
|
||||
typedef struct nghttp2_stream nghttp2_stream;
|
||||
|
@ -118,11 +122,17 @@ struct nghttp2_stream {
|
|||
dep_prev and sib_prev are NULL. */
|
||||
nghttp2_stream *dep_prev, *dep_next;
|
||||
nghttp2_stream *sib_prev, *sib_next;
|
||||
/* pointers to track dependency tree root streams. This is
|
||||
doubly-linked list and first element is pointed by
|
||||
roots->head. */
|
||||
nghttp2_stream *root_prev, *root_next;
|
||||
/* When stream is kept after closure, it may be kept in single
|
||||
linked list pointed by nghttp2_session closed_stream_head.
|
||||
closed_next points to the next stream object if it is the element
|
||||
of the list. */
|
||||
nghttp2_stream *closed_next;
|
||||
/* pointer to roots, which tracks dependency tree roots */
|
||||
nghttp2_stream_roots *roots;
|
||||
/* The arbitrary data provided by user for this stream. */
|
||||
void *stream_user_data;
|
||||
/* DATA frame item */
|
||||
|
@ -165,6 +175,7 @@ void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
|
|||
uint8_t flags,
|
||||
nghttp2_stream_state initial_state,
|
||||
int32_t weight,
|
||||
nghttp2_stream_roots *roots,
|
||||
int32_t remote_initial_window_size,
|
||||
int32_t local_initial_window_size,
|
||||
void *stream_user_data);
|
||||
|
@ -380,4 +391,40 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream);
|
|||
*/
|
||||
int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq);
|
||||
|
||||
/*
|
||||
* Makes the |stream| as root and all existing root streams become
|
||||
* direct children of |stream|.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_stream_dep_all_your_stream_are_belong_to_us
|
||||
(nghttp2_stream *stream, nghttp2_pq *pq);
|
||||
|
||||
/*
|
||||
* Returns nonzero if |stream| is in any dependency tree.
|
||||
*/
|
||||
int nghttp2_stream_in_dep_tree(nghttp2_stream *stream);
|
||||
|
||||
struct nghttp2_stream_roots {
|
||||
nghttp2_stream *head;
|
||||
|
||||
int32_t num_streams;
|
||||
};
|
||||
|
||||
void nghttp2_stream_roots_init(nghttp2_stream_roots *roots);
|
||||
|
||||
void nghttp2_stream_roots_free(nghttp2_stream_roots *roots);
|
||||
|
||||
void nghttp2_stream_roots_add(nghttp2_stream_roots *roots,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
void nghttp2_stream_roots_remove(nghttp2_stream_roots *roots,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
void nghttp2_stream_roots_remove_all(nghttp2_stream_roots *roots);
|
||||
|
||||
#endif /* NGHTTP2_STREAM */
|
||||
|
|
|
@ -103,10 +103,6 @@ static int nghttp2_submit_headers_shared
|
|||
|
||||
static void adjust_priority_spec_weight(nghttp2_priority_spec *pri_spec)
|
||||
{
|
||||
if(pri_spec->stream_id == 0) {
|
||||
pri_spec->exclusive = 0;
|
||||
}
|
||||
|
||||
if(pri_spec->weight < NGHTTP2_MIN_WEIGHT) {
|
||||
pri_spec->weight = NGHTTP2_MIN_WEIGHT;
|
||||
} else if(pri_spec->weight > NGHTTP2_MAX_WEIGHT) {
|
||||
|
|
|
@ -222,6 +222,8 @@ int main(int argc, char* argv[])
|
|||
test_nghttp2_session_stream_dep_add_subtree) ||
|
||||
!CU_add_test(pSuite, "session_stream_dep_remove_subtree",
|
||||
test_nghttp2_session_stream_dep_remove_subtree) ||
|
||||
!CU_add_test(pSuite, "session_stream_dep_all_your_stream_are_belong_to_us",
|
||||
test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us) ||
|
||||
!CU_add_test(pSuite, "session_stream_attach_data",
|
||||
test_nghttp2_session_stream_attach_data) ||
|
||||
!CU_add_test(pSuite, "session_stream_attach_data_subtree",
|
||||
|
|
|
@ -4873,6 +4873,10 @@ void test_nghttp2_session_stream_dep_add(void)
|
|||
check_stream_dep_sib(c, NULL, d, b, NULL);
|
||||
check_stream_dep_sib(d, c, NULL, NULL, NULL);
|
||||
|
||||
CU_ASSERT(4 == session->roots.num_streams);
|
||||
CU_ASSERT(a == session->roots.head);
|
||||
CU_ASSERT(NULL == a->root_next);
|
||||
|
||||
e = open_stream_with_dep_excl(session, 9, a);
|
||||
|
||||
/* a
|
||||
|
@ -4902,6 +4906,10 @@ void test_nghttp2_session_stream_dep_add(void)
|
|||
check_stream_dep_sib(c, NULL, d, b, NULL);
|
||||
check_stream_dep_sib(d, c, NULL, NULL, NULL);
|
||||
|
||||
CU_ASSERT(5 == session->roots.num_streams);
|
||||
CU_ASSERT(a == session->roots.head);
|
||||
CU_ASSERT(NULL == a->root_next);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
|
@ -4951,6 +4959,11 @@ void test_nghttp2_session_stream_dep_remove(void)
|
|||
check_stream_dep_sib(c, NULL, d, NULL, NULL);
|
||||
check_stream_dep_sib(d, c, NULL, NULL, NULL);
|
||||
|
||||
CU_ASSERT(3 == session->roots.num_streams);
|
||||
CU_ASSERT(c == session->roots.head);
|
||||
CU_ASSERT(b == c->root_next);
|
||||
CU_ASSERT(NULL == b->root_next);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
|
||||
/* Remove left most stream */
|
||||
|
@ -4993,6 +5006,10 @@ void test_nghttp2_session_stream_dep_remove(void)
|
|||
check_stream_dep_sib(c, a, d, NULL, NULL);
|
||||
check_stream_dep_sib(d, c, NULL, NULL, NULL);
|
||||
|
||||
CU_ASSERT(3 == session->roots.num_streams);
|
||||
CU_ASSERT(a == session->roots.head);
|
||||
CU_ASSERT(NULL == a->root_next);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
|
||||
/* Remove right most stream */
|
||||
|
@ -5348,6 +5365,131 @@ void test_nghttp2_session_stream_dep_remove_subtree(void)
|
|||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void)
|
||||
{
|
||||
nghttp2_session *session;
|
||||
nghttp2_session_callbacks callbacks;
|
||||
nghttp2_stream *a, *b, *c, *d;
|
||||
|
||||
memset(&callbacks, 0, sizeof(callbacks));
|
||||
|
||||
nghttp2_session_server_new(&session, &callbacks, NULL);
|
||||
|
||||
a = open_stream(session, 1);
|
||||
b = open_stream_with_dep(session, 3, a);
|
||||
|
||||
c = open_stream(session, 5);
|
||||
|
||||
/* a c
|
||||
* |
|
||||
* b
|
||||
*/
|
||||
|
||||
nghttp2_stream_dep_remove_subtree(c);
|
||||
CU_ASSERT(0 == nghttp2_stream_dep_all_your_stream_are_belong_to_us
|
||||
(c, &session->ob_pq));
|
||||
|
||||
/*
|
||||
* c
|
||||
* |
|
||||
* a
|
||||
* |
|
||||
* b
|
||||
*/
|
||||
|
||||
CU_ASSERT(3 == c->num_substreams);
|
||||
CU_ASSERT(2 == a->num_substreams);
|
||||
CU_ASSERT(1 == b->num_substreams);
|
||||
|
||||
CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
|
||||
CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
|
||||
CU_ASSERT(0 == b->sum_dep_weight);
|
||||
|
||||
check_stream_dep_sib(c, NULL, a, NULL, NULL);
|
||||
check_stream_dep_sib(a, c, b, NULL, NULL);
|
||||
check_stream_dep_sib(b, a, NULL, NULL, NULL);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
|
||||
nghttp2_session_server_new(&session, &callbacks, NULL);
|
||||
|
||||
a = open_stream(session, 1);
|
||||
|
||||
b = open_stream(session, 3);
|
||||
|
||||
c = open_stream(session, 5);
|
||||
|
||||
/*
|
||||
* a b c
|
||||
*/
|
||||
|
||||
nghttp2_stream_dep_remove_subtree(c);
|
||||
CU_ASSERT(0 == nghttp2_stream_dep_all_your_stream_are_belong_to_us
|
||||
(c, &session->ob_pq));
|
||||
|
||||
/*
|
||||
* c
|
||||
* |
|
||||
* b--a
|
||||
*/
|
||||
|
||||
CU_ASSERT(3 == c->num_substreams);
|
||||
CU_ASSERT(1 == a->num_substreams);
|
||||
CU_ASSERT(1 == b->num_substreams);
|
||||
|
||||
CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
|
||||
CU_ASSERT(0 == b->sum_dep_weight);
|
||||
CU_ASSERT(0 == a->sum_dep_weight);
|
||||
|
||||
check_stream_dep_sib(c, NULL, b, NULL, NULL);
|
||||
check_stream_dep_sib(b, c, NULL, NULL, a);
|
||||
check_stream_dep_sib(a, NULL, NULL, b, NULL);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
|
||||
nghttp2_session_server_new(&session, &callbacks, NULL);
|
||||
|
||||
a = open_stream(session, 1);
|
||||
b = open_stream_with_dep(session, 3, a);
|
||||
|
||||
c = open_stream(session, 5);
|
||||
d = open_stream_with_dep(session, 7, c);
|
||||
|
||||
/* a c
|
||||
* | |
|
||||
* b d
|
||||
*/
|
||||
|
||||
nghttp2_stream_dep_remove_subtree(c);
|
||||
CU_ASSERT(0 == nghttp2_stream_dep_all_your_stream_are_belong_to_us
|
||||
(c, &session->ob_pq));
|
||||
|
||||
/*
|
||||
* c
|
||||
* |
|
||||
* d--a
|
||||
* |
|
||||
* b
|
||||
*/
|
||||
|
||||
CU_ASSERT(4 == c->num_substreams);
|
||||
CU_ASSERT(1 == d->num_substreams);
|
||||
CU_ASSERT(2 == a->num_substreams);
|
||||
CU_ASSERT(1 == b->num_substreams);
|
||||
|
||||
CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
|
||||
CU_ASSERT(0 == d->sum_dep_weight);
|
||||
CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
|
||||
CU_ASSERT(0 == b->sum_dep_weight);
|
||||
|
||||
check_stream_dep_sib(c, NULL, d, NULL, NULL);
|
||||
check_stream_dep_sib(d, c, NULL, NULL, a);
|
||||
check_stream_dep_sib(a, NULL, b, d, NULL);
|
||||
check_stream_dep_sib(b, a, NULL, NULL, NULL);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
static nghttp2_outbound_item* create_data_ob_item(void)
|
||||
{
|
||||
nghttp2_outbound_item *item;
|
||||
|
@ -5488,6 +5630,7 @@ void test_nghttp2_session_stream_attach_data_subtree(void)
|
|||
|
||||
/* Insert subtree e under a */
|
||||
|
||||
nghttp2_stream_dep_remove_subtree(e);
|
||||
nghttp2_stream_dep_insert_subtree(a, e, &session->ob_pq);
|
||||
|
||||
/*
|
||||
|
@ -5570,6 +5713,7 @@ void test_nghttp2_session_stream_attach_data_subtree(void)
|
|||
|
||||
/* Add subtree c to a */
|
||||
|
||||
nghttp2_stream_dep_remove_subtree(c);
|
||||
nghttp2_stream_dep_add_subtree(a, c, &session->ob_pq);
|
||||
|
||||
/*
|
||||
|
@ -5589,6 +5733,7 @@ void test_nghttp2_session_stream_attach_data_subtree(void)
|
|||
|
||||
/* Insert b under a */
|
||||
|
||||
nghttp2_stream_dep_remove_subtree(b);
|
||||
nghttp2_stream_dep_insert_subtree(a, b, &session->ob_pq);
|
||||
|
||||
/*
|
||||
|
@ -5608,21 +5753,10 @@ void test_nghttp2_session_stream_attach_data_subtree(void)
|
|||
CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == e->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == f->dpri);
|
||||
|
||||
nghttp2_stream_dep_make_root(a, &session->ob_pq);
|
||||
|
||||
/*
|
||||
* a
|
||||
* |
|
||||
* b
|
||||
* |
|
||||
* e--c
|
||||
* | |
|
||||
* f d
|
||||
*/
|
||||
|
||||
/* Remove subtree b */
|
||||
|
||||
nghttp2_stream_dep_remove_subtree(b);
|
||||
nghttp2_stream_dep_make_root(b, &session->ob_pq);
|
||||
|
||||
/*
|
||||
* b a
|
||||
|
@ -5870,6 +6004,58 @@ void test_nghttp2_session_stream_dep_effective_weight(void)
|
|||
CU_ASSERT(16 * 4 / 20 == d->effective_weight);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
|
||||
nghttp2_session_server_new(&session, &callbacks, NULL);
|
||||
|
||||
a = open_stream(session, 1);
|
||||
b = open_stream_with_dep_weight(session, 3, 8, a);
|
||||
c = open_stream_with_dep_weight(session, 5, 4, a);
|
||||
d = open_stream_with_dep_weight(session, 7, 1, c);
|
||||
|
||||
e = open_stream(session, 9);
|
||||
f = open_stream_with_dep_weight(session, 11, 12, e);
|
||||
|
||||
/* a e
|
||||
* | |
|
||||
* b--c f
|
||||
* |
|
||||
* d
|
||||
*/
|
||||
|
||||
CU_ASSERT(e->roots->head == e);
|
||||
CU_ASSERT(a == e->root_next);
|
||||
|
||||
/* Insert e under stream 0 */
|
||||
nghttp2_stream_dep_remove_subtree(e);
|
||||
|
||||
CU_ASSERT(a == e->roots->head);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_stream_dep_all_your_stream_are_belong_to_us
|
||||
(e, &session->ob_pq));
|
||||
|
||||
/* e
|
||||
* |
|
||||
* f--a
|
||||
* |
|
||||
* b--c
|
||||
* |
|
||||
* d
|
||||
*/
|
||||
|
||||
CU_ASSERT(6 == e->num_substreams);
|
||||
CU_ASSERT(28 == e->sum_dep_weight);
|
||||
|
||||
CU_ASSERT(16 == e->effective_weight);
|
||||
|
||||
CU_ASSERT(16 * 16 / 28 == a->effective_weight);
|
||||
CU_ASSERT(16 * 12 / 28 == f->effective_weight);
|
||||
|
||||
CU_ASSERT((16 * 16 / 28) * 8 / 12 == b->effective_weight);
|
||||
CU_ASSERT((16 * 16 / 28) * 4 / 12 == c->effective_weight);
|
||||
|
||||
CU_ASSERT((16 * 16 / 28) * 4 / 12 == d->effective_weight);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
void test_nghttp2_session_keep_closed_stream(void)
|
||||
|
|
|
@ -103,6 +103,7 @@ void test_nghttp2_session_stream_dep_add(void);
|
|||
void test_nghttp2_session_stream_dep_remove(void);
|
||||
void test_nghttp2_session_stream_dep_add_subtree(void);
|
||||
void test_nghttp2_session_stream_dep_remove_subtree(void);
|
||||
void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void);
|
||||
void test_nghttp2_session_stream_attach_data(void);
|
||||
void test_nghttp2_session_stream_attach_data_subtree(void);
|
||||
void test_nghttp2_session_stream_dep_effective_weight(void);
|
||||
|
|
Loading…
Reference in New Issue