]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: snapshots: dynamically allocate the snapshots
authorWilly Tarreau <w@1wt.eu>
Fri, 7 Sep 2018 17:02:32 +0000 (19:02 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 7 Sep 2018 17:59:58 +0000 (19:59 +0200)
Now upon error we dynamically allocate the snapshot instead of overwriting
it. This way there is no more memory wasted in the proxy to hold the two
error snapshot descriptors. Also an appreciable side effect of this is that
the proxy's lock is only taken during the pointer swap, no more while copying
the buffer's contents. This saves 480 bytes of memory per proxy.

include/types/proxy.h
src/proxy.c

index 9695b9c2d7f50ae418ff510319100a16fb7bd43b..ca3bc7de230a9d6b6b85a23b6f752dcd3f473f29 100644 (file)
@@ -410,7 +410,7 @@ struct proxy {
 
        /* warning: these structs are huge, keep them at the bottom */
        struct sockaddr_storage dispatch_addr;  /* the default address to connect to */
-       struct error_snapshot invalid_req, invalid_rep; /* captures of last errors */
+       struct error_snapshot *invalid_req, *invalid_rep; /* captures of last errors */
 
        /* used only during configuration parsing */
        int no_options;                         /* PR_O_REDISP, PR_O_TRANSP, ... */
index 9306637722376968eacb9f7ccf17bcef7a86717c..9f9fec878c8332ecc6f4f41b8097e03f6d41c247 100644 (file)
@@ -1356,6 +1356,15 @@ void proxy_capture_error(struct proxy *proxy, int is_back,
        struct error_snapshot *es;
        unsigned int buf_len;
        int len1, len2;
+       unsigned int ev_id;
+
+       ev_id = HA_ATOMIC_XADD(&error_snapshot_id, 1);
+
+       es = malloc(sizeof(*es));
+       if (!es)
+               return;
+
+       es->ev_id    = ev_id;
 
        buf_len = b_data(buf) - buf_out;
        len1 = b_size(buf) - buf_len;
@@ -1363,9 +1372,6 @@ void proxy_capture_error(struct proxy *proxy, int is_back,
                len1 = buf_len;
        len2 = buf_len - len1;
 
-       HA_SPIN_LOCK(PROXY_LOCK, &proxy->lock);
-       es = is_back ? &proxy->invalid_rep : &proxy->invalid_req;
-
        es->buf_len = buf_len;
 
        if (!es->buf)
@@ -1386,7 +1392,6 @@ void proxy_capture_error(struct proxy *proxy, int is_back,
        else
                memset(&es->src, 0, sizeof(es->src));
 
-       es->ev_id = HA_ATOMIC_XADD(&error_snapshot_id, 1);
        es->buf_wrap = b_wrap(buf) - b_peek(buf, buf_out);
        es->buf_out  = buf_out;
        es->buf_ofs  = buf_ofs;
@@ -1403,6 +1408,17 @@ void proxy_capture_error(struct proxy *proxy, int is_back,
        else
                memset(&es->ctx, 0, sizeof(es->ctx));
        es->show = show;
+
+       /* note: we still lock since we have to be certain that nobody is
+        * dumping the output while we free.
+        */
+       HA_SPIN_LOCK(PROXY_LOCK, &proxy->lock);
+       if (is_back) {
+               es = HA_ATOMIC_XCHG(&proxy->invalid_rep, es);
+       } else {
+               es = HA_ATOMIC_XCHG(&proxy->invalid_req, es);
+       }
+       free(es);
        HA_SPIN_UNLOCK(PROXY_LOCK, &proxy->lock);
 }
 
@@ -2012,17 +2028,17 @@ static int cli_io_handler_show_errors(struct appctx *appctx)
                HA_SPIN_LOCK(PROXY_LOCK, &appctx->ctx.errors.px->lock);
 
                if ((appctx->ctx.errors.flag & 1) == 0) {
-                       es = &appctx->ctx.errors.px->invalid_req;
+                       es = appctx->ctx.errors.px->invalid_req;
                        if (appctx->ctx.errors.flag & 2) // skip req
                                goto next;
                }
                else {
-                       es = &appctx->ctx.errors.px->invalid_rep;
+                       es = appctx->ctx.errors.px->invalid_rep;
                        if (appctx->ctx.errors.flag & 4) // skip resp
                                goto next;
                }
 
-               if (!es->when.tv_sec)
+               if (!es)
                        goto next;
 
                if (appctx->ctx.errors.iid >= 0 &&