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/11/24 17:22:52 UTC
svn commit: r1716197 - in /httpd/httpd/trunk/modules/http2: h2_h2.h
h2_push.c h2_push.h h2_session.c h2_session.h h2_stream.c h2_stream.h
Author: icing
Date: Tue Nov 24 16:22:50 2015
New Revision: 1716197
URL: http://svn.apache.org/viewvc?rev=1716197&view=rev
Log:
priorities for pushed streams are changed if nghttp2 library supports this, configurations for type based priority specs TBD
Modified:
httpd/httpd/trunk/modules/http2/h2_h2.h
httpd/httpd/trunk/modules/http2/h2_push.c
httpd/httpd/trunk/modules/http2/h2_push.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
Modified: httpd/httpd/trunk/modules/http2/h2_h2.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_h2.h?rev=1716197&r1=1716196&r2=1716197&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_h2.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_h2.h Tue Nov 24 16:22:50 2015
@@ -58,6 +58,17 @@ extern const char *H2_MAGIC_TOKEN;
#define H2_STREAM_CLIENT_INITIATED(id) (id&0x01)
+typedef enum {
+ H2_DEPENDANT_AFTER,
+ H2_DEPENDANT_INTERLEAVED,
+ H2_DEPENDANT_BEFORE,
+} h2_dependency;
+
+typedef struct h2_priority {
+ h2_dependency dependency;
+ int weight;
+} h2_priority;
+
/**
* Provide a user readable description of the HTTP/2 error code-
* @param h2_error http/2 error code, as in rfc 7540, ch. 7
Modified: httpd/httpd/trunk/modules/http2/h2_push.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_push.c?rev=1716197&r1=1716196&r2=1716197&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_push.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_push.c Tue Nov 24 16:22:50 2015
@@ -301,8 +301,8 @@ static int add_push(link_ctx *ctx)
h2_request_end_headers(req, ctx->pool, 1);
push->req = req;
- push->dep_pref = H2_PUSH_DEP_AFTER;
- push->weight = NGHTTP2_DEFAULT_WEIGHT;
+ push->prio.dependency = H2_DEPENDANT_AFTER;
+ push->prio.weight = NGHTTP2_DEFAULT_WEIGHT;
if (!ctx->pushes) {
ctx->pushes = apr_array_make(ctx->pool, 5, sizeof(h2_push*));
Modified: httpd/httpd/trunk/modules/http2/h2_push.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_push.h?rev=1716197&r1=1716196&r2=1716197&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_push.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_push.h Tue Nov 24 16:22:50 2015
@@ -19,17 +19,10 @@ struct h2_request;
struct h2_response;
struct h2_ngheader;
-typedef enum {
- H2_PUSH_DEP_AFTER,
- H2_PUSH_DEP_INTERLEAVED,
- H2_PUSH_DEP_BEFORE,
-} h2_push_dep_t;
-
typedef struct h2_push {
- int initiating_id;
+ int initiating_id;
const struct h2_request *req;
- h2_push_dep_t dep_pref;
- int weight;
+ h2_priority prio;
} h2_push;
Modified: httpd/httpd/trunk/modules/http2/h2_session.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_session.c?rev=1716197&r1=1716196&r2=1716197&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_session.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_session.c Tue Nov 24 16:22:50 2015
@@ -1167,6 +1167,7 @@ static apr_status_t submit_response(h2_s
nghttp2_data_provider provider;
h2_response *response = stream->response;
h2_ngheader *ngh;
+ h2_priority *prio;
memset(&provider, 0, sizeof(provider));
provider.source.fd = stream->id;
@@ -1176,6 +1177,12 @@ static apr_status_t submit_response(h2_s
"h2_stream(%ld-%d): submit response %d",
session->id, stream->id, response->http_status);
+ prio = h2_stream_get_priority(stream);
+ if (prio) {
+ h2_session_set_prio(session, stream, prio);
+ /* no showstopper if that fails for some reason */
+ }
+
ngh = h2_util_ngheader_make_res(stream->pool, response->http_status,
response->headers);
rv = nghttp2_submit_response(session->ngh2, response->stream_id,
@@ -1227,13 +1234,6 @@ static apr_status_t submit_response(h2_s
return status;
}
-static int valid_weight(float f)
-{
- int w = floor(f);
- return (w < NGHTTP2_MIN_WEIGHT? NGHTTP2_MIN_WEIGHT :
- (w > NGHTTP2_MAX_WEIGHT)? NGHTTP2_MAX_WEIGHT : w);
-}
-
struct h2_stream *h2_session_push(h2_session *session, h2_stream *is,
h2_push *push)
{
@@ -1259,95 +1259,10 @@ struct h2_stream *h2_session_push(h2_ses
session->id, push->initiating_id, nid,
push->req->method, push->req->path);
-#ifdef H2_NG2_CHANGE_PRIO
- /* If different than default, change the priority of the pushed stream
- * as specified in the h2_push:
- */
- if (push->weight != NGHTTP2_DEFAULT_WEIGHT || push->dep_pref != H2_PUSH_DEP_AFTER) {
- nghttp2_stream *s_init, *s_dep, *s_push;
- int id_init = push->initiating_id;
-
- s_push = nghttp2_session_find_stream(session->ngh2, nid);
- if (!s_push) {
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c,
- "h2_stream(%ld-%d): lookup of PUSHed stream failed",
- session->id, nid);
- }
- s_init = nghttp2_session_find_stream(session->ngh2, id_init);
- if (s_push && s_init) {
- nghttp2_priority_spec ps;
- int id_dep, w_init, w, rv = 0;
-
- switch (push->dep_pref) {
- case H2_PUSH_DEP_INTERLEAVED:
- /* PUSHed stream is to be interleaved with initiating stream.
- * It is made a sibling of the initiating stream and gets a
- * proportional weight [1, MAX_WEIGHT] of the initiaing
- * stream weight.
- */
- s_dep = nghttp2_stream_get_parent(s_init);
- if (s_dep) {
- id_dep = nghttp2_stream_get_stream_id(s_dep);
- w_init = nghttp2_stream_get_weight(s_init);
- w = valid_weight(w_init * ((float)NGHTTP2_MAX_WEIGHT / push->weight));
- nghttp2_priority_spec_init(&ps, id_dep, w, 0);
- rv = nghttp2_session_change_stream_priority(session->ngh2, nid, &ps);
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c,
- "h2_stream(%ld-%d): PUSH INTERLEAVE, weight=%d, "
- "depends=%d, returned=%d",
- session->id, nid, w, id_dep, rv);
- }
- break;
- case H2_PUSH_DEP_BEFORE:
- /* PUSHed stream os to be sent BEFORE the initiating stream.
- * It gets the same weight as the initiating stream, replaces
- * that stream in the dependency tree and has the initiating
- * stream as child with MAX_WEIGHT.
- */
- s_dep = nghttp2_stream_get_parent(s_init);
- if (s_dep) {
- id_dep = nghttp2_stream_get_stream_id(s_dep);
- w_init = nghttp2_stream_get_weight(s_init);
- nghttp2_priority_spec_init(&ps, id_dep, valid_weight(w_init), 0);
- rv = nghttp2_session_change_stream_priority(session->ngh2, nid, &ps);
- if (!rv) {
- nghttp2_priority_spec_init(&ps, nid, NGHTTP2_MAX_WEIGHT, 0);
- rv = nghttp2_session_change_stream_priority(session->ngh2, id_init, &ps);
- if (rv < 0) {
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c,
- "h2_stream(%ld-%d): PUSH BEFORE2, weight=%d, "
- "depends=%d, returned=%d",
- session->id, id_init, ps.weight, ps.stream_id, rv);
- }
- }
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c,
- "h2_stream(%ld-%d): PUSH BEFORE, weight=%d, "
- "depends=%d, before=%d, returned=%d",
- session->id, nid, w_init, id_dep, id_init, rv);
- }
- break;
- case H2_PUSH_DEP_AFTER:
- /* The PUSHed stream is to be sent after the initiating stream.
- * Give if the specified weight and let it depend on the intiating
- * stream.
- */
- /* fall through, it's the default */
- default:
- nghttp2_priority_spec_init(&ps, id_init, valid_weight(push->weight), 0);
- rv = nghttp2_session_change_stream_priority(session->ngh2, nid, &ps);
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c,
- "h2_stream(%ld-%d): PUSH AFTER, weight=%d, "
- "depends=%d, returned=%d",
- session->id, nid, ps.weight, ps.stream_id, rv);
- break;
- }
- }
- }
-#endif
-
stream = h2_session_open_stream(session, nid);
if (stream) {
h2_stream_set_h2_request(stream, is->id, push->req);
+ h2_stream_set_priority(stream, &push->prio);
status = stream_schedule(session, stream, 1);
if (status != APR_SUCCESS) {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, session->c,
@@ -1372,6 +1287,108 @@ struct h2_stream *h2_session_push(h2_ses
return stream;
}
+static int valid_weight(float f)
+{
+ int w = floor(f);
+ return (w < NGHTTP2_MIN_WEIGHT? NGHTTP2_MIN_WEIGHT :
+ (w > NGHTTP2_MAX_WEIGHT)? NGHTTP2_MAX_WEIGHT : w);
+}
+
+apr_status_t h2_session_set_prio(h2_session *session, h2_stream *stream,
+ h2_priority *prio)
+{
+ apr_status_t status = APR_SUCCESS;
+#ifdef H2_NG2_CHANGE_PRIO
+ nghttp2_stream *s_grandpa, *s_parent, *s;
+
+ s = nghttp2_session_find_stream(session->ngh2, stream->id);
+ if (!s) {
+ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c,
+ "h2_stream(%ld-%d): lookup of nghttp2_stream failed",
+ session->id, stream->id);
+ return APR_EINVAL;
+ }
+
+ s_parent = nghttp2_stream_get_parent(s);
+ if (s_parent) {
+ nghttp2_priority_spec ps;
+ int id_parent, id_grandpa, w_parent, w, rv = 0;
+ char *ptype = "AFTER";
+ h2_dependency dep = prio->dependency;
+
+ id_parent = nghttp2_stream_get_stream_id(s_parent);
+ s_grandpa = nghttp2_stream_get_parent(s_parent);
+ if (s_grandpa) {
+ id_grandpa = nghttp2_stream_get_stream_id(s_grandpa);
+ }
+ else {
+ /* parent of parent does not exist,
+ * only possible if parent == root */
+ dep = H2_DEPENDANT_AFTER;
+ }
+
+ switch (dep) {
+ case H2_DEPENDANT_INTERLEAVED:
+ /* PUSHed stream is to be interleaved with initiating stream.
+ * It is made a sibling of the initiating stream and gets a
+ * proportional weight [1, MAX_WEIGHT] of the initiaing
+ * stream weight.
+ */
+ ptype = "INTERLEAVED";
+ w_parent = nghttp2_stream_get_weight(s_parent);
+ w = valid_weight(w_parent * ((float)NGHTTP2_MAX_WEIGHT / prio->weight));
+ nghttp2_priority_spec_init(&ps, id_grandpa, w, 0);
+ break;
+
+ case H2_DEPENDANT_BEFORE:
+ /* PUSHed stream os to be sent BEFORE the initiating stream.
+ * It gets the same weight as the initiating stream, replaces
+ * that stream in the dependency tree and has the initiating
+ * stream as child with MAX_WEIGHT.
+ */
+ ptype = "BEFORE";
+ nghttp2_priority_spec_init(&ps, stream->id, NGHTTP2_MAX_WEIGHT, 0);
+ rv = nghttp2_session_change_stream_priority(session->ngh2, id_parent, &ps);
+ if (rv < 0) {
+ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c,
+ "h2_stream(%ld-%d): PUSH BEFORE2, weight=%d, "
+ "depends=%d, returned=%d",
+ session->id, id_parent, ps.weight, ps.stream_id, rv);
+ return APR_EGENERAL;
+ }
+ id_grandpa = nghttp2_stream_get_stream_id(s_grandpa);
+ w_parent = nghttp2_stream_get_weight(s_parent);
+ nghttp2_priority_spec_init(&ps, id_grandpa, valid_weight(w_parent), 0);
+ break;
+
+ case H2_DEPENDANT_AFTER:
+ /* The PUSHed stream is to be sent after the initiating stream.
+ * Give if the specified weight and let it depend on the intiating
+ * stream.
+ */
+ /* fall through, it's the default */
+ default:
+ nghttp2_priority_spec_init(&ps, id_parent, valid_weight(prio->weight), 0);
+ break;
+ }
+
+
+ rv = nghttp2_session_change_stream_priority(session->ngh2, stream->id, &ps);
+ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c,
+ "h2_stream(%ld-%d): PUSH %s, weight=%d, "
+ "depends=%d, returned=%d",
+ session->id, stream->id, ptype,
+ ps.weight, ps.stream_id, rv);
+ status = (rv < 0)? APR_EGENERAL : APR_SUCCESS;
+ }
+#else
+ (void)session;
+ (void)stream;
+ (void)prio;
+#endif
+ return status;
+}
+
apr_status_t h2_session_stream_destroy(h2_session *session, h2_stream *stream)
{
apr_pool_t *pool = h2_stream_detach_pool(stream);
Modified: httpd/httpd/trunk/modules/http2/h2_session.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_session.h?rev=1716197&r1=1716196&r2=1716197&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_session.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_session.h Tue Nov 24 16:22:50 2015
@@ -41,6 +41,7 @@ struct apr_thread_mutext_t;
struct apr_thread_cond_t;
struct h2_config;
struct h2_mplx;
+struct h2_priority;
struct h2_push;
struct h2_response;
struct h2_session;
@@ -195,4 +196,9 @@ apr_status_t h2_session_stream_destroy(h
struct h2_stream *h2_session_push(h2_session *session,
struct h2_stream *is, struct h2_push *push);
+apr_status_t h2_session_set_prio(h2_session *session,
+ struct h2_stream *stream,
+ struct h2_priority *prio);
+
+
#endif /* defined(__mod_h2__h2_session__) */
Modified: httpd/httpd/trunk/modules/http2/h2_stream.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_stream.c?rev=1716197&r1=1716196&r2=1716197&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_stream.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_stream.c Tue Nov 24 16:22:50 2015
@@ -668,3 +668,15 @@ apr_table_t *h2_stream_get_trailers(h2_s
{
return stream->response? stream->response->trailers : NULL;
}
+
+void h2_stream_set_priority(h2_stream *stream, h2_priority *prio)
+{
+ stream->prio = apr_pcalloc(stream->pool, sizeof(*prio));
+ memcpy(stream->prio, prio, sizeof(*prio));
+}
+
+h2_priority *h2_stream_get_priority(h2_stream *stream)
+{
+ return stream->prio;
+}
+
Modified: httpd/httpd/trunk/modules/http2/h2_stream.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_stream.h?rev=1716197&r1=1716196&r2=1716197&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_stream.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_stream.h Tue Nov 24 16:22:50 2015
@@ -41,6 +41,7 @@ typedef enum {
} h2_stream_state_t;
struct h2_mplx;
+struct h2_priority;
struct h2_request;
struct h2_response;
struct h2_session;
@@ -69,6 +70,8 @@ struct h2_stream {
apr_bucket_brigade *bbout; /* output DATA */
apr_off_t data_frames_sent; /* # of DATA frames sent out for this stream */
+
+ struct h2_priority *prio; /* priority information to set before submit */
};
@@ -300,4 +303,16 @@ apr_status_t h2_stream_submit_pushes(h2_
*/
apr_table_t *h2_stream_get_trailers(h2_stream *stream);
+/**
+ * Get priority information set for this stream.
+ */
+struct h2_priority *h2_stream_get_priority(h2_stream *stream);
+
+/**
+ * Set the priority information to use on the submit of the stream.
+ * @param stream the stream to set priority on
+ * @param prio the priority information
+ */
+void h2_stream_set_priority(h2_stream *stream, struct h2_priority *prio);
+
#endif /* defined(__mod_h2__h2_stream__) */