From 3e3d51842bca9661dd4763e0fc755a85e8cef206 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Thu, 8 May 2014 23:07:29 +0900 Subject: [PATCH] Interleave stream DATA more naturally We simulate resource sharing by decreasing weight. The thing is if weight is wrapped, that item continues to send DATA until its weight gets lowered under the other items. This commits fix this issue. --- lib/nghttp2_outbound_item.h | 3 ++ lib/nghttp2_session.c | 95 ++++++++++++++++++++++++------------ lib/nghttp2_session.h | 14 ++++++ lib/nghttp2_stream.c | 57 +++++++++++++--------- lib/nghttp2_stream.h | 21 +++++--- tests/nghttp2_session_test.c | 47 +++++++++--------- 6 files changed, 150 insertions(+), 87 deletions(-) diff --git a/lib/nghttp2_outbound_item.h b/lib/nghttp2_outbound_item.h index 50cbb4f3..0d1c105b 100644 --- a/lib/nghttp2_outbound_item.h +++ b/lib/nghttp2_outbound_item.h @@ -46,6 +46,9 @@ typedef struct { typedef struct { int64_t seq; + /* Reset count of weight. See comment for last_cycle in + nghttp2_session.h */ + uint64_t cycle; void *frame; void *aux_data; /* Type of |frame|. NGHTTP2_CTRL: nghttp2_frame*, NGHTTP2_DATA: diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index d083cdda..288b11e3 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -154,12 +154,16 @@ static int nghttp2_outbound_item_compar(const void *lhsx, const void *rhsx) lhs = (const nghttp2_outbound_item*)lhsx; rhs = (const nghttp2_outbound_item*)rhsx; - if(lhs->weight == rhs->weight) { - return (lhs->seq < rhs->seq) ? -1 : ((lhs->seq > rhs->seq) ? 1 : 0); + if(lhs->cycle == rhs->cycle) { + if(lhs->weight == rhs->weight) { + return (lhs->seq < rhs->seq) ? -1 : ((lhs->seq > rhs->seq) ? 1 : 0); + } + + /* Larger weight has higher precedence */ + return rhs->weight - lhs->weight; } - /* Larger weight has higher precedence */ - return rhs->weight - lhs->weight; + return (lhs->cycle < rhs->cycle) ? -1 : 1; } static void nghttp2_inbound_frame_reset(nghttp2_session *session) @@ -287,6 +291,7 @@ static int nghttp2_session_new(nghttp2_session **session_ptr, nghttp2_stream_roots_init(&(*session_ptr)->roots); (*session_ptr)->next_seq = 0; + (*session_ptr)->last_cycle = 1; (*session_ptr)->remote_window_size = NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE; (*session_ptr)->recv_window_size = 0; @@ -482,9 +487,10 @@ int nghttp2_session_reprioritize_stream session->roots.num_streams <= NGHTTP2_MAX_DEP_TREE_LENGTH) { rv = nghttp2_stream_dep_all_your_stream_are_belong_to_us - (stream, &session->ob_pq); + (stream, &session->ob_pq, session->last_cycle); } else { - rv = nghttp2_stream_dep_make_root(stream, &session->ob_pq); + rv = nghttp2_stream_dep_make_root(stream, &session->ob_pq, + session->last_cycle); } return rv; @@ -504,7 +510,8 @@ int nghttp2_session_reprioritize_stream stream, stream->stream_id)); nghttp2_stream_dep_remove_subtree(dep_stream); - nghttp2_stream_dep_make_root(dep_stream, &session->ob_pq); + nghttp2_stream_dep_make_root(dep_stream, &session->ob_pq, + session->last_cycle); } nghttp2_stream_dep_remove_subtree(stream); @@ -516,14 +523,17 @@ int nghttp2_session_reprioritize_stream if(root_stream->num_substreams + stream->num_substreams > NGHTTP2_MAX_DEP_TREE_LENGTH) { - rv = nghttp2_stream_dep_make_root(stream, &session->ob_pq); + rv = nghttp2_stream_dep_make_root(stream, &session->ob_pq, + session->last_cycle); } else { if(pri_spec->exclusive) { rv = nghttp2_stream_dep_insert_subtree(dep_stream, stream, - &session->ob_pq); + &session->ob_pq, + session->last_cycle); } else { rv = nghttp2_stream_dep_add_subtree(dep_stream, stream, - &session->ob_pq); + &session->ob_pq, + session->last_cycle); } } @@ -553,6 +563,8 @@ int nghttp2_session_add_frame(nghttp2_session *session, item->frame = abs_frame; item->aux_data = aux_data; item->seq = session->next_seq++; + /* We use cycle for DATA only */ + item->cycle = 0; item->weight = NGHTTP2_OB_EX_WEIGHT; item->queued = 0; @@ -630,8 +642,10 @@ int nghttp2_session_add_frame(nghttp2_session *session, rv = NGHTTP2_ERR_DATA_EXIST; } else { item->weight = stream->effective_weight; + item->cycle = session->last_cycle; - rv = nghttp2_stream_attach_data(stream, item, &session->ob_pq); + rv = nghttp2_stream_attach_data(stream, item, &session->ob_pq, + session->last_cycle); } } @@ -740,7 +754,7 @@ nghttp2_stream* nghttp2_session_open_stream(nghttp2_session *session, 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); + (stream, &session->ob_pq, session->last_cycle); /* Since no dpri is changed in dependency tree, the above function call never fail. */ @@ -796,7 +810,8 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id, item = stream->data_item; - rv = nghttp2_stream_detach_data(stream, &session->ob_pq); + rv = nghttp2_stream_detach_data(stream, &session->ob_pq, + session->last_cycle); if(rv != 0) { return rv; @@ -1755,7 +1770,8 @@ static int nghttp2_session_prep_frame(nghttp2_session *session, int rv2; if(stream) { - rv2 = nghttp2_stream_detach_data(stream, &session->ob_pq); + rv2 = nghttp2_stream_detach_data(stream, &session->ob_pq, + session->last_cycle); if(nghttp2_is_fatal(rv2)) { return rv2; @@ -1777,7 +1793,7 @@ static int nghttp2_session_prep_frame(nghttp2_session *session, rv = nghttp2_stream_defer_data(stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, - &session->ob_pq); + &session->ob_pq, session->last_cycle); if(nghttp2_is_fatal(rv)) { return rv; @@ -1793,7 +1809,7 @@ static int nghttp2_session_prep_frame(nghttp2_session *session, data_frame); if(framerv == NGHTTP2_ERR_DEFERRED) { rv = nghttp2_stream_defer_data(stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER, - &session->ob_pq); + &session->ob_pq, session->last_cycle); if(nghttp2_is_fatal(rv)) { return rv; @@ -1804,7 +1820,8 @@ static int nghttp2_session_prep_frame(nghttp2_session *session, return NGHTTP2_ERR_DEFERRED; } if(framerv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = nghttp2_stream_detach_data(stream, &session->ob_pq); + rv = nghttp2_stream_detach_data(stream, &session->ob_pq, + session->last_cycle); if(nghttp2_is_fatal(rv)) { return rv; @@ -1949,11 +1966,19 @@ static int session_call_on_frame_send(nghttp2_session *session, return 0; } -static void outbound_item_cycle_weight(nghttp2_outbound_item *item, - int32_t ini_weight) +static void session_outbound_item_cycle_weight(nghttp2_session *session, + nghttp2_outbound_item *item, + int32_t ini_weight) { if(item->weight == NGHTTP2_MIN_WEIGHT || item->weight > ini_weight) { + item->weight = ini_weight; + + if(item->cycle == session->last_cycle) { + item->cycle = ++session->last_cycle; + } else { + item->cycle = session->last_cycle; + } } else { --item->weight; } @@ -2144,7 +2169,8 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session) } if(stream && data_frame->eof) { - rv = nghttp2_stream_detach_data(stream, &session->ob_pq); + rv = nghttp2_stream_detach_data(stream, &session->ob_pq, + session->last_cycle); if(nghttp2_is_fatal(rv)) { return rv; @@ -2176,13 +2202,15 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session) assert(stream); next_item = nghttp2_session_get_next_ob_item(session); - outbound_item_cycle_weight(aob->item, stream->effective_weight); + session_outbound_item_cycle_weight(session, aob->item, + stream->effective_weight); /* If priority of this stream is higher or equal to other stream waiting at the top of the queue, we continue to send this data. */ if(stream->dpri == NGHTTP2_STREAM_DPRI_TOP && - (next_item == NULL || aob->item->weight > next_item->weight)) { + (next_item == NULL || + nghttp2_outbound_item_compar(item, next_item) < 0)) { size_t next_readmax; next_readmax = nghttp2_session_next_data_read(session, stream); @@ -2195,7 +2223,8 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session) } rv = nghttp2_stream_defer_data - (stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, &session->ob_pq); + (stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, &session->ob_pq, + session->last_cycle); if(nghttp2_is_fatal(rv)) { return rv; @@ -2217,7 +2246,7 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session) if(rv == NGHTTP2_ERR_DEFERRED) { rv = nghttp2_stream_defer_data(stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER, - &session->ob_pq); + &session->ob_pq, session->last_cycle); if(nghttp2_is_fatal(rv)) { return rv; @@ -2240,7 +2269,8 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session) return rv; } - rv = nghttp2_stream_detach_data(stream, &session->ob_pq); + rv = nghttp2_stream_detach_data(stream, &session->ob_pq, + session->last_cycle); if(nghttp2_is_fatal(rv)) { return rv; @@ -2254,9 +2284,6 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session) return 0; } - /* Update seq to interleave other streams with the same - priority. */ - aob->item->seq = session->next_seq++; if(stream->dpri == NGHTTP2_STREAM_DPRI_TOP) { rv = nghttp2_pq_push(&session->ob_pq, aob->item); @@ -3183,7 +3210,8 @@ static int nghttp2_update_remote_initial_window_size_func stream->remote_window_size > 0 && arg->session->remote_window_size > 0) { - rv = nghttp2_stream_resume_deferred_data(stream, &arg->session->ob_pq); + rv = nghttp2_stream_resume_deferred_data(stream, &arg->session->ob_pq, + arg->session->last_cycle); if(nghttp2_is_fatal(rv)) { return rv; @@ -3701,7 +3729,8 @@ static int nghttp2_push_back_deferred_data_func(nghttp2_map_entry *entry, if(nghttp2_stream_check_deferred_by_flow_control(stream) && stream->remote_window_size > 0) { - rv = nghttp2_stream_resume_deferred_data(stream, &session->ob_pq); + rv = nghttp2_stream_resume_deferred_data(stream, &session->ob_pq, + session->last_cycle); if(nghttp2_is_fatal(rv)) { return rv; @@ -3778,7 +3807,8 @@ static int session_on_stream_window_update_received session->remote_window_size > 0 && nghttp2_stream_check_deferred_by_flow_control(stream)) { - rv = nghttp2_stream_resume_deferred_data(stream, &session->ob_pq); + rv = nghttp2_stream_resume_deferred_data(stream, &session->ob_pq, + session->last_cycle); if(nghttp2_is_fatal(rv)) { return rv; @@ -5624,7 +5654,8 @@ int nghttp2_session_resume_data(nghttp2_session *session, int32_t stream_id) return NGHTTP2_ERR_INVALID_ARGUMENT; } - rv = nghttp2_stream_resume_deferred_data(stream, &session->ob_pq); + rv = nghttp2_stream_resume_deferred_data(stream, &session->ob_pq, + session->last_cycle); if(nghttp2_is_fatal(rv)) { return rv; diff --git a/lib/nghttp2_session.h b/lib/nghttp2_session.h index 16eecb22..74117e74 100644 --- a/lib/nghttp2_session.h +++ b/lib/nghttp2_session.h @@ -130,6 +130,20 @@ struct nghttp2_session { /* Sequence number of outbound frame to maintain the order of enqueue if priority is equal. */ int64_t next_seq; + /* Reset count of nghttp2_outbound_item's weight. We decrements + weight each time DATA is sent to simulate resource sharing. We + use priority queue and larger weight has the precedence. If + weight is reached to lowest weight, it resets to its initial + weight. If this happens, other items which have the lower weight + currently but same initial weight cannot send DATA until item + having large weight is decreased. To avoid this, we use this + cycle variable. Initally, this is set to 1. If weight gets + lowest weight, and if item's cycle == last_cycle, we increments + last_cycle and assigns it to item's cycle. Otherwise, just + assign last_cycle. In priority queue comparator, we first + compare items' cycle value. Lower cycle value has the + precedence. */ + uint64_t last_cycle; void *user_data; /* Points to the latest closed stream. NULL if there is no closed stream. Only used when session is initialized as server. */ diff --git a/lib/nghttp2_stream.c b/lib/nghttp2_stream.c index da20046e..34274eff 100644 --- a/lib/nghttp2_stream.c +++ b/lib/nghttp2_stream.c @@ -85,7 +85,8 @@ void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag) stream->shut_flags |= flag; } -static int stream_push_data(nghttp2_stream *stream, nghttp2_pq *pq) +static int stream_push_data(nghttp2_stream *stream, nghttp2_pq *pq, + uint64_t cycle) { int rv; @@ -96,6 +97,8 @@ static int stream_push_data(nghttp2_stream *stream, nghttp2_pq *pq) stream->data_item->weight = stream->effective_weight; } + stream->data_item->cycle = cycle; + rv = nghttp2_pq_push(pq, stream->data_item); if(rv != 0) { @@ -216,7 +219,8 @@ static void stream_update_dep_set_rest(nghttp2_stream *stream) * NGHTTP2_ERR_NOMEM * Out of memory. */ -static int stream_update_dep_set_top(nghttp2_stream *stream, nghttp2_pq *pq) +static int stream_update_dep_set_top(nghttp2_stream *stream, nghttp2_pq *pq, + uint64_t cycle) { int rv; nghttp2_stream *si; @@ -230,7 +234,7 @@ static int stream_update_dep_set_top(nghttp2_stream *stream, nghttp2_pq *pq) stream->stream_id)); if(!stream->data_item->queued) { - rv = stream_push_data(stream, pq); + rv = stream_push_data(stream, pq, cycle); if(rv != 0) { return rv; @@ -243,7 +247,7 @@ static int stream_update_dep_set_top(nghttp2_stream *stream, nghttp2_pq *pq) } for(si = stream->dep_next; si; si = si->sib_next) { - rv = stream_update_dep_set_top(si, pq); + rv = stream_update_dep_set_top(si, pq, cycle); if(rv != 0) { return rv; @@ -292,7 +296,7 @@ static int stream_update_dep_sum_norest_weight(nghttp2_stream *stream) } static int stream_update_dep_on_attach_data(nghttp2_stream *stream, - nghttp2_pq *pq) + nghttp2_pq *pq, uint64_t cycle) { int rv; nghttp2_stream *root_stream; @@ -305,7 +309,7 @@ static int stream_update_dep_on_attach_data(nghttp2_stream *stream, DEBUGF(fprintf(stderr, "root=%p, stream=%p\n", root_stream, stream)); - rv = stream_update_dep_set_top(root_stream, pq); + rv = stream_update_dep_set_top(root_stream, pq, cycle); if(rv != 0) { return rv; @@ -318,7 +322,7 @@ static int stream_update_dep_on_attach_data(nghttp2_stream *stream, } static int stream_update_dep_on_detach_data(nghttp2_stream *stream, - nghttp2_pq *pq) + nghttp2_pq *pq, uint64_t cycle) { int rv; nghttp2_stream *root_stream; @@ -327,7 +331,7 @@ static int stream_update_dep_on_detach_data(nghttp2_stream *stream, root_stream = nghttp2_stream_get_dep_root(stream); - rv = stream_update_dep_set_top(root_stream, pq); + rv = stream_update_dep_set_top(root_stream, pq, cycle); if(rv != 0) { return rv; @@ -341,7 +345,8 @@ static int stream_update_dep_on_detach_data(nghttp2_stream *stream, int nghttp2_stream_attach_data(nghttp2_stream *stream, nghttp2_outbound_item *data_item, - nghttp2_pq *pq) + nghttp2_pq *pq, + uint64_t cycle) { assert((stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0); assert(stream->data_item == NULL); @@ -351,10 +356,11 @@ int nghttp2_stream_attach_data(nghttp2_stream *stream, stream->data_item = data_item; - return stream_update_dep_on_attach_data(stream, pq); + return stream_update_dep_on_attach_data(stream, pq, cycle); } -int nghttp2_stream_detach_data(nghttp2_stream *stream, nghttp2_pq *pq) +int nghttp2_stream_detach_data(nghttp2_stream *stream, nghttp2_pq *pq, + uint64_t cycle) { DEBUGF(fprintf(stderr, "stream: stream=%d detach data=%p\n", stream->stream_id, stream->data_item)); @@ -362,11 +368,11 @@ int nghttp2_stream_detach_data(nghttp2_stream *stream, nghttp2_pq *pq) stream->data_item = NULL; stream->flags &= ~NGHTTP2_STREAM_FLAG_DEFERRED_ALL; - return stream_update_dep_on_detach_data(stream, pq); + return stream_update_dep_on_detach_data(stream, pq, cycle); } int nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags, - nghttp2_pq *pq) + nghttp2_pq *pq, uint64_t cycle) { assert(stream->data_item); @@ -375,11 +381,11 @@ int nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags, stream->flags |= flags; - return stream_update_dep_on_detach_data(stream, pq); + return stream_update_dep_on_detach_data(stream, pq, cycle); } int nghttp2_stream_resume_deferred_data(nghttp2_stream *stream, - nghttp2_pq *pq) + nghttp2_pq *pq, uint64_t cycle) { assert(stream->data_item); @@ -388,7 +394,7 @@ int nghttp2_stream_resume_deferred_data(nghttp2_stream *stream, stream->flags &= ~NGHTTP2_STREAM_FLAG_DEFERRED_ALL; - return stream_update_dep_on_attach_data(stream, pq); + return stream_update_dep_on_attach_data(stream, pq, cycle); } int nghttp2_stream_check_deferred_data(nghttp2_stream *stream) @@ -665,7 +671,8 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream) int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream, nghttp2_stream *stream, - nghttp2_pq *pq) + nghttp2_pq *pq, + uint64_t cycle) { nghttp2_stream *last_sib; nghttp2_stream *dep_next; @@ -717,7 +724,7 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream, root_stream = stream_update_dep_length(dep_stream, delta_substreams); - rv = stream_update_dep_set_top(root_stream, pq); + rv = stream_update_dep_set_top(root_stream, pq, cycle); if(rv != 0) { return rv; @@ -731,7 +738,8 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream, int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream, nghttp2_stream *stream, - nghttp2_pq *pq) + nghttp2_pq *pq, + uint64_t cycle) { nghttp2_stream *last_sib; nghttp2_stream *root_stream; @@ -761,7 +769,7 @@ int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream, root_stream = stream_update_dep_length(dep_stream, stream->num_substreams); - rv = stream_update_dep_set_top(root_stream, pq); + rv = stream_update_dep_set_top(root_stream, pq, cycle); if(rv != 0) { return rv; @@ -824,7 +832,8 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream) stream->dep_prev = NULL; } -int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq) +int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq, + uint64_t cycle) { int rv; @@ -837,7 +846,7 @@ int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq) stream->effective_weight = stream->weight; - rv = stream_update_dep_set_top(stream, pq); + rv = stream_update_dep_set_top(stream, pq, cycle); if(rv != 0) { return rv; @@ -850,7 +859,7 @@ int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq) } int nghttp2_stream_dep_all_your_stream_are_belong_to_us -(nghttp2_stream *stream, nghttp2_pq *pq) +(nghttp2_stream *stream, nghttp2_pq *pq, uint64_t cycle) { nghttp2_stream *first, *si; @@ -905,7 +914,7 @@ int nghttp2_stream_dep_all_your_stream_are_belong_to_us nghttp2_stream_roots_remove_all(stream->roots); - return nghttp2_stream_dep_make_root(stream, pq); + return nghttp2_stream_dep_make_root(stream, pq, cycle); } int nghttp2_stream_in_dep_tree(nghttp2_stream *stream) diff --git a/lib/nghttp2_stream.h b/lib/nghttp2_stream.h index 256510e2..5b2d0e45 100644 --- a/lib/nghttp2_stream.h +++ b/lib/nghttp2_stream.h @@ -209,7 +209,7 @@ void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag); * Out of memory */ int nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags, - nghttp2_pq *pq); + nghttp2_pq *pq, uint64_t cycle); /* * Detaches deferred data in this stream and it is back to active @@ -218,7 +218,7 @@ int nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags, * set. */ int nghttp2_stream_resume_deferred_data(nghttp2_stream *stream, - nghttp2_pq *pq); + nghttp2_pq *pq, uint64_t cycle); /* * Returns nonzero if data item is deferred by whatever reason. @@ -329,7 +329,8 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream); */ int nghttp2_stream_attach_data(nghttp2_stream *stream, nghttp2_outbound_item *data_item, - nghttp2_pq *pq); + nghttp2_pq *pq, + uint64_t cycle); /* * Detaches |stream->data_item|. Updates dpri members in this @@ -342,7 +343,8 @@ int nghttp2_stream_attach_data(nghttp2_stream *stream, * NGHTTP2_ERR_NOMEM * Out of memory */ -int nghttp2_stream_detach_data(nghttp2_stream *stream, nghttp2_pq *pq); +int nghttp2_stream_detach_data(nghttp2_stream *stream, nghttp2_pq *pq, + uint64_t cycle); /* @@ -357,7 +359,8 @@ int nghttp2_stream_detach_data(nghttp2_stream *stream, nghttp2_pq *pq); */ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream, nghttp2_stream *stream, - nghttp2_pq *pq); + nghttp2_pq *pq, + uint64_t cycle); /* * Makes the |stream| depend on the |dep_stream|. This dependency is @@ -371,7 +374,8 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream, */ int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream, nghttp2_stream *stream, - nghttp2_pq *pq); + nghttp2_pq *pq, + uint64_t cycle); /* * Removes subtree whose root stream is |stream|. Removing subtree @@ -396,7 +400,8 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream); * NGHTTP2_ERR_NOMEM * Out of memory */ -int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq); +int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq, + uint64_t cycle); /* * Makes the |stream| as root and all existing root streams become @@ -409,7 +414,7 @@ int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq); * Out of memory */ int nghttp2_stream_dep_all_your_stream_are_belong_to_us -(nghttp2_stream *stream, nghttp2_pq *pq); +(nghttp2_stream *stream, nghttp2_pq *pq, uint64_t cycle); /* * Returns nonzero if |stream| is in any dependency tree. diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c index 7e5fb472..ad9aaa7c 100644 --- a/tests/nghttp2_session_test.c +++ b/tests/nghttp2_session_test.c @@ -2222,7 +2222,8 @@ void test_nghttp2_session_on_window_update_received(void) data_item->frame_cat = NGHTTP2_CAT_DATA; CU_ASSERT(0 == nghttp2_stream_attach_data(stream, data_item, - &session->ob_pq)); + &session->ob_pq, + session->last_cycle)); nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1, 16*1024); @@ -2233,7 +2234,7 @@ void test_nghttp2_session_on_window_update_received(void) CU_ASSERT(0 == nghttp2_stream_defer_data (stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, - &session->ob_pq)); + &session->ob_pq, session->last_cycle)); CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame)); CU_ASSERT(2 == user_data.frame_recv_cb_called); @@ -5270,7 +5271,7 @@ void test_nghttp2_session_stream_dep_add_subtree(void) * d */ - nghttp2_stream_dep_add_subtree(a, e, &session->ob_pq); + nghttp2_stream_dep_add_subtree(a, e, &session->ob_pq, session->last_cycle); /* becomes * a @@ -5321,7 +5322,7 @@ void test_nghttp2_session_stream_dep_add_subtree(void) * d */ - nghttp2_stream_dep_insert_subtree(a, e, &session->ob_pq); + nghttp2_stream_dep_insert_subtree(a, e, &session->ob_pq, session->last_cycle); /* becomes * a @@ -5514,7 +5515,7 @@ void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) nghttp2_stream_dep_remove_subtree(c); CU_ASSERT(0 == nghttp2_stream_dep_all_your_stream_are_belong_to_us - (c, &session->ob_pq)); + (c, &session->ob_pq, session->last_cycle)); /* * c @@ -5552,7 +5553,7 @@ void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) nghttp2_stream_dep_remove_subtree(c); CU_ASSERT(0 == nghttp2_stream_dep_all_your_stream_are_belong_to_us - (c, &session->ob_pq)); + (c, &session->ob_pq, session->last_cycle)); /* * c @@ -5589,7 +5590,7 @@ void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) nghttp2_stream_dep_remove_subtree(c); CU_ASSERT(0 == nghttp2_stream_dep_all_your_stream_are_belong_to_us - (c, &session->ob_pq)); + (c, &session->ob_pq, session->last_cycle)); /* * c @@ -5642,7 +5643,7 @@ void test_nghttp2_session_stream_attach_data(void) db = create_data_ob_item(); - nghttp2_stream_attach_data(b, db, &session->ob_pq); + nghttp2_stream_attach_data(b, db, &session->ob_pq, session->last_cycle); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); @@ -5657,7 +5658,7 @@ void test_nghttp2_session_stream_attach_data(void) dc = create_data_ob_item(); - nghttp2_stream_attach_data(c, dc, &session->ob_pq); + nghttp2_stream_attach_data(c, dc, &session->ob_pq, session->last_cycle); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); @@ -5673,7 +5674,7 @@ void test_nghttp2_session_stream_attach_data(void) da = create_data_ob_item(); - nghttp2_stream_attach_data(a, da, &session->ob_pq); + nghttp2_stream_attach_data(a, da, &session->ob_pq, session->last_cycle); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == b->dpri); @@ -5684,7 +5685,7 @@ void test_nghttp2_session_stream_attach_data(void) CU_ASSERT(1 == da->queued); - nghttp2_stream_detach_data(a, &session->ob_pq); + nghttp2_stream_detach_data(a, &session->ob_pq, session->last_cycle); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); @@ -5696,7 +5697,7 @@ void test_nghttp2_session_stream_attach_data(void) dd = create_data_ob_item(); - nghttp2_stream_attach_data(d, dd, &session->ob_pq); + nghttp2_stream_attach_data(d, dd, &session->ob_pq, session->last_cycle); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); @@ -5708,7 +5709,7 @@ void test_nghttp2_session_stream_attach_data(void) CU_ASSERT(0 == dd->queued); - nghttp2_stream_detach_data(c, &session->ob_pq); + nghttp2_stream_detach_data(c, &session->ob_pq, session->last_cycle); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); @@ -5751,11 +5752,11 @@ void test_nghttp2_session_stream_attach_data_subtree(void) de = create_data_ob_item(); - nghttp2_stream_attach_data(e, de, &session->ob_pq); + nghttp2_stream_attach_data(e, de, &session->ob_pq, session->last_cycle); db = create_data_ob_item(); - nghttp2_stream_attach_data(b, db, &session->ob_pq); + nghttp2_stream_attach_data(b, db, &session->ob_pq, session->last_cycle); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); @@ -5770,7 +5771,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); + nghttp2_stream_dep_insert_subtree(a, e, &session->ob_pq, session->last_cycle); /* * a @@ -5795,7 +5796,7 @@ void test_nghttp2_session_stream_attach_data_subtree(void) nghttp2_stream_dep_remove_subtree(b); - nghttp2_stream_dep_make_root(b, &session->ob_pq); + nghttp2_stream_dep_make_root(b, &session->ob_pq, session->last_cycle); /* * a b @@ -5821,7 +5822,7 @@ void test_nghttp2_session_stream_attach_data_subtree(void) nghttp2_stream_dep_remove_subtree(a); - nghttp2_stream_dep_make_root(a, &session->ob_pq); + nghttp2_stream_dep_make_root(a, &session->ob_pq, session->last_cycle); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); @@ -5834,7 +5835,7 @@ void test_nghttp2_session_stream_attach_data_subtree(void) nghttp2_stream_dep_remove_subtree(c); - nghttp2_stream_dep_make_root(c, &session->ob_pq); + nghttp2_stream_dep_make_root(c, &session->ob_pq, session->last_cycle); /* * a b c @@ -5853,12 +5854,12 @@ void test_nghttp2_session_stream_attach_data_subtree(void) dd = create_data_ob_item(); - nghttp2_stream_attach_data(d, dd, &session->ob_pq); + nghttp2_stream_attach_data(d, dd, &session->ob_pq, session->last_cycle); /* Add subtree c to a */ nghttp2_stream_dep_remove_subtree(c); - nghttp2_stream_dep_add_subtree(a, c, &session->ob_pq); + nghttp2_stream_dep_add_subtree(a, c, &session->ob_pq, session->last_cycle); /* * a b @@ -5885,7 +5886,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); + nghttp2_stream_dep_insert_subtree(a, b, &session->ob_pq, session->last_cycle); /* * a @@ -5912,7 +5913,7 @@ void test_nghttp2_session_stream_attach_data_subtree(void) /* Remove subtree b */ nghttp2_stream_dep_remove_subtree(b); - nghttp2_stream_dep_make_root(b, &session->ob_pq); + nghttp2_stream_dep_make_root(b, &session->ob_pq, session->last_cycle); /* * b a