Commit 3e3d5184 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

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.
parent b041218a
......@@ -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:
......
This diff is collapsed.
......@@ -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. */
......
......@@ -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)
......
......@@ -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.
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment