MEDIUM: snapshots: dynamically allocate the snapshots
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.
diff --git a/include/types/proxy.h b/include/types/proxy.h
index 9695b9c..ca3bc7d 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -410,7 +410,7 @@
/* 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, ... */
diff --git a/src/proxy.c b/src/proxy.c
index 9306637..9f9fec8 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -1356,6 +1356,15 @@
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 @@
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 @@
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 @@
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 @@
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 &&