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/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 &&