CLEANUP: proxy/cli: take the "show errors" context definition out of the appctx

This makes use of the generic command context allocation so that the
appctx doesn't have to declare a specific one anymore. The context is
created during parsing.

The code still has room for improvement, such as in the "flags" field
where bits are hard-coded, but they weren't modified.
This commit is contained in:
Willy Tarreau 2022-05-03 11:24:24 +02:00
parent 6177cfc3b5
commit 0fd8f0e236
2 changed files with 56 additions and 51 deletions

View File

@ -149,14 +149,6 @@ struct appctx {
int iid, type, sid; /* proxy id, type and service id if bounding of stats is enabled */ int iid, type, sid; /* proxy id, type and service id if bounding of stats is enabled */
int st_code; /* the status code returned by an action */ int st_code; /* the status code returned by an action */
} stats; } stats;
struct {
int iid; /* if >= 0, ID of the proxy to filter on */
struct proxy *px; /* current proxy being dumped, NULL = not started yet. */
unsigned int flag; /* bit0: buffer being dumped, 0 = req, 1 = resp ; bit1=skip req ; bit2=skip resp. */
unsigned int ev_id; /* event ID of error being dumped */
int ptr; /* <0: headers, >=0 : text pointer to restart from */
int bol; /* pointer to beginning of current line */
} errors;
struct { struct {
void *target; /* table we want to dump, or NULL for all */ void *target; /* table we want to dump, or NULL for all */
struct stktable *t; /* table being currently dumped (first if NULL) */ struct stktable *t; /* table being currently dumped (first if NULL) */

View File

@ -21,7 +21,7 @@
#include <haproxy/acl.h> #include <haproxy/acl.h>
#include <haproxy/api.h> #include <haproxy/api.h>
#include <haproxy/applet-t.h> #include <haproxy/applet.h>
#include <haproxy/capture-t.h> #include <haproxy/capture-t.h>
#include <haproxy/cfgparse.h> #include <haproxy/cfgparse.h>
#include <haproxy/cli.h> #include <haproxy/cli.h>
@ -3083,11 +3083,23 @@ static int cli_parse_enable_frontend(char **args, char *payload, struct appctx *
return 1; return 1;
} }
/* appctx context used during "show errors" */
struct show_errors_ctx {
struct proxy *px; /* current proxy being dumped, NULL = not started yet. */
unsigned int flag; /* bit0: buffer being dumped, 0 = req, 1 = resp ; bit1=skip req ; bit2=skip resp. */
unsigned int ev_id; /* event ID of error being dumped */
int iid; /* if >= 0, ID of the proxy to filter on */
int ptr; /* <0: headers, >=0 : text pointer to restart from */
int bol; /* pointer to beginning of current line */
};
/* "show errors" handler for the CLI. Returns 0 if wants to continue, 1 to stop /* "show errors" handler for the CLI. Returns 0 if wants to continue, 1 to stop
* now. * now.
*/ */
static int cli_parse_show_errors(char **args, char *payload, struct appctx *appctx, void *private) static int cli_parse_show_errors(char **args, char *payload, struct appctx *appctx, void *private)
{ {
struct show_errors_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
if (!cli_has_level(appctx, ACCESS_LVL_OPER)) if (!cli_has_level(appctx, ACCESS_LVL_OPER))
return 1; return 1;
@ -3096,22 +3108,22 @@ static int cli_parse_show_errors(char **args, char *payload, struct appctx *appc
px = proxy_find_by_name(args[2], 0, 0); px = proxy_find_by_name(args[2], 0, 0);
if (px) if (px)
appctx->ctx.errors.iid = px->uuid; ctx->iid = px->uuid;
else else
appctx->ctx.errors.iid = atoi(args[2]); ctx->iid = atoi(args[2]);
if (!appctx->ctx.errors.iid) if (!ctx->iid)
return cli_err(appctx, "No such proxy.\n"); return cli_err(appctx, "No such proxy.\n");
} }
else else
appctx->ctx.errors.iid = -1; // dump all proxies ctx->iid = -1; // dump all proxies
appctx->ctx.errors.flag = 0; ctx->flag = 0;
if (strcmp(args[3], "request") == 0) if (strcmp(args[3], "request") == 0)
appctx->ctx.errors.flag |= 4; // ignore response ctx->flag |= 4; // ignore response
else if (strcmp(args[3], "response") == 0) else if (strcmp(args[3], "response") == 0)
appctx->ctx.errors.flag |= 2; // ignore request ctx->flag |= 2; // ignore request
appctx->ctx.errors.px = NULL; ctx->px = NULL;
return 0; return 0;
} }
@ -3121,6 +3133,7 @@ static int cli_parse_show_errors(char **args, char *payload, struct appctx *appc
*/ */
static int cli_io_handler_show_errors(struct appctx *appctx) static int cli_io_handler_show_errors(struct appctx *appctx)
{ {
struct show_errors_ctx *ctx = appctx->svcctx;
struct conn_stream *cs = appctx->owner; struct conn_stream *cs = appctx->owner;
extern const char *monthname[12]; extern const char *monthname[12];
@ -3129,7 +3142,7 @@ static int cli_io_handler_show_errors(struct appctx *appctx)
chunk_reset(&trash); chunk_reset(&trash);
if (!appctx->ctx.errors.px) { if (!ctx->px) {
/* the function had not been called yet, let's prepare the /* the function had not been called yet, let's prepare the
* buffer for a response. * buffer for a response.
*/ */
@ -3144,39 +3157,39 @@ static int cli_io_handler_show_errors(struct appctx *appctx)
if (ci_putchk(cs_ic(cs), &trash) == -1) if (ci_putchk(cs_ic(cs), &trash) == -1)
goto cant_send; goto cant_send;
appctx->ctx.errors.px = proxies_list; ctx->px = proxies_list;
appctx->ctx.errors.bol = 0; ctx->bol = 0;
appctx->ctx.errors.ptr = -1; ctx->ptr = -1;
} }
/* we have two inner loops here, one for the proxy, the other one for /* we have two inner loops here, one for the proxy, the other one for
* the buffer. * the buffer.
*/ */
while (appctx->ctx.errors.px) { while (ctx->px) {
struct error_snapshot *es; struct error_snapshot *es;
HA_RWLOCK_RDLOCK(PROXY_LOCK, &appctx->ctx.errors.px->lock); HA_RWLOCK_RDLOCK(PROXY_LOCK, &ctx->px->lock);
if ((appctx->ctx.errors.flag & 1) == 0) { if ((ctx->flag & 1) == 0) {
es = appctx->ctx.errors.px->invalid_req; es = ctx->px->invalid_req;
if (appctx->ctx.errors.flag & 2) // skip req if (ctx->flag & 2) // skip req
goto next; goto next;
} }
else { else {
es = appctx->ctx.errors.px->invalid_rep; es = ctx->px->invalid_rep;
if (appctx->ctx.errors.flag & 4) // skip resp if (ctx->flag & 4) // skip resp
goto next; goto next;
} }
if (!es) if (!es)
goto next; goto next;
if (appctx->ctx.errors.iid >= 0 && if (ctx->iid >= 0 &&
appctx->ctx.errors.px->uuid != appctx->ctx.errors.iid && ctx->px->uuid != ctx->iid &&
(!es->oe || es->oe->uuid != appctx->ctx.errors.iid)) (!es->oe || es->oe->uuid != ctx->iid))
goto next; goto next;
if (appctx->ctx.errors.ptr < 0) { if (ctx->ptr < 0) {
/* just print headers now */ /* just print headers now */
char pn[INET6_ADDRSTRLEN]; char pn[INET6_ADDRSTRLEN];
@ -3197,12 +3210,12 @@ static int cli_io_handler_show_errors(struct appctx *appctx)
port = 0; port = 0;
} }
switch (appctx->ctx.errors.flag & 1) { switch (ctx->flag & 1) {
case 0: case 0:
chunk_appendf(&trash, chunk_appendf(&trash,
" frontend %s (#%d): invalid request\n" " frontend %s (#%d): invalid request\n"
" backend %s (#%d)", " backend %s (#%d)",
appctx->ctx.errors.px->id, appctx->ctx.errors.px->uuid, ctx->px->id, ctx->px->uuid,
(es->oe && es->oe->cap & PR_CAP_BE) ? es->oe->id : "<NONE>", (es->oe && es->oe->cap & PR_CAP_BE) ? es->oe->id : "<NONE>",
(es->oe && es->oe->cap & PR_CAP_BE) ? es->oe->uuid : -1); (es->oe && es->oe->cap & PR_CAP_BE) ? es->oe->uuid : -1);
break; break;
@ -3210,7 +3223,7 @@ static int cli_io_handler_show_errors(struct appctx *appctx)
chunk_appendf(&trash, chunk_appendf(&trash,
" backend %s (#%d): invalid response\n" " backend %s (#%d): invalid response\n"
" frontend %s (#%d)", " frontend %s (#%d)",
appctx->ctx.errors.px->id, appctx->ctx.errors.px->uuid, ctx->px->id, ctx->px->uuid,
es->oe ? es->oe->id : "<NONE>" , es->oe ? es->oe->uuid : -1); es->oe ? es->oe->id : "<NONE>" , es->oe ? es->oe->uuid : -1);
break; break;
} }
@ -3234,11 +3247,11 @@ static int cli_io_handler_show_errors(struct appctx *appctx)
if (ci_putchk(cs_ic(cs), &trash) == -1) if (ci_putchk(cs_ic(cs), &trash) == -1)
goto cant_send_unlock; goto cant_send_unlock;
appctx->ctx.errors.ptr = 0; ctx->ptr = 0;
appctx->ctx.errors.ev_id = es->ev_id; ctx->ev_id = es->ev_id;
} }
if (appctx->ctx.errors.ev_id != es->ev_id) { if (ctx->ev_id != es->ev_id) {
/* the snapshot changed while we were dumping it */ /* the snapshot changed while we were dumping it */
chunk_appendf(&trash, chunk_appendf(&trash,
" WARNING! update detected on this snapshot, dump interrupted. Please re-check!\n"); " WARNING! update detected on this snapshot, dump interrupted. Please re-check!\n");
@ -3249,35 +3262,35 @@ static int cli_io_handler_show_errors(struct appctx *appctx)
} }
/* OK, ptr >= 0, so we have to dump the current line */ /* OK, ptr >= 0, so we have to dump the current line */
while (appctx->ctx.errors.ptr < es->buf_len && appctx->ctx.errors.ptr < global.tune.bufsize) { while (ctx->ptr < es->buf_len && ctx->ptr < global.tune.bufsize) {
int newptr; int newptr;
int newline; int newline;
newline = appctx->ctx.errors.bol; newline = ctx->bol;
newptr = dump_text_line(&trash, es->buf, global.tune.bufsize, es->buf_len, &newline, appctx->ctx.errors.ptr); newptr = dump_text_line(&trash, es->buf, global.tune.bufsize, es->buf_len, &newline, ctx->ptr);
if (newptr == appctx->ctx.errors.ptr) if (newptr == ctx->ptr)
goto cant_send_unlock; goto cant_send_unlock;
if (ci_putchk(cs_ic(cs), &trash) == -1) if (ci_putchk(cs_ic(cs), &trash) == -1)
goto cant_send_unlock; goto cant_send_unlock;
appctx->ctx.errors.ptr = newptr; ctx->ptr = newptr;
appctx->ctx.errors.bol = newline; ctx->bol = newline;
}; };
next: next:
HA_RWLOCK_RDUNLOCK(PROXY_LOCK, &appctx->ctx.errors.px->lock); HA_RWLOCK_RDUNLOCK(PROXY_LOCK, &ctx->px->lock);
appctx->ctx.errors.bol = 0; ctx->bol = 0;
appctx->ctx.errors.ptr = -1; ctx->ptr = -1;
appctx->ctx.errors.flag ^= 1; ctx->flag ^= 1;
if (!(appctx->ctx.errors.flag & 1)) if (!(ctx->flag & 1))
appctx->ctx.errors.px = appctx->ctx.errors.px->next; ctx->px = ctx->px->next;
} }
/* dump complete */ /* dump complete */
return 1; return 1;
cant_send_unlock: cant_send_unlock:
HA_RWLOCK_RDUNLOCK(PROXY_LOCK, &appctx->ctx.errors.px->lock); HA_RWLOCK_RDUNLOCK(PROXY_LOCK, &ctx->px->lock);
cant_send: cant_send:
cs_rx_room_blk(cs); cs_rx_room_blk(cs);
return 0; return 0;