]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon/http: optimize code by using trie instead of array macros
authorTomas Krizek <tomas.krizek@nic.cz>
Mon, 8 Mar 2021 11:19:29 +0000 (12:19 +0100)
committerLukáš Ježek <lukas.jezek@nic.cz>
Tue, 9 Mar 2021 09:31:51 +0000 (10:31 +0100)
daemon/http.c
daemon/http.h

index 802d96ba723fe5598efb4b6e75eec91a8658fd35..313808706a0189a81bbe1babd215edd8af19926e 100644 (file)
@@ -45,6 +45,24 @@ struct http_data {
        uv_write_t *req;
 };
 
+static void http_stream_status_free(struct http_stream_status *stat)
+{
+       if (!stat)
+               return;
+
+       free(stat->err_msg);
+       stat->err_msg = NULL;
+       free(stat);
+}
+
+static int status_free(trie_val_t *stat, void *null)
+{
+       assert(stat);
+       http_stream_status_free(*stat);
+       return 0;
+}
+
+
 /*
  * Write HTTP/2 protocol data to underlying transport layer.
  */
@@ -95,9 +113,6 @@ static int send_padding(struct http_ctx *ctx, uint8_t padlen)
        return 0;
 }
 
-static int http_status_remove(struct http_ctx *ctx, struct http_stream_status * stat);
-static struct http_stream_status * http_status_get(struct http_ctx *ctx, int32_t stream_id);
-
 /*
  * Write entire DATA frame to underlying transport layer.
  *
@@ -131,8 +146,6 @@ static int send_data_callback(nghttp2_session *h2, nghttp2_frame *frame, const u
        if (ret < 0)
                return NGHTTP2_ERR_CALLBACK_FAILURE;
 
-       http_status_remove(ctx, http_status_get(ctx, frame->hd.stream_id));
-
        return 0;
 }
 
@@ -168,49 +181,6 @@ static ssize_t read_callback(nghttp2_session *h2, int32_t stream_id, uint8_t *bu
        return send;
 }
 
-/*
- * Get pointer to stream status.
- */
-static struct http_stream_status * http_status_get(struct http_ctx *ctx, int32_t stream_id)
-{
-       assert(ctx);
-       struct http_stream_status *stat = NULL;
-
-       if (ctx->current_stream && ctx->current_stream->stream_id == stream_id)
-               return ctx->current_stream;
-
-
-       for (size_t idx = 0; idx < ctx->stream_status.len; ++idx) {
-               stat = ctx->stream_status.at[idx];
-               if (stat->stream_id == stream_id)
-                       return stat;
-       }
-       return NULL;
-}
-
-/*
- * Remove error stream status from list
- */
-static int http_status_remove(struct http_ctx *ctx, struct http_stream_status * stat)
-{
-       if (!stat)
-               return 0;
-
-       free(stat->err_msg);
-       stat->err_msg = NULL;
-
-       size_t idx;
-       for (idx = 0; idx < ctx->stream_status.len; ++idx) {
-               if (stat->stream_id == ctx->stream_status.at[idx]->stream_id) {
-                       array_del(ctx->stream_status, idx);
-                       free(stat);
-                       break;
-               }
-       }
-
-       return 0;
-}
-
 /*
  * Send http error status code.
  */
@@ -219,10 +189,11 @@ static int send_err_status(struct http_ctx *ctx, int32_t stream_id)
        int ret;
        int status_len;
        nghttp2_data_provider prov;
-       struct http_stream_status *stat = http_status_get(ctx, stream_id);
+       trie_val_t *stat_p = trie_get_try(ctx->stream_status, (char *)&stream_id, sizeof(stream_id));
 
-       if(!stat)
+       if (!stat_p || !*stat_p)
                return kr_error(EINVAL);
+       struct http_stream_status *stat = *stat_p;
 
        prov.source.ptr = NULL;
        prov.read_callback = read_callback;
@@ -265,7 +236,8 @@ static int send_err_status(struct http_ctx *ctx, int32_t stream_id)
 static struct http_stream_status * set_error_status(struct http_ctx *ctx, int32_t stream_id, int status, const char *const status_msg)
 {
 
-       struct http_stream_status *stat = http_status_get(ctx, stream_id);
+       trie_val_t *stat_p = trie_get_ins(ctx->stream_status, (char *)&stream_id, sizeof(stream_id));
+       struct http_stream_status *stat = *stat_p;
        if (stat && stat->err_status != 200)
                return stat;
 
@@ -275,12 +247,7 @@ static struct http_stream_status * set_error_status(struct http_ctx *ctx, int32_
                if (!stat)
                        return NULL;
 
-               // push to end of array
-               if (array_push(ctx->stream_status, stat) < 0) {
-                       free(stat);
-                       return NULL;
-               }
-
+               *stat_p = stat;
                stat->err_msg = NULL;
        }
        stat->stream_id = stream_id;
@@ -711,12 +678,19 @@ static void on_pkt_write(struct http_data *data, int status)
 static int on_stream_close_callback(nghttp2_session *h2, int32_t stream_id,
                                    uint32_t error_code, void *user_data)
 {
+       struct http_ctx *ctx = (struct http_ctx *)user_data;
        struct http_data *data;
+       struct http_stream_status *stat;
+       int ret;
 
        data = nghttp2_session_get_stream_user_data(h2, stream_id);
        if (data)
                on_pkt_write(data, error_code == 0 ? 0 : kr_error(EIO));
 
+       ret = trie_del(ctx->stream_status, (char *)&stream_id, sizeof(stream_id), (trie_val_t *)&stat);
+       if (ret == 0)
+               http_stream_status_free(stat);
+
        return 0;
 }
 
@@ -758,7 +732,7 @@ struct http_ctx* http_new(struct session *session, http_send_callback send_cb)
        ctx->current_method = HTTP_METHOD_NONE;
        ctx->uri_path = NULL;
        ctx->content_type = NULL;
-       array_init(ctx->stream_status);
+       ctx->stream_status = trie_create(NULL);
 
 
        nghttp2_session_server_new(&ctx->h2, callbacks, ctx);
@@ -920,9 +894,8 @@ void http_free(struct http_ctx *ctx)
        if (!ctx)
                return;
 
-       while(ctx->stream_status.len)
-               http_status_remove(ctx, ctx->stream_status.at[0]);
-       array_clear(ctx->stream_status);
+       trie_apply(ctx->stream_status, status_free, NULL);
+       trie_free(ctx->stream_status);
 
        queue_deinit(ctx->streams);
        nghttp2_session_del(ctx->h2);
index 114f261e307ee0912e980b9ef9419c3d142f38c9..2f9c84529cd1ad4810fd62058302341f1f0bab53 100644 (file)
@@ -51,7 +51,7 @@ struct http_ctx {
        uint8_t *buf;  /* Part of the wire_buf that belongs to current HTTP/2 stream. */
        ssize_t buf_pos;
        ssize_t buf_size;
-       array_t(struct http_stream_status*) stream_status;
+       trie_t *stream_status;
        struct http_stream_status *current_stream;
 };