[MEDIUM] stats: don't use s->ana_state anymore
The stats handler used to store internal states in s->ana_state. Now we only rely on si->st0 in which we can store as many states as we have possible outputs. This cleans up the stats code a lot and makes it more maintainable. It has also reduced code size by a few hundred bytes.
This commit is contained in:
parent
24955a1000
commit
f5a885fd28
|
@ -39,10 +39,18 @@
|
|||
#define STATS_TYPE_BE 1
|
||||
#define STATS_TYPE_SV 2
|
||||
|
||||
#define STATS_ST_INIT 0
|
||||
#define STATS_ST_REQ 1
|
||||
#define STATS_ST_REP 2
|
||||
#define STATS_ST_CLOSE 3
|
||||
/* unix stats socket states */
|
||||
#define STAT_CLI_INIT 0 /* initial state */
|
||||
#define STAT_CLI_END 1 /* final state, let's close */
|
||||
#define STAT_CLI_GETREQ 2 /* wait for a request */
|
||||
#define STAT_CLI_OUTPUT 3 /* all states after this one are responses */
|
||||
#define STAT_CLI_PROMPT 3 /* display the prompt (first output, same code) */
|
||||
|
||||
#define STAT_CLI_O_HELP 4 /* display help */
|
||||
#define STAT_CLI_O_INFO 5 /* dump info/stats */
|
||||
#define STAT_CLI_O_SESS 6 /* dump sessions */
|
||||
#define STAT_CLI_O_ERR 7 /* dump errors */
|
||||
|
||||
|
||||
int stats_sock_parse_request(struct stream_interface *si, char *line);
|
||||
void stats_io_handler(struct stream_interface *si);
|
||||
|
|
129
src/dumpstats.c
129
src/dumpstats.c
|
@ -232,10 +232,9 @@ int print_csv_header(struct chunk *msg)
|
|||
}
|
||||
|
||||
/* Processes the stats interpreter on the statistics socket. This function is
|
||||
* called from an applet running in a stream interface. Right now we still
|
||||
* support older functions which used to emulate servers and to set
|
||||
* STATS_ST_CLOSE upon completion, but we also support a new interactive mode.
|
||||
* The function returns 1 if the request was understood, otherwise zero.
|
||||
* called from an applet running in a stream interface. The function returns 1
|
||||
* if the request was understood, otherwise zero. It sets si->st0 to a value
|
||||
* designating the function which will have to process the request.
|
||||
*/
|
||||
int stats_sock_parse_request(struct stream_interface *si, char *line)
|
||||
{
|
||||
|
@ -266,7 +265,6 @@ int stats_sock_parse_request(struct stream_interface *si, char *line)
|
|||
while (++arg <= MAX_STATS_ARGS)
|
||||
args[arg] = line;
|
||||
|
||||
si->st0 = 0;
|
||||
s->data_ctx.stats.flags = 0;
|
||||
if (strcmp(args[0], "show") == 0) {
|
||||
if (strcmp(args[1], "stat") == 0) {
|
||||
|
@ -280,20 +278,17 @@ int stats_sock_parse_request(struct stream_interface *si, char *line)
|
|||
s->data_ctx.stats.flags |= STAT_SHOW_STAT;
|
||||
s->data_ctx.stats.flags |= STAT_FMT_CSV;
|
||||
s->data_state = DATA_ST_INIT;
|
||||
s->ana_state = STATS_ST_REP;
|
||||
si->st0 = 3; // stats_dump_raw_to_buffer
|
||||
si->st0 = STAT_CLI_O_INFO; // stats_dump_raw_to_buffer
|
||||
}
|
||||
else if (strcmp(args[1], "info") == 0) {
|
||||
s->data_ctx.stats.flags |= STAT_SHOW_INFO;
|
||||
s->data_ctx.stats.flags |= STAT_FMT_CSV;
|
||||
s->data_state = DATA_ST_INIT;
|
||||
s->ana_state = STATS_ST_REP;
|
||||
si->st0 = 3; // stats_dump_raw_to_buffer
|
||||
si->st0 = STAT_CLI_O_INFO; // stats_dump_raw_to_buffer
|
||||
}
|
||||
else if (strcmp(args[1], "sess") == 0) {
|
||||
s->data_state = DATA_ST_INIT;
|
||||
s->ana_state = STATS_ST_REP;
|
||||
si->st0 = 4; // stats_dump_sess_to_buffer
|
||||
si->st0 = STAT_CLI_O_SESS; // stats_dump_sess_to_buffer
|
||||
}
|
||||
else if (strcmp(args[1], "errors") == 0) {
|
||||
if (*args[2])
|
||||
|
@ -302,8 +297,7 @@ int stats_sock_parse_request(struct stream_interface *si, char *line)
|
|||
s->data_ctx.errors.iid = -1;
|
||||
s->data_ctx.errors.px = NULL;
|
||||
s->data_state = DATA_ST_INIT;
|
||||
s->ana_state = STATS_ST_REP;
|
||||
si->st0 = 5; // stats_dump_errors_to_buffer
|
||||
si->st0 = STAT_CLI_O_ERR; // stats_dump_errors_to_buffer
|
||||
}
|
||||
else { /* neither "stat" nor "info" nor "sess" */
|
||||
return 0;
|
||||
|
@ -316,15 +310,12 @@ int stats_sock_parse_request(struct stream_interface *si, char *line)
|
|||
}
|
||||
|
||||
/* This I/O handler runs as an applet embedded in a stream interface. It is
|
||||
* used to processes I/O from/to the stats unix socket. Right now we still
|
||||
* support older functions which used to emulate servers and to set
|
||||
* STATS_ST_CLOSE upon completion, but we also support a new interactive mode.
|
||||
* The system relies on a request/response flip-flop state machine. We read
|
||||
* a request, then we process it and send the response. Then we can read again.
|
||||
* This could be enhanced a lot but we're still bound to support older output
|
||||
* functions which were designed to work as hijackers.
|
||||
* At the moment, we use si->st0 as the output type, and si->st1 to indicate
|
||||
* whether we're in prompt mode or not.
|
||||
* used to processes I/O from/to the stats unix socket. The system relies on a
|
||||
* state machine handling requests and various responses. We read a request,
|
||||
* then we process it and send the response, and we possibly display a prompt.
|
||||
* Then we can read again. The state is stored in si->st0 and is one of the
|
||||
* STAT_CLI_* constants. si->st1 is used to indicate whether prompt is enabled
|
||||
* or not.
|
||||
*/
|
||||
void stats_io_handler(struct stream_interface *si)
|
||||
{
|
||||
|
@ -338,18 +329,25 @@ void stats_io_handler(struct stream_interface *si)
|
|||
goto out;
|
||||
|
||||
while (1) {
|
||||
if (s->ana_state == STATS_ST_INIT) {
|
||||
if (si->st0 == STAT_CLI_INIT) {
|
||||
/* Stats output not initialized yet */
|
||||
memset(&s->data_ctx.stats, 0, sizeof(s->data_ctx.stats));
|
||||
s->data_source = DATA_SRC_STATS;
|
||||
s->ana_state = STATS_ST_REQ;
|
||||
si->st0 = STAT_CLI_GETREQ;
|
||||
}
|
||||
else if (s->ana_state == STATS_ST_REQ) {
|
||||
else if (si->st0 == STAT_CLI_END) {
|
||||
/* Let's close for real now. We just close the request
|
||||
* side, the conditions below will complete if needed.
|
||||
*/
|
||||
si->shutw(si);
|
||||
break;
|
||||
}
|
||||
else if (si->st0 == STAT_CLI_GETREQ) {
|
||||
reql = buffer_si_peekline(si->ob, trash, sizeof(trash));
|
||||
if (reql <= 0) { /* closed or EOL not found */
|
||||
if (reql == 0)
|
||||
break;
|
||||
s->ana_state = STATS_ST_CLOSE;
|
||||
si->st0 = STAT_CLI_END;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -369,7 +367,7 @@ void stats_io_handler(struct stream_interface *si)
|
|||
*/
|
||||
len = reql - 1;
|
||||
if (trash[len] != '\n') {
|
||||
s->ana_state = STATS_ST_CLOSE;
|
||||
si->st0 = STAT_CLI_END;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -378,77 +376,69 @@ void stats_io_handler(struct stream_interface *si)
|
|||
|
||||
trash[len] = '\0';
|
||||
|
||||
si->st0 = 1; // default to prompt
|
||||
si->st0 = STAT_CLI_PROMPT;
|
||||
if (len) {
|
||||
if (strcmp(trash, "quit") == 0) {
|
||||
s->ana_state = STATS_ST_CLOSE;
|
||||
si->st0 = STAT_CLI_END;
|
||||
continue;
|
||||
}
|
||||
else if (strcmp(trash, "prompt") == 0)
|
||||
si->st1 = !si->st1;
|
||||
else if (strcmp(trash, "help") == 0 ||
|
||||
!stats_sock_parse_request(si, trash))
|
||||
si->st0 = 2; // help
|
||||
si->st0 = STAT_CLI_O_HELP;
|
||||
/* NB: stats_sock_parse_request() may have put
|
||||
* another STAT_CLI_O_* into si->st0.
|
||||
*/
|
||||
}
|
||||
else if (!si->st1) {
|
||||
/* if prompt is disabled, print help on empty lines,
|
||||
* so that the user at least knows how to enable
|
||||
* prompt and find help.
|
||||
*/
|
||||
si->st0 = 2;
|
||||
si->st0 = STAT_CLI_O_HELP;
|
||||
}
|
||||
|
||||
/* re-adjust req buffer */
|
||||
buffer_skip(si->ob, reql);
|
||||
|
||||
s->ana_state = STATS_ST_REP;
|
||||
req->flags |= BF_READ_DONTWAIT; /* we plan to read small requests */
|
||||
}
|
||||
else if (s->ana_state == STATS_ST_REP) {
|
||||
else { /* output functions: first check if the output buffer is closed then abort */
|
||||
if (res->flags & (BF_SHUTR_NOW|BF_SHUTR)) {
|
||||
s->ana_state = STATS_ST_CLOSE;
|
||||
si->st0 = STAT_CLI_END;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (si->st0) {
|
||||
case 2: /* help */
|
||||
case STAT_CLI_O_HELP:
|
||||
if (buffer_feed(si->ib, stats_sock_usage.str, stats_sock_usage.len) < 0)
|
||||
/* message sent or too large for buffer (!) */
|
||||
si->st0 = 1; // send prompt
|
||||
si->st0 = STAT_CLI_PROMPT;
|
||||
break;
|
||||
case 3: /* stats/info dump, should be split later ? */
|
||||
case STAT_CLI_O_INFO:
|
||||
if (stats_dump_raw_to_buffer(s, res))
|
||||
si->st0 = 1; // end of command, send prompt
|
||||
si->st0 = STAT_CLI_PROMPT;
|
||||
break;
|
||||
case 4: /* sessions dump */
|
||||
case STAT_CLI_O_SESS:
|
||||
if (stats_dump_sess_to_buffer(s, res))
|
||||
si->st0 = 1; // end of command, send prompt
|
||||
si->st0 = STAT_CLI_PROMPT;
|
||||
break;
|
||||
case 5: /* errors dump */
|
||||
case STAT_CLI_O_ERR: /* errors dump */
|
||||
if (stats_dump_errors_to_buffer(s, res))
|
||||
si->st0 = 1; // end of command, send prompt
|
||||
si->st0 = STAT_CLI_PROMPT;
|
||||
break;
|
||||
default: /* abnormal state or lack of space for prompt */
|
||||
si->st0 = 1; // return to prompt
|
||||
default: /* abnormal state */
|
||||
si->st0 = STAT_CLI_PROMPT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (si->st0 == 1) { /* post-command prompt (LF or LF + '> ') */
|
||||
if (!si->st1) { /* non-interactive mode */
|
||||
if (buffer_feed(si->ib, "\n", 1) < 0)
|
||||
si->st0 = 0; // end of output
|
||||
}
|
||||
else { /* interactive mode */
|
||||
if (buffer_feed(si->ib, "\n> ", 3) < 0)
|
||||
si->st0 = 0; // end of output
|
||||
}
|
||||
/* The post-command prompt is either LF alone or LF + '> ' in interactive mode */
|
||||
if (si->st0 == STAT_CLI_PROMPT) {
|
||||
if (buffer_feed(si->ib, si->st1 ? "\n> " : "\n", si->st1 ? 3 : 1) < 0)
|
||||
si->st0 = STAT_CLI_GETREQ;
|
||||
}
|
||||
|
||||
/* If the output functions are still there, it means
|
||||
* they require more room.
|
||||
*/
|
||||
if (si->st0 > 0) {
|
||||
s->ana_state = STATS_ST_REP; /* some old applets still force CLOSE */
|
||||
/* If the output functions are still there, it means they require more room. */
|
||||
if (si->st0 >= STAT_CLI_OUTPUT) {
|
||||
si->flags |= SI_FL_WAIT_ROOM;
|
||||
break;
|
||||
}
|
||||
|
@ -459,24 +449,16 @@ void stats_io_handler(struct stream_interface *si)
|
|||
* to be sent in non-interactive mode.
|
||||
*/
|
||||
if ((res->flags & (BF_SHUTW|BF_SHUTW_NOW)) || (!si->st1 && !req->send_max)) {
|
||||
s->ana_state = STATS_ST_CLOSE;
|
||||
si->st0 = STAT_CLI_END;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* switch state back to ST_REQ to read next requests */
|
||||
s->ana_state = STATS_ST_REQ;
|
||||
}
|
||||
else if (s->ana_state == STATS_ST_CLOSE) {
|
||||
/* Let's close for real now. We just close the request
|
||||
* side, the conditions below will complete if needed.
|
||||
*/
|
||||
si->shutw(si);
|
||||
s->ana_state = 0;
|
||||
break;
|
||||
/* switch state back to GETREQ to read next requests */
|
||||
si->st0 = STAT_CLI_GETREQ;
|
||||
}
|
||||
}
|
||||
|
||||
if ((res->flags & BF_SHUTR) && (si->state == SI_ST_EST) && (s->ana_state != STATS_ST_REQ)) {
|
||||
if ((res->flags & BF_SHUTR) && (si->state == SI_ST_EST) && (si->st0 != STAT_CLI_GETREQ)) {
|
||||
DPRINTF(stderr, "%s@%d: si to buf closed. req=%08x, res=%08x, st=%d\n",
|
||||
__FUNCTION__, __LINE__, req->flags, res->flags, si->state);
|
||||
/* Other size has closed, let's abort if we have no more processing to do
|
||||
|
@ -487,7 +469,7 @@ void stats_io_handler(struct stream_interface *si)
|
|||
si->shutw(si);
|
||||
}
|
||||
|
||||
if ((req->flags & BF_SHUTW) && (si->state == SI_ST_EST) && (s->ana_state != STATS_ST_REP)) {
|
||||
if ((req->flags & BF_SHUTW) && (si->state == SI_ST_EST) && (si->st0 < STAT_CLI_OUTPUT)) {
|
||||
DPRINTF(stderr, "%s@%d: buf to si closed. req=%08x, res=%08x, st=%d\n",
|
||||
__FUNCTION__, __LINE__, req->flags, res->flags, si->state);
|
||||
/* We have no more processing to do, and nothing more to send, and
|
||||
|
@ -513,7 +495,6 @@ void stats_io_handler(struct stream_interface *si)
|
|||
if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO)) {
|
||||
/* check that we have released everything then unregister */
|
||||
stream_int_unregister_handler(si);
|
||||
s->ana_state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -471,7 +471,8 @@ int uxst_event_accept(int fd) {
|
|||
|
||||
stream_int_register_handler(&s->si[1], stats_io_handler);
|
||||
s->si[1].private = s;
|
||||
s->si[1].st0 = s->si[1].st1 = 0;
|
||||
s->si[1].st1 = 0;
|
||||
s->si[1].st0 = STAT_CLI_INIT;
|
||||
|
||||
s->srv = s->prev_srv = s->srv_conn = NULL;
|
||||
s->pend_pos = NULL;
|
||||
|
|
Loading…
Reference in New Issue