From: Stefan Eissing Date: Thu, 5 Nov 2015 14:21:13 +0000 (+0000) Subject: replacing own stream_set with apr_hash internally X-Git-Tag: 2.5.0-alpha~2660 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1c89ed5c8b8bdeb11d46e045f83c6ba0ccce4ccc;p=apache replacing own stream_set with apr_hash internally git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1712782 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/http2/h2_session.c b/modules/http2/h2_session.c index fc0287042b..d656499c5d 100644 --- a/modules/http2/h2_session.c +++ b/modules/http2/h2_session.c @@ -204,7 +204,7 @@ static int on_data_chunk_recv_cb(nghttp2_session *ngh2, uint8_t flags, if (session->aborted) { return NGHTTP2_ERR_CALLBACK_FAILURE; } - stream = h2_stream_set_get(session->streams, stream_id); + stream = h2_session_get_stream(session, stream_id); if (!stream) { ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, session->c, APLOGNO(02919) @@ -335,7 +335,7 @@ static int on_stream_close_cb(nghttp2_session *ngh2, int32_t stream_id, if (session->aborted) { return NGHTTP2_ERR_CALLBACK_FAILURE; } - stream = h2_stream_set_get(session->streams, stream_id); + stream = h2_session_get_stream(session, stream_id); if (stream) { stream_destroy(session, stream, error_code); } @@ -379,8 +379,7 @@ static int on_header_cb(nghttp2_session *ngh2, const nghttp2_frame *frame, if (session->aborted) { return NGHTTP2_ERR_CALLBACK_FAILURE; } - stream = h2_stream_set_get(session->streams, - frame->hd.stream_id); + stream = h2_session_get_stream(session, frame->hd.stream_id); if (!stream) { ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, session->c, APLOGNO(02920) @@ -421,8 +420,8 @@ static int on_frame_recv_cb(nghttp2_session *ng2s, switch (frame->hd.type) { case NGHTTP2_HEADERS: { int eos; - h2_stream * stream = h2_stream_set_get(session->streams, - frame->hd.stream_id); + h2_stream * stream = h2_session_get_stream(session, + frame->hd.stream_id); if (stream == NULL) { ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, session->c, APLOGNO(02921) @@ -444,8 +443,8 @@ static int on_frame_recv_cb(nghttp2_session *ng2s, break; } case NGHTTP2_DATA: { - h2_stream * stream = h2_stream_set_get(session->streams, - frame->hd.stream_id); + h2_stream * stream = h2_session_get_stream(session, + frame->hd.stream_id); if (stream == NULL) { ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, session->c, APLOGNO(02922) @@ -490,8 +489,8 @@ static int on_frame_recv_cb(nghttp2_session *ng2s, have to check the frame type first. */ if ((frame->hd.type == NGHTTP2_DATA || frame->hd.type == NGHTTP2_HEADERS) && frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { - h2_stream * stream = h2_stream_set_get(session->streams, - frame->hd.stream_id); + h2_stream * stream = h2_session_get_stream(session, + frame->hd.stream_id); if (stream != NULL) { status = h2_stream_write_eos(stream); ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, session->c, @@ -546,7 +545,7 @@ static int on_send_data_cb(nghttp2_session *ngh2, return NGHTTP2_ERR_CALLBACK_FAILURE; } - stream = h2_stream_set_get(session->streams, stream_id); + stream = h2_session_get_stream(session, stream_id); if (!stream) { ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_NOTFOUND, session->c, APLOGNO(02924) @@ -700,7 +699,7 @@ static h2_session *h2_session_create_int(conn_rec *c, return NULL; } - session->streams = h2_stream_set_create(session->pool); + session->streams = h2_stream_set_create(session->pool, session->max_stream_count); session->workers = workers; session->mplx = h2_mplx_create(c, session->pool, workers); @@ -769,7 +768,7 @@ void h2_session_destroy(h2_session *session) session->mplx = NULL; } if (session->streams) { - if (h2_stream_set_size(session->streams)) { + if (!h2_stream_set_is_empty(session->streams)) { ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, session->c, "h2_session(%ld): destroy, %d streams open", session->id, (int)h2_stream_set_size(session->streams)); @@ -915,7 +914,7 @@ apr_status_t h2_session_start(h2_session *session, int *rv) return status; } - stream = h2_stream_set_get(session->streams, 1); + stream = h2_session_get_stream(session, 1); if (stream == NULL) { status = APR_EGENERAL; ap_log_rerror(APLOG_MARK, APLOG_ERR, status, session->r, @@ -1183,7 +1182,7 @@ static ssize_t stream_data_cb(nghttp2_session *ng2s, (void)ng2s; (void)buf; (void)source; - stream = h2_stream_set_get(session->streams, stream_id); + stream = h2_session_get_stream(session, stream_id); if (!stream) { ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, session->c, APLOGNO(02937) diff --git a/modules/http2/h2_stream_set.c b/modules/http2/h2_stream_set.c index 5ef48a13e1..b93e45bb68 100644 --- a/modules/http2/h2_stream_set.c +++ b/modules/http2/h2_stream_set.c @@ -19,31 +19,30 @@ #include #include -#include -#include #include #include "h2_private.h" -#include "h2_session.h" #include "h2_stream.h" -#include "h2_task.h" #include "h2_stream_set.h" -#define H2_STREAM_IDX(list, i) ((h2_stream**)(list)->elts)[i] struct h2_stream_set { - apr_array_header_t *list; + apr_hash_t *hash; }; -h2_stream_set *h2_stream_set_create(apr_pool_t *pool) +static unsigned int stream_hash(const char *key, apr_ssize_t *klen) +{ + /* we use the "int stream_id" has key, which always odd from + * client and even from server. As long as we do not mix them + * in one set, snip off the lsb. */ + return (unsigned int)(*((int*)key)) >> 1; +} + +h2_stream_set *h2_stream_set_create(apr_pool_t *pool, int max) { h2_stream_set *sp = apr_pcalloc(pool, sizeof(h2_stream_set)); - if (sp) { - sp->list = apr_array_make(pool, 100, sizeof(h2_stream*)); - if (!sp->list) { - return NULL; - } - } + sp->hash = apr_hash_make_custom(pool, stream_hash); + return sp; } @@ -52,111 +51,50 @@ void h2_stream_set_destroy(h2_stream_set *sp) (void)sp; } -static int h2_stream_id_cmp(const void *s1, const void *s2) -{ - return (*((h2_stream **)s1))->id - (*((h2_stream **)s2))->id; -} - h2_stream *h2_stream_set_get(h2_stream_set *sp, int stream_id) { - /* we keep the array sorted by id, so lookup can be done - * by bsearch. - */ - h2_stream key; - h2_stream *pkey, **ps; - memset(&key, 0, sizeof(key)); - key.id = stream_id; - pkey = &key; - ps = bsearch(&pkey, sp->list->elts, sp->list->nelts, - sp->list->elt_size, h2_stream_id_cmp); - return ps? *ps : NULL; + return apr_hash_get(sp->hash, &stream_id, sizeof(stream_id)); } -static void h2_stream_set_sort(h2_stream_set *sp) +void h2_stream_set_add(h2_stream_set *sp, h2_stream *stream) { - qsort(sp->list->elts, sp->list->nelts, sp->list->elt_size, - h2_stream_id_cmp); + apr_hash_set(sp->hash, &stream->id, sizeof(stream->id), stream); } -apr_status_t h2_stream_set_add(h2_stream_set *sp, h2_stream *stream) +void h2_stream_set_remove(h2_stream_set *sp, int stream_id) { - h2_stream *existing = h2_stream_set_get(sp, stream->id); - if (!existing) { - int last; - APR_ARRAY_PUSH(sp->list, h2_stream*) = stream; - /* Normally, streams get added in ascending order if id. We - * keep the array sorted, so we just need to check of the newly - * appended stream has a lower id than the last one. if not, - * sorting is not necessary. - */ - last = sp->list->nelts - 1; - if (last > 0 - && (H2_STREAM_IDX(sp->list, last)->id - < H2_STREAM_IDX(sp->list, last-1)->id)) { - h2_stream_set_sort(sp); - } - } - return APR_SUCCESS; + apr_hash_set(sp->hash, &stream_id, sizeof(stream_id), NULL); } -h2_stream *h2_stream_set_remove(h2_stream_set *sp, int stream_id) +int h2_stream_set_is_empty(h2_stream_set *sp) { - int i; - for (i = 0; i < sp->list->nelts; ++i) { - h2_stream *s = H2_STREAM_IDX(sp->list, i); - if (s->id == stream_id) { - int n; - --sp->list->nelts; - n = sp->list->nelts - i; - if (n > 0) { - /* Close the hole in the array by moving the upper - * parts down one step. - */ - h2_stream **selts = (h2_stream**)sp->list->elts; - memmove(selts+i, selts+i+1, n * sizeof(h2_stream*)); - } - return s; - } - } - return NULL; + return apr_hash_count(sp->hash) == 0; } -void h2_stream_set_remove_all(h2_stream_set *sp) +apr_size_t h2_stream_set_size(h2_stream_set *sp) { - sp->list->nelts = 0; + return apr_hash_count(sp->hash); } -int h2_stream_set_is_empty(h2_stream_set *sp) -{ - AP_DEBUG_ASSERT(sp); - return sp->list->nelts == 0; -} +typedef struct { + h2_stream_set_iter_fn *iter; + void *ctx; +} iter_ctx; -h2_stream *h2_stream_set_find(h2_stream_set *sp, - h2_stream_set_match_fn *match, void *ctx) +static int hash_iter(void *ctx, const void *key, apr_ssize_t klen, + const void *val) { - h2_stream *s = NULL; - int i; - for (i = 0; !s && i < sp->list->nelts; ++i) { - s = match(ctx, H2_STREAM_IDX(sp->list, i)); - } - return s; + iter_ctx *ictx = ctx; + return ictx->iter(ictx->ctx, (h2_stream*)val); } void h2_stream_set_iter(h2_stream_set *sp, h2_stream_set_iter_fn *iter, void *ctx) { - int i; - for (i = 0; i < sp->list->nelts; ++i) { - h2_stream *s = H2_STREAM_IDX(sp->list, i); - if (!iter(ctx, s)) { - break; - } - } + iter_ctx ictx; + ictx.iter = iter; + ictx.ctx = ctx; + apr_hash_do(hash_iter, &ictx, sp->hash); } -apr_size_t h2_stream_set_size(h2_stream_set *sp) -{ - return sp->list->nelts; -} diff --git a/modules/http2/h2_stream_set.h b/modules/http2/h2_stream_set.h index 8bc6409223..44fe94ef3b 100644 --- a/modules/http2/h2_stream_set.h +++ b/modules/http2/h2_stream_set.h @@ -27,25 +27,20 @@ typedef int h2_stream_set_iter_fn(void *ctx, h2_stream *stream); typedef struct h2_stream_set h2_stream_set; -h2_stream_set *h2_stream_set_create(apr_pool_t *pool); +h2_stream_set *h2_stream_set_create(apr_pool_t *pool, int max); void h2_stream_set_destroy(h2_stream_set *sp); -apr_status_t h2_stream_set_add(h2_stream_set *sp, h2_stream *stream); +void h2_stream_set_add(h2_stream_set *sp, h2_stream *stream); h2_stream *h2_stream_set_get(h2_stream_set *sp, int stream_id); -h2_stream *h2_stream_set_remove(h2_stream_set *sp, int stream_id); - -void h2_stream_set_remove_all(h2_stream_set *sp); +void h2_stream_set_remove(h2_stream_set *sp, int stream_id); int h2_stream_set_is_empty(h2_stream_set *sp); apr_size_t h2_stream_set_size(h2_stream_set *sp); -h2_stream *h2_stream_set_find(h2_stream_set *sp, - h2_stream_set_match_fn *match, void *ctx); - void h2_stream_set_iter(h2_stream_set *sp, h2_stream_set_iter_fn *iter, void *ctx); diff --git a/modules/http2/h2_version.h b/modules/http2/h2_version.h index e72f662873..daada0f92b 100644 --- a/modules/http2/h2_version.h +++ b/modules/http2/h2_version.h @@ -20,7 +20,7 @@ * @macro * Version number of the h2 module as c string */ -#define MOD_HTTP2_VERSION "1.0.3-DEV" +#define MOD_HTTP2_VERSION "1.0.4-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 0x010003 +#define MOD_HTTP2_VERSION_NUM 0x010004 #endif /* mod_h2_h2_version_h */