MAJOR: cli: Update the CLI applet to handle its own buffers
It is the third applet to be refactored to use its own buffers. In addition to the CLI applet, some I/O handlers of CLI commands were also updated, especially the stats ones. Some command I/O handlers were updated to use applet's buffers instead of channels ones.
This commit is contained in:
parent
b8ca114031
commit
f37ddbeb4b
90
src/cli.c
90
src/cli.c
@ -910,34 +910,36 @@ static int cli_output_msg(struct appctx *appctx, const char *msg, int severity,
|
|||||||
*/
|
*/
|
||||||
static void cli_io_handler(struct appctx *appctx)
|
static void cli_io_handler(struct appctx *appctx)
|
||||||
{
|
{
|
||||||
struct stconn *sc = appctx_sc(appctx);
|
|
||||||
struct channel *res = sc_ic(sc);
|
|
||||||
struct bind_conf *bind_conf = strm_li(__sc_strm(sc))->bind_conf;
|
|
||||||
int reql;
|
int reql;
|
||||||
int len;
|
int len;
|
||||||
int lf = 0;
|
int lf = 0;
|
||||||
|
|
||||||
if (unlikely(se_fl_test(appctx->sedesc, (SE_FL_EOS|SE_FL_ERROR)))) {
|
if (applet_fl_test(appctx, APPCTX_FL_OUTBLK_ALLOC|APPCTX_FL_OUTBLK_FULL))
|
||||||
co_skip(sc_oc(sc), co_data(sc_oc(sc)));
|
goto out;
|
||||||
|
|
||||||
|
if (!appctx_get_buf(appctx, &appctx->outbuf)) {
|
||||||
|
applet_fl_set(appctx, APPCTX_FL_OUTBLK_ALLOC);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the input buffer is available. */
|
if (unlikely(applet_fl_test(appctx, APPCTX_FL_EOS|APPCTX_FL_ERROR))) {
|
||||||
if (!b_size(&res->buf)) {
|
appctx->st0 = CLI_ST_END;
|
||||||
sc_need_room(sc, 0);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (appctx->st0 == CLI_ST_INIT) {
|
if (appctx->st0 == CLI_ST_INIT) {
|
||||||
/* reset severity to default at init */
|
/* reset severity to default at init */
|
||||||
|
struct stconn *sc = appctx_sc(appctx);
|
||||||
|
struct bind_conf *bind_conf = strm_li(__sc_strm(sc))->bind_conf;
|
||||||
|
|
||||||
appctx->cli_severity_output = bind_conf->severity_output;
|
appctx->cli_severity_output = bind_conf->severity_output;
|
||||||
applet_reset_svcctx(appctx);
|
applet_reset_svcctx(appctx);
|
||||||
appctx->st0 = CLI_ST_GETREQ;
|
appctx->st0 = CLI_ST_GETREQ;
|
||||||
appctx->cli_level = bind_conf->level;
|
appctx->cli_level = bind_conf->level;
|
||||||
}
|
}
|
||||||
else if (appctx->st0 == CLI_ST_END) {
|
else if (appctx->st0 == CLI_ST_END) {
|
||||||
se_fl_set(appctx->sedesc, SE_FL_EOS);
|
applet_set_eos(appctx);
|
||||||
free_trash_chunk(appctx->chunk);
|
free_trash_chunk(appctx->chunk);
|
||||||
appctx->chunk = NULL;
|
appctx->chunk = NULL;
|
||||||
break;
|
break;
|
||||||
@ -960,8 +962,8 @@ static void cli_io_handler(struct appctx *appctx)
|
|||||||
/* ensure we have some output room left in the event we
|
/* ensure we have some output room left in the event we
|
||||||
* would want to return some info right after parsing.
|
* would want to return some info right after parsing.
|
||||||
*/
|
*/
|
||||||
if (buffer_almost_full(sc_ib(sc))) {
|
if (buffer_almost_full(&appctx->outbuf)) {
|
||||||
sc_need_room(sc, b_size(&res->buf) / 2);
|
applet_fl_set(appctx, APPCTX_FL_OUTBLK_FULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -972,19 +974,30 @@ static void cli_io_handler(struct appctx *appctx)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (appctx->st1 & APPCTX_CLI_ST1_PAYLOAD)
|
if (appctx->st1 & APPCTX_CLI_ST1_PAYLOAD)
|
||||||
reql = co_getline(sc_oc(sc), str,
|
reql = b_getline(&appctx->inbuf, 0, b_data(&appctx->inbuf), str,
|
||||||
appctx->chunk->size - appctx->chunk->data - 1);
|
appctx->chunk->size - appctx->chunk->data - 1);
|
||||||
else
|
else
|
||||||
reql = co_getdelim(sc_oc(sc), str,
|
reql = b_getdelim(&appctx->inbuf, 0, b_data(&appctx->inbuf), str,
|
||||||
appctx->chunk->size - appctx->chunk->data - 1,
|
appctx->chunk->size - appctx->chunk->data - 1,
|
||||||
"\n;", '\\');
|
"\n;", '\\');
|
||||||
|
|
||||||
if (reql <= 0) { /* closed or EOL not found */
|
if (!reql) {
|
||||||
if (reql == 0)
|
/* Line not found. Report an error if the input buffer is full, if there is not
|
||||||
break;
|
* enough space in the chunk or if a shutdown occurred.
|
||||||
se_fl_set(appctx->sedesc, SE_FL_ERROR);
|
* Otherwise, wait for more data */
|
||||||
appctx->st0 = CLI_ST_END;
|
if (applet_fl_test(appctx, APPCTX_FL_INBLK_FULL) ||
|
||||||
continue;
|
b_data(&appctx->inbuf) > appctx->chunk->size - appctx->chunk->data - 1) {
|
||||||
|
applet_set_eos(appctx);
|
||||||
|
applet_set_error(appctx);
|
||||||
|
cli_err(appctx, "The command is too big for the buffer size. Please change tune.bufsize in the configuration to use a bigger command.\n");
|
||||||
|
goto cli_output;
|
||||||
|
}
|
||||||
|
if (se_fl_test(appctx->sedesc, SE_FL_SHW)) {
|
||||||
|
applet_set_error(appctx);
|
||||||
|
appctx->st0 = CLI_ST_END;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str[reql-1] == '\n')
|
if (str[reql-1] == '\n')
|
||||||
@ -996,12 +1009,8 @@ static void cli_io_handler(struct appctx *appctx)
|
|||||||
*/
|
*/
|
||||||
len = reql - 1;
|
len = reql - 1;
|
||||||
if (str[len] != '\n' && str[len] != ';') {
|
if (str[len] != '\n' && str[len] != ';') {
|
||||||
se_fl_set(appctx->sedesc, SE_FL_ERROR);
|
applet_set_eos(appctx);
|
||||||
if (reql == appctx->chunk->size - appctx->chunk->data - 1) {
|
applet_set_error(appctx);
|
||||||
cli_err(appctx, "The command is too big for the buffer size. Please change tune.bufsize in the configuration to use a bigger command.\n");
|
|
||||||
co_skip(sc_oc(sc), co_data(sc_oc(sc)));
|
|
||||||
goto cli_output;
|
|
||||||
}
|
|
||||||
appctx->st0 = CLI_ST_END;
|
appctx->st0 = CLI_ST_END;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1082,8 +1091,7 @@ static void cli_io_handler(struct appctx *appctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* re-adjust req buffer */
|
/* re-adjust req buffer */
|
||||||
co_skip(sc_oc(sc), reql);
|
b_del(&appctx->inbuf, reql);
|
||||||
sc_opposite(sc)->flags |= SC_FL_RCV_ONCE; /* we plan to read small requests */
|
|
||||||
}
|
}
|
||||||
else { /* output functions */
|
else { /* output functions */
|
||||||
struct cli_print_ctx *ctx;
|
struct cli_print_ctx *ctx;
|
||||||
@ -1205,10 +1213,10 @@ static void cli_io_handler(struct appctx *appctx)
|
|||||||
* non-interactive mode.
|
* non-interactive mode.
|
||||||
*/
|
*/
|
||||||
if ((appctx->st1 & (APPCTX_CLI_ST1_PROMPT|APPCTX_CLI_ST1_PAYLOAD|APPCTX_CLI_ST1_LASTCMD)) == APPCTX_CLI_ST1_LASTCMD) {
|
if ((appctx->st1 & (APPCTX_CLI_ST1_PROMPT|APPCTX_CLI_ST1_PAYLOAD|APPCTX_CLI_ST1_LASTCMD)) == APPCTX_CLI_ST1_LASTCMD) {
|
||||||
se_fl_set(appctx->sedesc, SE_FL_EOI);
|
applet_set_eoi(appctx);
|
||||||
appctx->st0 = CLI_ST_END;
|
appctx->st0 = CLI_ST_END;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* switch state back to GETREQ to read next requests */
|
/* switch state back to GETREQ to read next requests */
|
||||||
applet_reset_svcctx(appctx);
|
applet_reset_svcctx(appctx);
|
||||||
@ -1225,7 +1233,7 @@ static void cli_io_handler(struct appctx *appctx)
|
|||||||
* refills the buffer with new bytes in non-interactive
|
* refills the buffer with new bytes in non-interactive
|
||||||
* mode, avoiding to close on apparently empty commands.
|
* mode, avoiding to close on apparently empty commands.
|
||||||
*/
|
*/
|
||||||
if (co_data(sc_oc(sc))) {
|
if (b_data(&appctx->inbuf)) {
|
||||||
appctx_wakeup(appctx);
|
appctx_wakeup(appctx);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -1233,6 +1241,11 @@ static void cli_io_handler(struct appctx *appctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
if (appctx->st0 == CLI_ST_END) {
|
||||||
|
/* eat the whole request */
|
||||||
|
b_reset(&appctx->inbuf);
|
||||||
|
applet_fl_clr(appctx, APPCTX_FL_INBLK_FULL);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2131,7 +2144,7 @@ static int cli_io_handler_wait(struct appctx *appctx)
|
|||||||
|
|
||||||
wait:
|
wait:
|
||||||
/* Stop waiting upon close/abort/error */
|
/* Stop waiting upon close/abort/error */
|
||||||
if (unlikely(se_fl_test(appctx->sedesc, SE_FL_SHW))) {
|
if (unlikely(se_fl_test(appctx->sedesc, SE_FL_SHW)) && !b_data(&appctx->inbuf)) {
|
||||||
ctx->error = CLI_WAIT_ERR_INTR;
|
ctx->error = CLI_WAIT_ERR_INTR;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -2139,6 +2152,7 @@ static int cli_io_handler_wait(struct appctx *appctx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* release structs allocated by "delete server" */
|
/* release structs allocated by "delete server" */
|
||||||
static void cli_release_wait(struct appctx *appctx)
|
static void cli_release_wait(struct appctx *appctx)
|
||||||
{
|
{
|
||||||
@ -3523,6 +3537,8 @@ static struct applet cli_applet = {
|
|||||||
.obj_type = OBJ_TYPE_APPLET,
|
.obj_type = OBJ_TYPE_APPLET,
|
||||||
.name = "<CLI>", /* used for logging */
|
.name = "<CLI>", /* used for logging */
|
||||||
.fct = cli_io_handler,
|
.fct = cli_io_handler,
|
||||||
|
.rcv_buf = appctx_raw_rcv_buf,
|
||||||
|
.snd_buf = appctx_raw_snd_buf,
|
||||||
.release = cli_release_handler,
|
.release = cli_release_handler,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3531,6 +3547,8 @@ static struct applet mcli_applet = {
|
|||||||
.obj_type = OBJ_TYPE_APPLET,
|
.obj_type = OBJ_TYPE_APPLET,
|
||||||
.name = "<MCLI>", /* used for logging */
|
.name = "<MCLI>", /* used for logging */
|
||||||
.fct = cli_io_handler,
|
.fct = cli_io_handler,
|
||||||
|
.rcv_buf = appctx_raw_rcv_buf,
|
||||||
|
.snd_buf = appctx_raw_snd_buf,
|
||||||
.release = cli_release_handler,
|
.release = cli_release_handler,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -190,7 +190,6 @@ err:
|
|||||||
static int hc_cli_io_handler(struct appctx *appctx)
|
static int hc_cli_io_handler(struct appctx *appctx)
|
||||||
{
|
{
|
||||||
struct hcli_svc_ctx *ctx = appctx->svcctx;
|
struct hcli_svc_ctx *ctx = appctx->svcctx;
|
||||||
struct stconn *sc = appctx_sc(appctx);
|
|
||||||
struct httpclient *hc = ctx->hc;
|
struct httpclient *hc = ctx->hc;
|
||||||
struct http_hdr *hdrs, *hdr;
|
struct http_hdr *hdrs, *hdr;
|
||||||
|
|
||||||
@ -217,10 +216,7 @@ static int hc_cli_io_handler(struct appctx *appctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->flags & HC_F_RES_BODY) {
|
if (ctx->flags & HC_F_RES_BODY) {
|
||||||
int ret;
|
httpclient_res_xfer(hc, &appctx->outbuf);
|
||||||
|
|
||||||
ret = httpclient_res_xfer(hc, sc_ib(sc));
|
|
||||||
channel_add_input(sc_ic(sc), ret); /* forward what we put in the buffer channel */
|
|
||||||
|
|
||||||
/* remove the flag if the buffer was emptied */
|
/* remove the flag if the buffer was emptied */
|
||||||
if (httpclient_data(hc))
|
if (httpclient_data(hc))
|
||||||
|
@ -3177,7 +3177,6 @@ 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 show_errors_ctx *ctx = appctx->svcctx;
|
||||||
struct stconn *sc = appctx_sc(appctx);
|
|
||||||
extern const char *monthname[12];
|
extern const char *monthname[12];
|
||||||
|
|
||||||
chunk_reset(&trash);
|
chunk_reset(&trash);
|
||||||
@ -3309,7 +3308,7 @@ static int cli_io_handler_show_errors(struct appctx *appctx)
|
|||||||
newline = ctx->bol;
|
newline = ctx->bol;
|
||||||
newptr = dump_text_line(&trash, es->buf, global.tune.bufsize, es->buf_len, &newline, ctx->ptr);
|
newptr = dump_text_line(&trash, es->buf, global.tune.bufsize, es->buf_len, &newline, ctx->ptr);
|
||||||
if (newptr == ctx->ptr) {
|
if (newptr == ctx->ptr) {
|
||||||
sc_need_room(sc, 0);
|
applet_fl_set(appctx, APPCTX_FL_OUTBLK_FULL);
|
||||||
goto cant_send_unlock;
|
goto cant_send_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,10 +346,8 @@ int stats_is_full(struct appctx *appctx, struct buffer *buf, struct htx *htx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
struct channel *rep = sc_ic(appctx_sc(appctx));
|
if (buffer_almost_full(&appctx->outbuf)) {
|
||||||
|
applet_fl_set(appctx, APPCTX_FL_OUTBLK_FULL);
|
||||||
if (buffer_almost_full(&rep->buf)) {
|
|
||||||
sc_need_room(appctx_sc(appctx), b_size(&rep->buf) / 2);
|
|
||||||
goto full;
|
goto full;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user