You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ic...@apache.org on 2015/10/28 16:53:07 UTC
svn commit: r1711044 - in /httpd/httpd/trunk/modules/http2: h2_io.h
h2_mplx.c h2_mplx.h h2_session.c h2_session.h h2_stream.c h2_stream.h
h2_task.c h2_task.h h2_task_queue.c h2_task_queue.h h2_version.h
Author: icing
Date: Wed Oct 28 15:53:07 2015
New Revision: 1711044
URL: http://svn.apache.org/viewvc?rev=1711044&view=rev
Log:
http2 priority based scheduling of stream execution in each session
Modified:
httpd/httpd/trunk/modules/http2/h2_io.h
httpd/httpd/trunk/modules/http2/h2_mplx.c
httpd/httpd/trunk/modules/http2/h2_mplx.h
httpd/httpd/trunk/modules/http2/h2_session.c
httpd/httpd/trunk/modules/http2/h2_session.h
httpd/httpd/trunk/modules/http2/h2_stream.c
httpd/httpd/trunk/modules/http2/h2_stream.h
httpd/httpd/trunk/modules/http2/h2_task.c
httpd/httpd/trunk/modules/http2/h2_task.h
httpd/httpd/trunk/modules/http2/h2_task_queue.c
httpd/httpd/trunk/modules/http2/h2_task_queue.h
httpd/httpd/trunk/modules/http2/h2_version.h
Modified: httpd/httpd/trunk/modules/http2/h2_io.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_io.h?rev=1711044&r1=1711043&r2=1711044&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_io.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_io.h Wed Oct 28 15:53:07 2015
@@ -21,8 +21,9 @@ struct apr_thread_cond_t;
struct h2_task;
-typedef apr_status_t h2_io_data_cb(void *ctx,
- const char *data, apr_size_t len);
+typedef apr_status_t h2_io_data_cb(void *ctx, const char *data, apr_size_t len);
+
+typedef int h2_stream_pri_cmp(int stream_id1, int stream_id2, void *ctx);
typedef struct h2_io h2_io;
Modified: httpd/httpd/trunk/modules/http2/h2_mplx.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_mplx.c?rev=1711044&r1=1711043&r2=1711044&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_mplx.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_mplx.c Wed Oct 28 15:53:07 2015
@@ -128,7 +128,7 @@ h2_mplx *h2_mplx_create(conn_rec *c, apr
m->bucket_alloc = apr_bucket_alloc_create(m->pool);
- m->q = h2_tq_create(m->id, m->pool);
+ m->q = h2_tq_create(m->pool, 23);
m->stream_ios = h2_io_set_create(m->pool);
m->ready_ios = h2_io_set_create(m->pool);
m->closed = h2_stream_set_create(m->pool);
@@ -812,19 +812,60 @@ static void have_out_data_for(h2_mplx *m
}
}
-apr_status_t h2_mplx_do_task(h2_mplx *m, struct h2_task *task)
+typedef struct {
+ h2_stream_pri_cmp *cmp;
+ void *ctx;
+} cmp_ctx;
+
+static int task_cmp(h2_task *t1, h2_task *t2, void *ctx)
+{
+ cmp_ctx *x = ctx;
+ return x->cmp(t1->stream_id, t2->stream_id, x->ctx);
+}
+
+apr_status_t h2_mplx_reprioritize(h2_mplx *m, h2_stream_pri_cmp *cmp, void *ctx)
+{
+ apr_status_t status;
+
+ AP_DEBUG_ASSERT(m);
+ if (m->aborted) {
+ return APR_ECONNABORTED;
+ }
+ status = apr_thread_mutex_lock(m->lock);
+ if (APR_SUCCESS == status) {
+ cmp_ctx x;
+
+ x.cmp = cmp;
+ x.ctx = ctx;
+ h2_tq_sort(m->q, task_cmp, &x);
+
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
+ "h2_mplx(%ld): reprioritize tasks", m->id);
+ apr_thread_mutex_unlock(m->lock);
+ }
+ workers_register(m);
+ return status;
+}
+
+apr_status_t h2_mplx_do_task(h2_mplx *m, struct h2_task *task,
+ h2_stream_pri_cmp *cmp, void *ctx)
{
apr_status_t status;
+
AP_DEBUG_ASSERT(m);
if (m->aborted) {
return APR_ECONNABORTED;
}
status = apr_thread_mutex_lock(m->lock);
if (APR_SUCCESS == status) {
- /* TODO: needs to sort queue by priority */
+ cmp_ctx x;
+
+ x.cmp = cmp;
+ x.ctx = ctx;
+ h2_tq_add(m->q, task, task_cmp, &x);
+
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c,
"h2_mplx: do task(%s)", task->id);
- h2_tq_append(m->q, task);
apr_thread_mutex_unlock(m->lock);
}
workers_register(m);
@@ -842,7 +883,7 @@ h2_task *h2_mplx_pop_task(h2_mplx *m, in
}
status = apr_thread_mutex_lock(m->lock);
if (APR_SUCCESS == status) {
- task = h2_tq_pop_first(m->q);
+ task = h2_tq_shift(m->q);
if (task) {
h2_task_set_started(task);
}
Modified: httpd/httpd/trunk/modules/http2/h2_mplx.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_mplx.h?rev=1711044&r1=1711043&r2=1711044&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_mplx.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_mplx.h Wed Oct 28 15:53:07 2015
@@ -76,6 +76,8 @@ struct h2_mplx {
int file_handles_allowed;
};
+
+
/*******************************************************************************
* Object lifecycle and information.
******************************************************************************/
@@ -144,9 +146,24 @@ apr_status_t h2_mplx_out_trywait(h2_mplx
******************************************************************************/
/**
- * Perform the task on the given stream.
+ * Schedule a task for execution.
+ *
+ * @param m the multiplexer
+ * @param task the task to schedule
+ * @param cmp the stream priority compare function
+ * @param ctx context data for the compare function
+ */
+apr_status_t h2_mplx_do_task(h2_mplx *m, struct h2_task *task,
+ h2_stream_pri_cmp *cmp, void *ctx);
+
+/**
+ * Stream priorities have changed, reschedule pending tasks.
+ *
+ * @param m the multiplexer
+ * @param cmp the stream priority compare function
+ * @param ctx context data for the compare function
*/
-apr_status_t h2_mplx_do_task(h2_mplx *mplx, struct h2_task *task);
+apr_status_t h2_mplx_reprioritize(h2_mplx *m, h2_stream_pri_cmp *cmp, void *ctx);
struct h2_task *h2_mplx_pop_task(h2_mplx *mplx, int *has_more);
Modified: httpd/httpd/trunk/modules/http2/h2_session.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_session.c?rev=1711044&r1=1711043&r2=1711044&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_session.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_session.c Wed Oct 28 15:53:07 2015
@@ -81,11 +81,64 @@ static int stream_open(h2_session *sessi
return NGHTTP2_ERR_INVALID_STREAM_ID;
}
+/**
+ * Determine the importance of streams when scheduling tasks.
+ * - if both stream depend on the same one, compare weights
+ * - if one stream is closer to the root, prioritize that one
+ * - if both are on the same level, use the weight of their root
+ * level ancestors
+ */
+static int spri_cmp(int sid1, nghttp2_stream *s1,
+ int sid2, nghttp2_stream *s2, h2_session *session)
+{
+ nghttp2_stream *p1, *p2;
+
+ p1 = nghttp2_stream_get_parent(s1);
+ p2 = nghttp2_stream_get_parent(s2);
+
+ if (p1 == p2) {
+ int32_t w1, w2;
+
+ w1 = nghttp2_stream_get_weight(s1);
+ w2 = nghttp2_stream_get_weight(s2);
+ return w2 - w1;
+ }
+ else if (!p1) {
+ /* stream 1 closer to root */
+ return -1;
+ }
+ else if (!p2) {
+ /* stream 2 closer to root */
+ return 1;
+ }
+ return spri_cmp(sid1, p1, sid2, p2, session);
+}
+
+static int stream_pri_cmp(int sid1, int sid2, void *ctx)
+{
+ h2_session *session = ctx;
+ nghttp2_stream *s1, *s2;
+
+ s1 = nghttp2_session_find_stream(session->ngh2, sid1);
+ s2 = nghttp2_session_find_stream(session->ngh2, sid2);
+
+ if (s1 == s2) {
+ return 0;
+ }
+ else if (!s1) {
+ return 1;
+ }
+ else if (!s2) {
+ return -1;
+ }
+ return spri_cmp(sid1, s1, sid2, s2, session);
+}
+
static apr_status_t stream_end_headers(h2_session *session,
h2_stream *stream, int eos)
{
(void)session;
- return h2_stream_write_eoh(stream, eos);
+ return h2_stream_schedule(stream, eos, stream_pri_cmp, session);
}
static apr_status_t send_data(h2_session *session, const char *data,
@@ -409,6 +462,7 @@ static int on_frame_recv_cb(nghttp2_sess
break;
}
case NGHTTP2_PRIORITY: {
+ session->reprioritize = 1;
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c,
"h2_session: stream(%ld-%d): PRIORITY frame "
" weight=%d, dependsOn=%d, exclusive=%d",
@@ -932,6 +986,10 @@ apr_status_t h2_session_write(h2_session
AP_DEBUG_ASSERT(session);
+ if (session->reprioritize) {
+ h2_mplx_reprioritize(session->mplx, stream_pri_cmp, session);
+ }
+
/* Check that any pending window updates are sent. */
status = h2_session_update_windows(session);
if (status != APR_SUCCESS && !APR_STATUS_IS_EAGAIN(status)) {
Modified: httpd/httpd/trunk/modules/http2/h2_session.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_session.h?rev=1711044&r1=1711043&r2=1711044&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_session.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_session.h Wed Oct 28 15:53:07 2015
@@ -59,6 +59,8 @@ struct h2_session {
* of 'h2c', NULL otherwise */
int aborted; /* this session is being aborted */
int flush; /* if != 0, flush output on next occasion */
+ int reprioritize; /* scheduled streams priority needs to
+ * be re-evaluated */
apr_size_t frames_received; /* number of http/2 frames received */
apr_size_t max_stream_count; /* max number of open streams */
apr_size_t max_stream_mem; /* max buffer memory for a single stream */
Modified: httpd/httpd/trunk/modules/http2/h2_stream.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_stream.c?rev=1711044&r1=1711043&r2=1711044&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_stream.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_stream.c Wed Oct 28 15:53:07 2015
@@ -160,7 +160,8 @@ apr_status_t h2_stream_rwrite(h2_stream
return status;
}
-apr_status_t h2_stream_write_eoh(h2_stream *stream, int eos)
+apr_status_t h2_stream_schedule(h2_stream *stream, int eos,
+ h2_stream_pri_cmp *cmp, void *ctx)
{
apr_status_t status;
AP_DEBUG_ASSERT(stream);
@@ -176,7 +177,7 @@ apr_status_t h2_stream_write_eoh(h2_stre
status = h2_request_end_headers(stream->request,
stream->m, stream->task, eos);
if (status == APR_SUCCESS) {
- status = h2_mplx_do_task(stream->m, stream->task);
+ status = h2_mplx_do_task(stream->m, stream->task, cmp, ctx);
}
if (eos) {
status = h2_stream_write_eos(stream);
Modified: httpd/httpd/trunk/modules/http2/h2_stream.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_stream.h?rev=1711044&r1=1711043&r2=1711044&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_stream.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_stream.h Wed Oct 28 15:53:07 2015
@@ -88,7 +88,8 @@ apr_status_t h2_stream_write_header(h2_s
const char *name, size_t nlen,
const char *value, size_t vlen);
-apr_status_t h2_stream_write_eoh(h2_stream *stream, int eos);
+apr_status_t h2_stream_schedule(h2_stream *stream, int eos,
+ h2_stream_pri_cmp *cmp, void *ctx);
apr_status_t h2_stream_write_data(h2_stream *stream,
const char *data, size_t len);
Modified: httpd/httpd/trunk/modules/http2/h2_task.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_task.c?rev=1711044&r1=1711043&r2=1711044&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_task.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_task.c Wed Oct 28 15:53:07 2015
@@ -164,8 +164,6 @@ h2_task *h2_task_create(long session_id,
return NULL;
}
- APR_RING_ELEM_INIT(task, link);
-
task->id = apr_psprintf(stream_pool, "%ld-%d", session_id, stream_id);
task->stream_id = stream_id;
task->mplx = mplx;
Modified: httpd/httpd/trunk/modules/http2/h2_task.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_task.h?rev=1711044&r1=1711043&r2=1711044&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_task.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_task.h Wed Oct 28 15:53:07 2015
@@ -45,9 +45,6 @@ struct h2_worker;
typedef struct h2_task h2_task;
struct h2_task {
- /** Links to the rest of the tasks */
- APR_RING_ENTRY(h2_task) link;
-
const char *id;
int stream_id;
struct h2_mplx *mplx;
@@ -91,74 +88,6 @@ struct h2_task_env {
struct apr_thread_cond_t *io; /* used to wait for events on */
};
-/**
- * The magic pointer value that indicates the head of a h2_task list
- * @param b The task list
- * @return The magic pointer value
- */
-#define H2_TASK_LIST_SENTINEL(b) APR_RING_SENTINEL((b), h2_task, link)
-
-/**
- * Determine if the task list is empty
- * @param b The list to check
- * @return true or false
- */
-#define H2_TASK_LIST_EMPTY(b) APR_RING_EMPTY((b), h2_task, link)
-
-/**
- * Return the first task in a list
- * @param b The list to query
- * @return The first task in the list
- */
-#define H2_TASK_LIST_FIRST(b) APR_RING_FIRST(b)
-
-/**
- * Return the last task in a list
- * @param b The list to query
- * @return The last task int he list
- */
-#define H2_TASK_LIST_LAST(b) APR_RING_LAST(b)
-
-/**
- * Insert a single task at the front of a list
- * @param b The list to add to
- * @param e The task to insert
- */
-#define H2_TASK_LIST_INSERT_HEAD(b, e) do { \
- h2_task *ap__b = (e); \
- APR_RING_INSERT_HEAD((b), ap__b, h2_task, link); \
-} while (0)
-
-/**
- * Insert a single task at the end of a list
- * @param b The list to add to
- * @param e The task to insert
- */
-#define H2_TASK_LIST_INSERT_TAIL(b, e) do { \
- h2_task *ap__b = (e); \
- APR_RING_INSERT_TAIL((b), ap__b, h2_task, link); \
-} while (0)
-
-/**
- * Get the next task in the list
- * @param e The current task
- * @return The next task
- */
-#define H2_TASK_NEXT(e) APR_RING_NEXT((e), link)
-/**
- * Get the previous task in the list
- * @param e The current task
- * @return The previous task
- */
-#define H2_TASK_PREV(e) APR_RING_PREV((e), link)
-
-/**
- * Remove a task from its list
- * @param e The task to remove
- */
-#define H2_TASK_REMOVE(e) APR_RING_REMOVE((e), link)
-
-
h2_task *h2_task_create(long session_id, int stream_id,
apr_pool_t *pool, struct h2_mplx *mplx,
conn_rec *c);
Modified: httpd/httpd/trunk/modules/http2/h2_task_queue.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_task_queue.c?rev=1711044&r1=1711043&r2=1711044&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_task_queue.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_task_queue.c Wed Oct 28 15:53:07 2015
@@ -23,66 +23,139 @@
#include "h2_task_queue.h"
-h2_task_queue *h2_tq_create(long id, apr_pool_t *pool)
+static void grow(h2_task_queue *q, int nlen);
+static h2_task *qrm(h2_task_queue *q, int index);
+static void tqsort(h2_task_queue *q, int left, int right,
+ h2_tq_cmp *cmp, void *ctx);
+
+h2_task_queue *h2_tq_create(apr_pool_t *pool, int capacity)
{
h2_task_queue *q = apr_pcalloc(pool, sizeof(h2_task_queue));
if (q) {
- q->id = id;
- APR_RING_ELEM_INIT(q, link);
- APR_RING_INIT(&q->tasks, h2_task, link);
+ q->pool = pool;
+ grow(q, capacity);
+ q->nelts = 0;
}
return q;
}
void h2_tq_destroy(h2_task_queue *q)
{
- while (!H2_TASK_LIST_EMPTY(&q->tasks)) {
- h2_task *task = H2_TASK_LIST_FIRST(&q->tasks);
- H2_TASK_REMOVE(task);
+}
+
+int h2_tq_empty(h2_task_queue *q)
+{
+ return q->nelts == 0;
+}
+
+void h2_tq_add(h2_task_queue *q, struct h2_task *task,
+ h2_tq_cmp *cmp, void *ctx)
+{
+ int i;
+
+ if (q->nelts >= q->nalloc) {
+ grow(q, q->nalloc * 2);
}
+
+ /* Assume tasks most commonly arrive in ascending order */
+ for (i = q->nelts; i > 0; --i) {
+ if (cmp(q->elts[i-1], task, ctx) <= 0) {
+ if (i < q->nelts) {
+ memmove(q->elts+i+1, q->elts+i, q->nelts - i);
+ }
+ q->elts[i] = task;
+ q->nelts++;
+ return;
+ }
+ }
+ /* insert at front */
+ if (q->nelts) {
+ memmove(q->elts+1, q->elts, q->nelts);
+ }
+ q->elts[q->nelts++] = task;
}
-static int in_list(h2_task_queue *q, h2_task *task)
+void h2_tq_sort(h2_task_queue *q, h2_tq_cmp *cmp, void *ctx)
+{
+ tqsort(q, 0, q->nelts - 1, cmp, ctx);
+}
+
+
+apr_status_t h2_tq_remove(h2_task_queue *q, struct h2_task *task)
{
- h2_task *e;
- for (e = H2_TASK_LIST_FIRST(&q->tasks);
- e != H2_TASK_LIST_SENTINEL(&q->tasks);
- e = H2_TASK_NEXT(e)) {
- if (e == task) {
- return 1;
+ int i;
+
+ for (i = 0; i < q->nelts; ++i) {
+ if (task == q->elts[i]) {
+ qrm(q, i);
+ return APR_SUCCESS;
}
}
- return 0;
+ return APR_NOTFOUND;
}
-int h2_tq_empty(h2_task_queue *q)
+h2_task *h2_tq_shift(h2_task_queue *q)
{
- return H2_TASK_LIST_EMPTY(&q->tasks);
+ return qrm(q, 0);
}
-void h2_tq_append(h2_task_queue *q, struct h2_task *task)
+static void grow(h2_task_queue *q, int nlen)
{
- H2_TASK_LIST_INSERT_TAIL(&q->tasks, task);
+ AP_DEBUG_ASSERT(q->nalloc <= nlen);
+ if (nlen > q->nalloc) {
+ h2_task **nq = apr_pcalloc(q->pool, sizeof(h2_task *) * nlen);
+ if (q->nelts > 0) {
+ memmove(nq, q->elts, sizeof(h2_task *) * q->nelts);
+ }
+ q->elts = nq;
+ q->nalloc = nlen;
+ }
}
-apr_status_t h2_tq_remove(h2_task_queue *q, struct h2_task *task)
+static h2_task *qrm(h2_task_queue *q, int index)
{
- if (in_list(q, task)) {
- H2_TASK_REMOVE(task);
- return APR_SUCCESS;
+ if (index >= q->nelts) {
+ return NULL;
}
- return APR_NOTFOUND;
+ else if (index == q->nelts - 1) {
+ q->nelts--;
+ return q->elts[index];
+ }
+ else {
+ h2_task *t = q->elts[index];
+ q->nelts--;
+ memmove(q->elts+index, q->elts+index+1,
+ sizeof(q->elts[0]) * (q->nelts - index));
+ return t;
+ }
+}
+
+static void tqswap(h2_task_queue *q, int i, int j)
+{
+ h2_task *t = q->elts[i];
+ q->elts[i] = q->elts[j];
+ q->elts[j] = t;
}
-h2_task *h2_tq_pop_first(h2_task_queue *q)
+static void tqsort(h2_task_queue *q, int left, int right,
+ h2_tq_cmp *cmp, void *ctx)
{
- if (!H2_TASK_LIST_EMPTY(&q->tasks)) {
- h2_task *task = H2_TASK_LIST_FIRST(&q->tasks);
- H2_TASK_REMOVE(task);
- return task;
+ int i, last;
+
+ if (left >= right)
+ return;
+ tqswap(q, left, (left + right)/2);
+ last = left;
+ for (i = left+1; i <= right; i++) {
+ if ((*cmp)(q->elts[i], q->elts[left], ctx) < 0) {
+ tqswap(q, ++last, i);
+ }
}
- return NULL;
+ tqswap(q, left, last);
+ tqsort(q, left, last-1, cmp, ctx);
+ tqsort(q, last+1, right, cmp, ctx);
}
+
Modified: httpd/httpd/trunk/modules/http2/h2_task_queue.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_task_queue.h?rev=1711044&r1=1711043&r2=1711044&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_task_queue.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_task_queue.h Wed Oct 28 15:53:07 2015
@@ -25,9 +25,10 @@ struct h2_task;
typedef struct h2_task_queue h2_task_queue;
struct h2_task_queue {
- APR_RING_ENTRY(h2_task_queue) link;
- APR_RING_HEAD(h2_tasks, h2_task) tasks;
- long id;
+ apr_pool_t *pool;
+ struct h2_task **elts;
+ int nelts;
+ int nalloc;
};
/**
@@ -35,7 +36,7 @@ struct h2_task_queue {
* @param id the identifier of the queue
* @param pool the memory pool
*/
-h2_task_queue *h2_tq_create(long id, apr_pool_t *pool);
+h2_task_queue *h2_tq_create(apr_pool_t *pool, int capacity);
/**
* Release all queue tasks.
@@ -49,12 +50,29 @@ void h2_tq_destroy(h2_task_queue *q);
*/
int h2_tq_empty(h2_task_queue *q);
+typedef int h2_tq_cmp(struct h2_task *t1, struct h2_task *t2, void *ctx);
+
/**
- * Append the task to the end of the queue.
+ * Add the task to the sorted queue. For optimiztation, it is assumed
+ * that the order of the existing tasks has not changed.
+ *
* @param q the queue to append the task to
- * @param task the task to append
- */
-void h2_tq_append(h2_task_queue *q, struct h2_task *task);
+ * @param task the task to add
+ * @param cmp the compare function for sorting
+ * @param ctx user data for the compare function
+ */
+void h2_tq_add(h2_task_queue *q, struct h2_task *task,
+ h2_tq_cmp *cmp, void *ctx);
+
+/**
+ * Sort the tasks queue again. Useful to call if the task order
+ * has changed.
+ *
+ * @param q the queue to sort
+ * @param cmp the compare function for sorting
+ * @param ctx user data for the compare function
+ */
+void h2_tq_sort(h2_task_queue *q, h2_tq_cmp *cmp, void *ctx);
/**
* Remove a task from the queue. Return APR_SUCCESS if the task
@@ -65,84 +83,10 @@ void h2_tq_append(h2_task_queue *q, stru
apr_status_t h2_tq_remove(h2_task_queue *q, struct h2_task *task);
/**
- * Get the first task from the queue or NULL if the queue is empty. The
- * task will be removed.
- * @param q the queue to pop the first task from
- */
-h2_task *h2_tq_pop_first(h2_task_queue *q);
-
-/*******************************************************************************
- * Queue Manipulation.
- ******************************************************************************/
-
-/**
- * The magic pointer value that indicates the head of a h2_task_queue list
- * @param b The queue list
- * @return The magic pointer value
- */
-#define H2_TQ_LIST_SENTINEL(b) APR_RING_SENTINEL((b), h2_task_queue, link)
-
-/**
- * Determine if the queue list is empty
- * @param b The list to check
- * @return true or false
- */
-#define H2_TQ_LIST_EMPTY(b) APR_RING_EMPTY((b), h2_task_queue, link)
-
-/**
- * Return the first queue in a list
- * @param b The list to query
- * @return The first queue in the list
+ * Get the first task from the queue or NULL if the queue is empty.
+ * The task will be removed.
+ * @param q the queue to get the first task from
*/
-#define H2_TQ_LIST_FIRST(b) APR_RING_FIRST(b)
-
-/**
- * Return the last queue in a list
- * @param b The list to query
- * @return The last queue int he list
- */
-#define H2_TQ_LIST_LAST(b) APR_RING_LAST(b)
-
-/**
- * Insert a single queue at the front of a list
- * @param b The list to add to
- * @param e The queue to insert
- */
-#define H2_TQ_LIST_INSERT_HEAD(b, e) do { \
-h2_task_queue *ap__b = (e); \
-APR_RING_INSERT_HEAD((b), ap__b, h2_task_queue, link); \
-} while (0)
-
-/**
- * Insert a single queue at the end of a list
- * @param b The list to add to
- * @param e The queue to insert
- */
-#define H2_TQ_LIST_INSERT_TAIL(b, e) do { \
-h2_task_queue *ap__b = (e); \
-APR_RING_INSERT_TAIL((b), ap__b, h2_task_queue, link); \
-} while (0)
-
-/**
- * Get the next queue in the list
- * @param e The current queue
- * @return The next queue
- */
-#define H2_TQ_NEXT(e) APR_RING_NEXT((e), link)
-/**
- * Get the previous queue in the list
- * @param e The current queue
- * @return The previous queue
- */
-#define H2_TQ_PREV(e) APR_RING_PREV((e), link)
-
-/**
- * Remove a queue from its list
- * @param e The queue to remove
- */
-#define H2_TQ_REMOVE(e) APR_RING_REMOVE((e), link)
-
-
-#define H2_TQ_EMPTY(e) H2_TASK_LIST_EMPTY(&(e)->tasks)
+h2_task *h2_tq_shift(h2_task_queue *q);
#endif /* defined(__mod_h2__h2_task_queue__) */
Modified: httpd/httpd/trunk/modules/http2/h2_version.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_version.h?rev=1711044&r1=1711043&r2=1711044&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_version.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_version.h Wed Oct 28 15:53:07 2015
@@ -20,7 +20,7 @@
* @macro
* Version number of the h2 module as c string
*/
-#define MOD_HTTP2_VERSION "1.0.2-DEV"
+#define MOD_HTTP2_VERSION "1.0.3-DEV"
/**
* @macro
@@ -28,7 +28,7 @@
* release. This is a 24 bit number with 8 bits for major number, 8 bits
* for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
*/
-#define MOD_HTTP2_VERSION_NUM 0x010002
+#define MOD_HTTP2_VERSION_NUM 0x010003
#endif /* mod_h2_h2_version_h */
Re: svn commit: r1711044 - in /httpd/httpd/trunk/modules/http2: h2_io.h h2_mplx.c h2_mplx.h h2_session.c h2_session.h h2_stream.c h2_stream.h h2_task.c h2_task.h h2_task_queue.c h2_task_queue.h h2_version.h
Posted by Stefan Eissing <st...@greenbytes.de>.
> Am 28.10.2015 um 21:03 schrieb Ruediger Pluem <rp...@apache.org>:
> On 10/28/2015 04:53 PM, icing@apache.org wrote:
>> [Modified: httpd/httpd/trunk/modules/http2/h2_mplx.c
>> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_mplx.c?rev=1711044&r1=1711043&r2=1711044&view=diff
>> ==============================================================================
>> --- httpd/httpd/trunk/modules/http2/h2_mplx.c (original)
>> +++ httpd/httpd/trunk/modules/http2/h2_mplx.c Wed Oct 28 15:53:07 2015
>> @@ -128,7 +128,7 @@ h2_mplx *h2_mplx_create(conn_rec *c, apr
>>
>> m->bucket_alloc = apr_bucket_alloc_create(m->pool);
>>
>> - m->q = h2_tq_create(m->id, m->pool);
>> + m->q = h2_tq_create(m->pool, 23);
>
> I thought the answer to the last question was 42 :-). Seriously using a hardcoded value that is not done via a #define
> with a descriptive name and that is not documented is IMHO bad.
You are correct. I need to give this change a rework anyway, so this number will disappear.
//Stefan
Re: svn commit: r1711044 - in /httpd/httpd/trunk/modules/http2:
h2_io.h h2_mplx.c h2_mplx.h h2_session.c h2_session.h h2_stream.c h2_stream.h
h2_task.c h2_task.h h2_task_queue.c h2_task_queue.h h2_version.h
Posted by Ruediger Pluem <rp...@apache.org>.
On 10/28/2015 04:53 PM, icing@apache.org wrote:
> Author: icing
> Date: Wed Oct 28 15:53:07 2015
> New Revision: 1711044
>
> URL: http://svn.apache.org/viewvc?rev=1711044&view=rev
> Log:
> http2 priority based scheduling of stream execution in each session
>
> Modified:
> httpd/httpd/trunk/modules/http2/h2_io.h
> httpd/httpd/trunk/modules/http2/h2_mplx.c
> httpd/httpd/trunk/modules/http2/h2_mplx.h
> httpd/httpd/trunk/modules/http2/h2_session.c
> httpd/httpd/trunk/modules/http2/h2_session.h
> httpd/httpd/trunk/modules/http2/h2_stream.c
> httpd/httpd/trunk/modules/http2/h2_stream.h
> httpd/httpd/trunk/modules/http2/h2_task.c
> httpd/httpd/trunk/modules/http2/h2_task.h
> httpd/httpd/trunk/modules/http2/h2_task_queue.c
> httpd/httpd/trunk/modules/http2/h2_task_queue.h
> httpd/httpd/trunk/modules/http2/h2_version.h
>
> Modified: httpd/httpd/trunk/modules/http2/h2_io.h
> Modified: httpd/httpd/trunk/modules/http2/h2_mplx.c
> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_mplx.c?rev=1711044&r1=1711043&r2=1711044&view=diff
> ==============================================================================
> --- httpd/httpd/trunk/modules/http2/h2_mplx.c (original)
> +++ httpd/httpd/trunk/modules/http2/h2_mplx.c Wed Oct 28 15:53:07 2015
> @@ -128,7 +128,7 @@ h2_mplx *h2_mplx_create(conn_rec *c, apr
>
> m->bucket_alloc = apr_bucket_alloc_create(m->pool);
>
> - m->q = h2_tq_create(m->id, m->pool);
> + m->q = h2_tq_create(m->pool, 23);
I thought the answer to the last question was 42 :-). Seriously using a hardcoded value that is not done via a #define
with a descriptive name and that is not documented is IMHO bad.
> m->stream_ios = h2_io_set_create(m->pool);
> m->ready_ios = h2_io_set_create(m->pool);
> m->closed = h2_stream_set_create(m->pool);
Regards
RĂ¼diger