]> granicus.if.org Git - apache/commitdiff
replacing own stream_set with apr_hash internally
authorStefan Eissing <icing@apache.org>
Thu, 5 Nov 2015 14:21:13 +0000 (14:21 +0000)
committerStefan Eissing <icing@apache.org>
Thu, 5 Nov 2015 14:21:13 +0000 (14:21 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1712782 13f79535-47bb-0310-9956-ffa450edef68

modules/http2/h2_session.c
modules/http2/h2_stream_set.c
modules/http2/h2_stream_set.h
modules/http2/h2_version.h

index fc0287042bb1b2e1ac015f3f98464166bc938a18..d656499c5db1f9146c92209c736ca29f0423776d 100644 (file)
@@ -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) 
index 5ef48a13e17d384a40f1f33844da0c1ed7a7ee67..b93e45bb687e96c87bd08f5461c1e9c81f7c746b 100644 (file)
 #include <apr_strings.h>
 
 #include <httpd.h>
-#include <http_core.h>
-#include <http_connection.h>
 #include <http_log.h>
 
 #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;
-}
 
index 8bc6409223b186b09b0e1121039c58e9e08e17c1..44fe94ef3beb33ee2d7e628253d31a30df06c451 100644 (file)
@@ -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);
 
index e72f66287399ea83efd60305f0e5aaba19c3770b..daada0f92bcc669cf0f8f46de74f10184f602d0b 100644 (file)
@@ -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 */