MEDIUM: proxy: use dynamic allocation for error dumps

There are two issues with error captures. The first one is that the
capture size is still hard-coded to BUFSIZE regardless of any possible
tune.bufsize setting and of the fact that frontends only capture request
errors and that backends only capture response errors. The second is that
captures are allocated in both directions for all proxies, which start to
count a lot in configs using thousands of proxies.

This patch changes this so that error captures are allocated only when
needed, and of the proper size. It also refrains from dumping a buffer
that was not allocated, which still allows to emit all relevant info
such as flags and HTTP states. This way it is possible to save up to
32 kB of RAM per proxy in the default configuration.
This commit is contained in:
Willy Tarreau 2016-03-31 13:45:10 +02:00
parent 40e1d51068
commit f3764b7993
3 changed files with 12 additions and 7 deletions

View file

@ -221,7 +221,7 @@ struct error_snapshot {
struct server *srv; /* server associated with the error (or NULL) */
struct proxy *oe; /* other end = frontend or backend involved */
struct sockaddr_storage src; /* client's address */
char buf[BUFSIZE]; /* copy of the beginning of the message */
char *buf; /* copy of the beginning of the message (may be NULL) */
};
struct email_alert {

View file

@ -7032,12 +7032,12 @@ static int stats_dump_errors_to_buffer(struct stream_interface *si)
}
/* OK, ptr >= 0, so we have to dump the current line */
while (appctx->ctx.errors.ptr < es->len && appctx->ctx.errors.ptr < sizeof(es->buf)) {
while (es->buf && appctx->ctx.errors.ptr < es->len && appctx->ctx.errors.ptr < global.tune.bufsize) {
int newptr;
int newline;
newline = appctx->ctx.errors.bol;
newptr = dump_text_line(&trash, es->buf, sizeof(es->buf), es->len, &newline, appctx->ctx.errors.ptr);
newptr = dump_text_line(&trash, es->buf, global.tune.bufsize, es->len, &newline, appctx->ctx.errors.ptr);
if (newptr == appctx->ctx.errors.ptr)
return 0;

View file

@ -8382,14 +8382,19 @@ void http_capture_bad_message(struct error_snapshot *es, struct stream *s,
struct channel *chn = msg->chn;
int len1, len2;
es->len = MIN(chn->buf->i, sizeof(es->buf));
es->len = MIN(chn->buf->i, global.tune.bufsize);
len1 = chn->buf->data + chn->buf->size - chn->buf->p;
len1 = MIN(len1, es->len);
len2 = es->len - len1; /* remaining data if buffer wraps */
memcpy(es->buf, chn->buf->p, len1);
if (len2)
memcpy(es->buf + len1, chn->buf->data, len2);
if (!es->buf)
es->buf = malloc(global.tune.bufsize);
if (es->buf) {
memcpy(es->buf, chn->buf->p, len1);
if (len2)
memcpy(es->buf + len1, chn->buf->data, len2);
}
if (msg->err_pos >= 0)
es->pos = msg->err_pos;