From: Stefan Eissing Date: Mon, 21 Dec 2015 10:54:38 +0000 (+0000) Subject: byte savings by using bit fields, new env vars HTTP2 and H2PUSH, set to on when enabl... X-Git-Tag: 2.5.0-alpha~2517 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=483c9dd0603cf2cb44b77bfe635b021919b614a2;p=thirdparty%2Fapache%2Fhttpd.git byte savings by using bit fields, new env vars HTTP2 and H2PUSH, set to on when enabled on request git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1721121 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/http2/h2_h2.c b/modules/http2/h2_h2.c index 5bff7052f0f..2a795ba332c 100644 --- a/modules/http2/h2_h2.c +++ b/modules/http2/h2_h2.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "h2_private.h" @@ -33,6 +34,7 @@ #include "h2_config.h" #include "h2_ctx.h" #include "h2_conn.h" +#include "h2_request.h" #include "h2_session.h" #include "h2_util.h" #include "h2_h2.h" @@ -438,7 +440,7 @@ static int cipher_is_blacklisted(const char *cipher, const char **psource) */ static int h2_h2_process_conn(conn_rec* c); static int h2_h2_post_read_req(request_rec *r); - +static int h2_h2_fixups(request_rec *r); /******************************************************************************* * Once per lifetime init, retrieve optional functions @@ -569,6 +571,10 @@ void h2_h2_register_hooks(void) * never see the response. */ ap_hook_post_read_request(h2_h2_post_read_req, NULL, NULL, APR_HOOK_REALLY_FIRST); + + /* Setup subprocess env for certain variables + */ + ap_hook_fixups(h2_h2_fixups, NULL,NULL, APR_HOOK_MIDDLE); } int h2_h2_process_conn(conn_rec* c) @@ -700,3 +706,18 @@ static int h2_h2_post_read_req(request_rec *r) } return DECLINED; } + +static int h2_h2_fixups(request_rec *r) +{ + if (r->connection->master) { + h2_ctx *ctx = h2_ctx_rget(r); + struct h2_task *task = h2_ctx_get_task(ctx); + if (task) { + apr_table_setn(r->subprocess_env, "HTTP2", "on"); + if (task->request->push) { + apr_table_setn(r->subprocess_env, "H2PUSH", "on"); + } + } + } + return DECLINED; +} \ No newline at end of file diff --git a/modules/http2/h2_io.c b/modules/http2/h2_io.c index 801106341d4..4b6c013e382 100644 --- a/modules/http2/h2_io.c +++ b/modules/http2/h2_io.c @@ -193,7 +193,7 @@ static apr_status_t append_eos(h2_io *io, apr_bucket_brigade *bb, status = apr_brigade_puts(bb, NULL, NULL, "0\r\n\r\n"); } } - APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(io->bbin->bucket_alloc)); + APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(io->bucket_alloc)); return status; } @@ -422,7 +422,7 @@ apr_status_t h2_io_out_close(h2_io *io, apr_table_t *trailers) } if (!h2_util_has_eos(io->bbout, -1)) { APR_BRIGADE_INSERT_TAIL(io->bbout, - apr_bucket_eos_create(io->bbout->bucket_alloc)); + apr_bucket_eos_create(io->bucket_alloc)); } } return APR_SUCCESS; diff --git a/modules/http2/h2_io.h b/modules/http2/h2_io.h index 3f0b96dbc4c..c23fa3b470a 100644 --- a/modules/http2/h2_io.h +++ b/modules/http2/h2_io.h @@ -38,29 +38,30 @@ typedef struct h2_io h2_io; struct h2_io { int id; /* stream identifier */ apr_pool_t *pool; /* stream pool */ - int orphaned; /* h2_stream is gone for this io */ + apr_bucket_alloc_t *bucket_alloc; - int task_done; const struct h2_request *request; /* request on this io */ - int request_body; /* == 0 iff request has no body */ - struct h2_response *response;/* response for submit, once created */ - int rst_error; + struct h2_response *response;/* response to request */ + int rst_error; /* h2 related stream abort error */ - h2_io_op timed_op; /* which operation is waited on */ - struct apr_thread_cond_t *timed_cond; /* condition to wait on */ - apr_time_t timeout_at; /* when IO wait will time out */ - - int eos_in; - int eos_in_written; apr_bucket_brigade *bbin; /* input data for stream */ - apr_size_t input_consumed; /* how many bytes have been read */ - - int eos_out; apr_bucket_brigade *bbout; /* output data from stream */ - apr_bucket_alloc_t *bucket_alloc; + apr_bucket_brigade *tmp; /* temporary data for chunking */ + + int orphaned : 1; /* h2_stream is gone for this io */ + int task_done : 1; /* h2_task has finished for this io */ + int request_body : 1; /* iff request has body */ + int eos_in : 1; /* input eos has been seen */ + int eos_in_written : 1; /* input eos has been forwarded */ + int eos_out : 1; /* output eos has been seen */ + + h2_io_op timed_op; /* which operation is waited on, if any */ + struct apr_thread_cond_t *timed_cond; /* condition to wait on, maybe NULL */ + apr_time_t timeout_at; /* when IO wait will time out */ + apr_size_t input_consumed; /* how many bytes have been read */ + int files_handles_owned; - apr_bucket_brigade *tmp; /* temporary data for chunking */ }; /******************************************************************************* diff --git a/modules/http2/h2_mplx.h b/modules/http2/h2_mplx.h index 0a652ce91a5..35b63c2a7cc 100644 --- a/modules/http2/h2_mplx.h +++ b/modules/http2/h2_mplx.h @@ -67,6 +67,8 @@ struct h2_mplx { apr_pool_t *pool; apr_bucket_alloc_t *bucket_alloc; + int aborted : 1; + struct h2_task_queue *q; struct h2_io_set *stream_ios; struct h2_io_set *ready_ios; @@ -75,7 +77,6 @@ struct h2_mplx { struct apr_thread_cond_t *added_output; struct apr_thread_cond_t *join_wait; - int aborted; apr_size_t stream_max_mem; int stream_timeout_secs; diff --git a/modules/http2/h2_push.c b/modules/http2/h2_push.c index b80ffb90812..9997c5769c5 100644 --- a/modules/http2/h2_push.c +++ b/modules/http2/h2_push.c @@ -293,7 +293,8 @@ static int add_push(link_ctx *ctx) "GET", ctx->req->scheme, ctx->req->authority, path, headers); - h2_request_end_headers(req, ctx->pool, 1); + /* atm, we do not push on pushes */ + h2_request_end_headers(req, ctx->pool, 1, 0); push->req = req; if (!ctx->pushes) { diff --git a/modules/http2/h2_request.c b/modules/http2/h2_request.c index bf2d0c2e3ad..04227efea54 100644 --- a/modules/http2/h2_request.c +++ b/modules/http2/h2_request.c @@ -227,7 +227,8 @@ apr_status_t h2_request_add_header(h2_request *req, apr_pool_t *pool, return status; } -apr_status_t h2_request_end_headers(h2_request *req, apr_pool_t *pool, int eos) +apr_status_t h2_request_end_headers(h2_request *req, apr_pool_t *pool, + int eos, int push) { const char *s; @@ -271,6 +272,7 @@ apr_status_t h2_request_end_headers(h2_request *req, apr_pool_t *pool, int eos) } req->eoh = 1; + req->push = push; /* In the presence of trailers, force behaviour of chunked encoding */ s = apr_table_get(req->headers, "Trailer"); diff --git a/modules/http2/h2_request.h b/modules/http2/h2_request.h index 9e74492cd9d..86f0eac0d24 100644 --- a/modules/http2/h2_request.h +++ b/modules/http2/h2_request.h @@ -28,10 +28,9 @@ struct h2_task; typedef struct h2_request h2_request; struct h2_request { - int id; /* stream id */ + int id; /* stream id */ - /* pseudo header values, see ch. 8.1.2.3 */ - const char *method; + const char *method; /* pseudo header values, see ch. 8.1.2.3 */ const char *scheme; const char *authority; const char *path; @@ -41,8 +40,10 @@ struct h2_request { apr_time_t request_time; apr_off_t content_length; - int chunked; - int eoh; + + int chunked : 1; /* iff requst body needs to be forwarded as chunked */ + int eoh : 1; /* iff end-of-headers has been seen and request is complete */ + int push : 1; /* iff server push is possible for this request */ const struct h2_config *config; }; @@ -68,7 +69,8 @@ apr_status_t h2_request_add_trailer(h2_request *req, apr_pool_t *pool, const char *name, size_t nlen, const char *value, size_t vlen); -apr_status_t h2_request_end_headers(h2_request *req, apr_pool_t *pool, int eos); +apr_status_t h2_request_end_headers(h2_request *req, apr_pool_t *pool, + int eos, int push); void h2_request_copy(apr_pool_t *p, h2_request *dst, const h2_request *src); diff --git a/modules/http2/h2_session.c b/modules/http2/h2_session.c index f80ee91bec8..3b624a8f331 100644 --- a/modules/http2/h2_session.c +++ b/modules/http2/h2_session.c @@ -171,7 +171,8 @@ static apr_status_t stream_schedule(h2_session *session, h2_stream *stream, int eos) { (void)session; - return h2_stream_schedule(stream, eos, stream_pri_cmp, session); + return h2_stream_schedule(stream, eos, h2_session_push_enabled(session), + stream_pri_cmp, session); } /* @@ -1240,7 +1241,6 @@ static apr_status_t submit_response(h2_session *session, h2_stream *stream) * also have the pushed ones as well. */ if (!stream->initiated_on - && h2_config_geti(session->config, H2_CONF_PUSH) && H2_HTTP_2XX(response->http_status) && h2_session_push_enabled(session)) { @@ -1545,8 +1545,10 @@ static int frame_print(const nghttp2_frame *frame, char *buffer, size_t maxlen) int h2_session_push_enabled(h2_session *session) { - return nghttp2_session_get_remote_settings(session->ngh2, - NGHTTP2_SETTINGS_ENABLE_PUSH); + /* iff we can and they can */ + return (h2_config_geti(session->config, H2_CONF_PUSH) + && nghttp2_session_get_remote_settings(session->ngh2, + NGHTTP2_SETTINGS_ENABLE_PUSH)); } static apr_status_t h2_session_send(h2_session *session) diff --git a/modules/http2/h2_session.h b/modules/http2/h2_session.h index 086ab18a785..602bf691398 100644 --- a/modules/http2/h2_session.h +++ b/modules/http2/h2_session.h @@ -64,10 +64,9 @@ struct h2_session { server_rec *s; /* server/vhost we're starting on */ const struct h2_config *config; /* Relevant config for this session */ - int started; - int aborted; /* this session is being aborted */ - int reprioritize; /* scheduled streams priority needs to - * be re-evaluated */ + int started : 1; /* session startup done */ + int aborted : 1; /* this session is being aborted */ + int reprioritize : 1; /* scheduled streams priority changed */ apr_interval_time_t wait_micros; int unsent_submits; /* number of submitted, but not yet sent diff --git a/modules/http2/h2_stream.c b/modules/http2/h2_stream.c index 06eee07ecca..1006bc2123e 100644 --- a/modules/http2/h2_stream.c +++ b/modules/http2/h2_stream.c @@ -273,7 +273,7 @@ apr_status_t h2_stream_add_header(h2_stream *stream, } } -apr_status_t h2_stream_schedule(h2_stream *stream, int eos, +apr_status_t h2_stream_schedule(h2_stream *stream, int eos, int push_enabled, h2_stream_pri_cmp *cmp, void *ctx) { apr_status_t status; @@ -294,7 +294,8 @@ apr_status_t h2_stream_schedule(h2_stream *stream, int eos, /* Seeing the end-of-headers, we have everything we need to * start processing it. */ - status = h2_request_end_headers(stream->request, stream->pool, eos); + status = h2_request_end_headers(stream->request, stream->pool, + eos, push_enabled); if (status == APR_SUCCESS) { if (!eos) { stream->bbin = apr_brigade_create(stream->pool, diff --git a/modules/http2/h2_stream.h b/modules/http2/h2_stream.h index 7b3eb3e7bca..f15bf66837d 100644 --- a/modules/http2/h2_stream.h +++ b/modules/http2/h2_stream.h @@ -58,12 +58,12 @@ struct h2_stream { apr_pool_t *pool; /* the memory pool for this stream */ struct h2_request *request; /* the request made in this stream */ struct h2_response *response; /* the response, once ready */ - - int aborted; /* was aborted */ - int suspended; /* DATA sending has been suspended */ int rst_error; /* stream error for RST_STREAM */ - int scheduled; /* stream has been scheduled */ - int submitted; /* response HEADER has been sent */ + + int aborted : 1; /* was aborted */ + int suspended : 1; /* DATA sending has been suspended */ + int scheduled : 1; /* stream has been scheduled */ + int submitted : 1; /* response HEADER has been sent */ apr_off_t input_remaining; /* remaining bytes on input as advertised via content-length */ apr_bucket_brigade *bbin; /* input DATA */ @@ -184,7 +184,7 @@ void h2_stream_rst(h2_stream *streamm, int error_code); * @param cmp priority comparision * @param ctx context for comparision */ -apr_status_t h2_stream_schedule(h2_stream *stream, int eos, +apr_status_t h2_stream_schedule(h2_stream *stream, int eos, int push_enabled, h2_stream_pri_cmp *cmp, void *ctx); /** diff --git a/modules/http2/h2_task.c b/modules/http2/h2_task.c index f1b808db07a..93d20ade777 100644 --- a/modules/http2/h2_task.c +++ b/modules/http2/h2_task.c @@ -100,7 +100,7 @@ void h2_task_register_hooks(void) */ ap_hook_pre_connection(h2_task_pre_conn, NULL, mod_ssl, APR_HOOK_FIRST); - /* When the connection processing actually starts, we might to + /* When the connection processing actually starts, we might * take over, if the connection is for a task. */ ap_hook_process_connection(h2_task_process_conn, diff --git a/modules/http2/h2_task.h b/modules/http2/h2_task.h index 9d3e235312a..5a7c79db62a 100644 --- a/modules/http2/h2_task.h +++ b/modules/http2/h2_task.h @@ -48,17 +48,17 @@ typedef struct h2_task h2_task; struct h2_task { const char *id; int stream_id; - struct h2_mplx *mplx; - - const struct h2_request *request; - int filters_set; - int input_eos; - - int serialize_headers; - - struct conn_rec *c; apr_pool_t *pool; apr_bucket_alloc_t *bucket_alloc; + + struct h2_mplx *mplx; + struct conn_rec *c; + const struct h2_request *request; + + int filters_set : 1; + int input_eos : 1; + int serialize_headers : 1; + struct h2_task_input *input; struct h2_task_output *output; diff --git a/modules/http2/h2_task_output.h b/modules/http2/h2_task_output.h index de03890ed69..10ec3ccbbcf 100644 --- a/modules/http2/h2_task_output.h +++ b/modules/http2/h2_task_output.h @@ -38,7 +38,7 @@ struct h2_task_output { struct h2_task *task; h2_task_output_state_t state; struct h2_from_h1 *from_h1; - int trailers_passed; + int trailers_passed : 1; }; h2_task_output *h2_task_output_create(struct h2_task *task, apr_pool_t *pool); diff --git a/modules/http2/h2_worker.h b/modules/http2/h2_worker.h index 43a72930977..249cae0e98e 100644 --- a/modules/http2/h2_worker.h +++ b/modules/http2/h2_worker.h @@ -53,7 +53,7 @@ struct h2_worker { h2_worker_done_fn *worker_done; void *ctx; - int aborted; + int aborted : 1; int pool_reuses; struct h2_task *task; }; diff --git a/modules/http2/h2_workers.h b/modules/http2/h2_workers.h index 99aa1f4daf7..f92f3732cef 100644 --- a/modules/http2/h2_workers.h +++ b/modules/http2/h2_workers.h @@ -33,12 +33,13 @@ typedef struct h2_workers h2_workers; struct h2_workers { server_rec *s; apr_pool_t *pool; - int aborted; int next_worker_id; int min_size; int max_size; + int aborted : 1; + apr_threadattr_t *thread_attr; APR_RING_HEAD(h2_worker_list, h2_worker) workers;