[CLEANUP] stats: make all dump functions only rely on the stream interface

This will be needed to move the applet-specific data out of the session.
This commit is contained in:
Willy Tarreau 2011-02-13 15:27:22 +01:00
parent 75581aebb0
commit 5ec29ffa42
2 changed files with 74 additions and 74 deletions

View File

@ -67,12 +67,12 @@ extern struct si_applet cli_applet;
int stats_accept(struct session *s); int stats_accept(struct session *s);
int stats_sock_parse_request(struct stream_interface *si, char *line); int stats_sock_parse_request(struct stream_interface *si, char *line);
void stats_io_handler(struct stream_interface *si); void stats_io_handler(struct stream_interface *si);
int stats_dump_raw_to_buffer(struct session *s, struct buffer *rep); int stats_dump_raw_to_buffer(struct stream_interface *si);
int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri); int stats_dump_http(struct stream_interface *si, struct uri_auth *uri);
int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri); int stats_dump_proxy(struct stream_interface *si, struct proxy *px, struct uri_auth *uri);
int stats_dump_sess_to_buffer(struct session *s, struct buffer *rep); int stats_dump_sess_to_buffer(struct stream_interface *si);
int stats_dump_table_to_buffer(struct session *s, struct buffer *rep); int stats_dump_table_to_buffer(struct stream_interface *si);
int stats_dump_errors_to_buffer(struct session *s, struct buffer *rep); int stats_dump_errors_to_buffer(struct stream_interface *si);
#endif /* _PROTO_DUMPSTATS_H */ #endif /* _PROTO_DUMPSTATS_H */

View File

@ -953,19 +953,19 @@ static void cli_io_handler(struct stream_interface *si)
si->applet.st0 = STAT_CLI_PROMPT; si->applet.st0 = STAT_CLI_PROMPT;
break; break;
case STAT_CLI_O_INFO: case STAT_CLI_O_INFO:
if (stats_dump_raw_to_buffer(s, res)) if (stats_dump_raw_to_buffer(si))
si->applet.st0 = STAT_CLI_PROMPT; si->applet.st0 = STAT_CLI_PROMPT;
break; break;
case STAT_CLI_O_SESS: case STAT_CLI_O_SESS:
if (stats_dump_sess_to_buffer(s, res)) if (stats_dump_sess_to_buffer(si))
si->applet.st0 = STAT_CLI_PROMPT; si->applet.st0 = STAT_CLI_PROMPT;
break; break;
case STAT_CLI_O_ERR: /* errors dump */ case STAT_CLI_O_ERR: /* errors dump */
if (stats_dump_errors_to_buffer(s, res)) if (stats_dump_errors_to_buffer(si))
si->applet.st0 = STAT_CLI_PROMPT; si->applet.st0 = STAT_CLI_PROMPT;
break; break;
case STAT_CLI_O_TAB: case STAT_CLI_O_TAB:
if (stats_dump_table_to_buffer(s, res)) if (stats_dump_table_to_buffer(si))
si->applet.st0 = STAT_CLI_PROMPT; si->applet.st0 = STAT_CLI_PROMPT;
break; break;
default: /* abnormal state */ default: /* abnormal state */
@ -1038,15 +1038,15 @@ static void cli_io_handler(struct stream_interface *si)
} }
} }
/* This function is called to send output to the response buffer. /* This function dumps statistics onto the stream interface's read buffer.
* It dumps statistics onto the output buffer <rep> owned by session <s>. * The data_ctx must have been zeroed first, and the flags properly set.
* s->data_ctx must have been zeroed first, and the flags properly set.
* It returns 0 as long as it does not complete, non-zero upon completion. * It returns 0 as long as it does not complete, non-zero upon completion.
* Some states are not used but it makes the code more similar to other * Some states are not used but it makes the code more similar to other
* functions which handle stats too. * functions which handle stats too.
*/ */
int stats_dump_raw_to_buffer(struct session *s, struct buffer *rep) int stats_dump_raw_to_buffer(struct stream_interface *si)
{ {
struct session *s = si->applet.private;
struct proxy *px; struct proxy *px;
struct chunk msg; struct chunk msg;
unsigned int up; unsigned int up;
@ -1062,7 +1062,7 @@ int stats_dump_raw_to_buffer(struct session *s, struct buffer *rep)
case DATA_ST_HEAD: case DATA_ST_HEAD:
if (s->data_ctx.stats.flags & STAT_SHOW_STAT) { if (s->data_ctx.stats.flags & STAT_SHOW_STAT) {
print_csv_header(&msg); print_csv_header(&msg);
if (buffer_feed_chunk(rep, &msg) >= 0) if (buffer_feed_chunk(si->ib, &msg) >= 0)
return 0; return 0;
} }
@ -1106,7 +1106,7 @@ int stats_dump_raw_to_buffer(struct session *s, struct buffer *rep)
nb_tasks_cur, run_queue_cur, nb_tasks_cur, run_queue_cur,
global.node, global.desc?global.desc:"" global.node, global.desc?global.desc:""
); );
if (buffer_feed_chunk(rep, &msg) >= 0) if (buffer_feed_chunk(si->ib, &msg) >= 0)
return 0; return 0;
} }
@ -1127,7 +1127,7 @@ int stats_dump_raw_to_buffer(struct session *s, struct buffer *rep)
/* skip the disabled proxies and non-networked ones */ /* skip the disabled proxies and non-networked ones */
if (px->state != PR_STSTOPPED && if (px->state != PR_STSTOPPED &&
(px->cap & (PR_CAP_FE | PR_CAP_BE))) { (px->cap & (PR_CAP_FE | PR_CAP_BE))) {
if (stats_dump_proxy(s, px, NULL) == 0) if (stats_dump_proxy(si, px, NULL) == 0)
return 0; return 0;
} }
@ -1159,8 +1159,9 @@ int stats_dump_raw_to_buffer(struct session *s, struct buffer *rep)
* repost the data. We don't want this to happen on accident so we redirect * repost the data. We don't want this to happen on accident so we redirect
* the browse to the stats page with a GET. * the browse to the stats page with a GET.
*/ */
int stats_http_redir(struct session *s, struct buffer *rep, struct uri_auth *uri) int stats_http_redir(struct stream_interface *si, struct uri_auth *uri)
{ {
struct session *s = si->applet.private;
struct chunk msg; struct chunk msg;
chunk_init(&msg, trash, sizeof(trash)); chunk_init(&msg, trash, sizeof(trash));
@ -1176,7 +1177,7 @@ int stats_http_redir(struct session *s, struct buffer *rep, struct uri_auth *uri
uri->uri_prefix, s->data_ctx.stats.st_code); uri->uri_prefix, s->data_ctx.stats.st_code);
chunk_printf(&msg, "\r\n\r\n"); chunk_printf(&msg, "\r\n\r\n");
if (buffer_feed_chunk(rep, &msg) >= 0) if (buffer_feed_chunk(si->ib, &msg) >= 0)
return 0; return 0;
s->txn.status = 303; s->txn.status = 303;
@ -1213,12 +1214,12 @@ static void http_stats_io_handler(struct stream_interface *si)
if (!si->applet.st0) { if (!si->applet.st0) {
if (s->txn.meth == HTTP_METH_POST) { if (s->txn.meth == HTTP_METH_POST) {
if (stats_http_redir(s, res, s->be->uri_auth)) { if (stats_http_redir(si, s->be->uri_auth)) {
si->applet.st0 = 1; si->applet.st0 = 1;
si->shutw(si); si->shutw(si);
} }
} else { } else {
if (stats_dump_http(s, res, s->be->uri_auth)) { if (stats_dump_http(si, s->be->uri_auth)) {
si->applet.st0 = 1; si->applet.st0 = 1;
si->shutw(si); si->shutw(si);
} }
@ -1248,18 +1249,16 @@ static void http_stats_io_handler(struct stream_interface *si)
} }
/* /* This function dumps statistics in HTTP format onto the stream interface's
* Produces statistics data for the session <s>. Expects to be called with * read buffer. The data_ctx must have been zeroed first, and the flags
* client socket shut down on input. It stops by itself by unsetting the * properly set. It returns 0 if it had to stop writing data and an I/O is
* BF_HIJACK flag from the buffer, which it uses to keep on being called * needed, 1 if the dump is finished and the session must be closed, or -1
* when there is free space in the buffer, of simply by letting an empty buffer * in case of any error.
* upon return.s->data_ctx must have been zeroed before the first call, and the
* flags set. It returns 0 if it had to stop writing data and an I/O is needed,
* 1 if the dump is finished and the session must be closed, or -1 in case of
* any error.
*/ */
int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri) int stats_dump_http(struct stream_interface *si, struct uri_auth *uri)
{ {
struct session *s = si->applet.private;
struct buffer *rep = si->ib;
struct proxy *px; struct proxy *px;
struct chunk msg; struct chunk msg;
unsigned int up; unsigned int up;
@ -1568,7 +1567,7 @@ int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri)
px = s->data_ctx.stats.px; px = s->data_ctx.stats.px;
/* skip the disabled proxies and non-networked ones */ /* skip the disabled proxies and non-networked ones */
if (px->state != PR_STSTOPPED && (px->cap & (PR_CAP_FE | PR_CAP_BE))) if (px->state != PR_STSTOPPED && (px->cap & (PR_CAP_FE | PR_CAP_BE)))
if (stats_dump_proxy(s, px, uri) == 0) if (stats_dump_proxy(si, px, uri) == 0)
return 0; return 0;
s->data_ctx.stats.px = px->next; s->data_ctx.stats.px = px->next;
@ -1605,9 +1604,10 @@ int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri)
* Returns 0 if it had to stop dumping data because of lack of buffer space, * Returns 0 if it had to stop dumping data because of lack of buffer space,
* ot non-zero if everything completed. * ot non-zero if everything completed.
*/ */
int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) int stats_dump_proxy(struct stream_interface *si, struct proxy *px, struct uri_auth *uri)
{ {
struct buffer *rep = s->rep; struct session *s = si->applet.private;
struct buffer *rep = si->ib;
struct server *sv, *svs; /* server and server-state, server-state=server or server->tracked */ struct server *sv, *svs; /* server and server-state, server-state=server or server->tracked */
struct listener *l; struct listener *l;
struct chunk msg; struct chunk msg;
@ -2647,16 +2647,15 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri)
} }
} }
/* This function is called to send output to the response buffer. It dumps a /* This function dumps a complete session state onto the stream intreface's
* complete session state onto the output buffer <rep>. The session has to be * read buffer. The data_ctx must have been zeroed first, and the flags
* set in data_ctx.sess.target. It returns 0 if the output buffer is full and * properly set. The session has to be set in data_ctx.sess.target. It returns
* it needs to be called again, otherwise non-zero. It is designed to be called * 0 if the output buffer is full and it needs to be called again, otherwise
* from stats_dump_sess_to_buffer() below. * non-zero. It is designed to be called from stats_dump_sess_to_buffer() below.
*/ */
int stats_dump_full_sess_to_buffer(struct stream_interface *si)
/* returns 1 if dump is not complete */
int stats_dump_full_sess_to_buffer(struct session *s, struct buffer *rep)
{ {
struct session *s = si->applet.private;
struct tm tm; struct tm tm;
struct chunk msg; struct chunk msg;
struct session *sess; struct session *sess;
@ -2669,7 +2668,7 @@ int stats_dump_full_sess_to_buffer(struct session *s, struct buffer *rep)
if (s->data_ctx.sess.section > 0 && s->data_ctx.sess.uid != sess->uniq_id) { if (s->data_ctx.sess.section > 0 && s->data_ctx.sess.uid != sess->uniq_id) {
/* session changed, no need to go any further */ /* session changed, no need to go any further */
chunk_printf(&msg, " *** session terminated while we were watching it ***\n"); chunk_printf(&msg, " *** session terminated while we were watching it ***\n");
if (buffer_feed_chunk(rep, &msg) >= 0) if (buffer_feed_chunk(si->ib, &msg) >= 0)
return 0; return 0;
s->data_ctx.sess.target = NULL; s->data_ctx.sess.target = NULL;
s->data_ctx.sess.uid = 0; s->data_ctx.sess.uid = 0;
@ -2844,7 +2843,7 @@ int stats_dump_full_sess_to_buffer(struct session *s, struct buffer *rep)
(int)(sess->rep->lr - sess->rep->data), (int)(sess->rep->lr - sess->rep->data),
sess->rep->total); sess->rep->total);
if (buffer_feed_chunk(rep, &msg) >= 0) if (buffer_feed_chunk(si->ib, &msg) >= 0)
return 0; return 0;
/* use other states to dump the contents */ /* use other states to dump the contents */
@ -2854,17 +2853,18 @@ int stats_dump_full_sess_to_buffer(struct session *s, struct buffer *rep)
return 1; return 1;
} }
/* This function is called to send output to the response buffer. /* This function dumps all sessions' states onto the stream intreface's
* It dumps the sessions states onto the output buffer <rep>. * read buffer. The data_ctx must have been zeroed first, and the flags
* Expects to be called with client socket shut down on input. * properly set. It returns 0 if the output buffer is full and it needs
* s->data_ctx must have been zeroed first, and the flags properly set. * to be called again, otherwise non-zero. It is designed to be called
* It returns 0 as long as it does not complete, non-zero upon completion. * from stats_dump_sess_to_buffer() below.
*/ */
int stats_dump_sess_to_buffer(struct session *s, struct buffer *rep) int stats_dump_sess_to_buffer(struct stream_interface *si)
{ {
struct session *s = si->applet.private;
struct chunk msg; struct chunk msg;
if (unlikely(rep->flags & (BF_WRITE_ERROR|BF_SHUTW))) { if (unlikely(si->ib->flags & (BF_WRITE_ERROR|BF_SHUTW))) {
/* If we're forced to shut down, we might have to remove our /* If we're forced to shut down, we might have to remove our
* reference to the last session being dumped. * reference to the last session being dumped.
*/ */
@ -2913,7 +2913,7 @@ int stats_dump_sess_to_buffer(struct session *s, struct buffer *rep)
LIST_ADDQ(&curr_sess->back_refs, &s->data_ctx.sess.bref.users); LIST_ADDQ(&curr_sess->back_refs, &s->data_ctx.sess.bref.users);
/* call the proper dump() function and return if we're missing space */ /* call the proper dump() function and return if we're missing space */
if (!stats_dump_full_sess_to_buffer(s, rep)) if (!stats_dump_full_sess_to_buffer(si))
return 0; return 0;
/* session dump complete */ /* session dump complete */
@ -3045,7 +3045,7 @@ int stats_dump_sess_to_buffer(struct session *s, struct buffer *rep)
chunk_printf(&msg, "\n"); chunk_printf(&msg, "\n");
if (buffer_feed_chunk(rep, &msg) >= 0) { if (buffer_feed_chunk(si->ib, &msg) >= 0) {
/* let's try again later from this session. We add ourselves into /* let's try again later from this session. We add ourselves into
* this session's users so that it can remove us upon termination. * this session's users so that it can remove us upon termination.
*/ */
@ -3064,7 +3064,7 @@ int stats_dump_sess_to_buffer(struct session *s, struct buffer *rep)
else else
chunk_printf(&msg, "Session not found.\n"); chunk_printf(&msg, "Session not found.\n");
if (buffer_feed_chunk(rep, &msg) >= 0) if (buffer_feed_chunk(si->ib, &msg) >= 0)
return 0; return 0;
s->data_ctx.sess.target = NULL; s->data_ctx.sess.target = NULL;
@ -3150,14 +3150,14 @@ static int dump_binary(struct chunk *out, const char *buf, int bsize)
return ptr; return ptr;
} }
/* This function is called to send output to the response buffer. /* This function dumps all tables' states onto the stream intreface's
* It dumps the tables states onto the output buffer <rep>. * read buffer. The data_ctx must have been zeroed first, and the flags
* Expects to be called with client socket shut down on input. * properly set. It returns 0 if the output buffer is full and it needs
* s->data_ctx must have been zeroed first, and the flags properly set. * to be called again, otherwise non-zero.
* It returns 0 as long as it does not complete, non-zero upon completion.
*/ */
int stats_dump_table_to_buffer(struct session *s, struct buffer *rep) int stats_dump_table_to_buffer(struct stream_interface *si)
{ {
struct session *s = si->applet.private;
struct chunk msg; struct chunk msg;
struct ebmb_node *eb; struct ebmb_node *eb;
int dt; int dt;
@ -3174,7 +3174,7 @@ int stats_dump_table_to_buffer(struct session *s, struct buffer *rep)
* data though. * data though.
*/ */
if (unlikely(rep->flags & (BF_WRITE_ERROR|BF_SHUTW))) { if (unlikely(si->ib->flags & (BF_WRITE_ERROR|BF_SHUTW))) {
/* in case of abort, remove any refcount we might have set on an entry */ /* in case of abort, remove any refcount we might have set on an entry */
if (s->data_state == DATA_ST_LIST) { if (s->data_state == DATA_ST_LIST) {
s->data_ctx.table.entry->ref_cnt--; s->data_ctx.table.entry->ref_cnt--;
@ -3217,7 +3217,7 @@ int stats_dump_table_to_buffer(struct session *s, struct buffer *rep)
s->listener->perm.ux.level < ACCESS_LVL_OPER) s->listener->perm.ux.level < ACCESS_LVL_OPER)
chunk_printf(&msg, "# contents not dumped due to insufficient privileges\n"); chunk_printf(&msg, "# contents not dumped due to insufficient privileges\n");
if (buffer_feed_chunk(rep, &msg) >= 0) if (buffer_feed_chunk(si->ib, &msg) >= 0)
return 0; return 0;
if (s->data_ctx.table.target && if (s->data_ctx.table.target &&
@ -3338,7 +3338,7 @@ int stats_dump_table_to_buffer(struct session *s, struct buffer *rep)
} }
chunk_printf(&msg, "\n"); chunk_printf(&msg, "\n");
if (buffer_feed_chunk(rep, &msg) >= 0) if (buffer_feed_chunk(si->ib, &msg) >= 0)
return 0; return 0;
skip_entry: skip_entry:
@ -3424,18 +3424,18 @@ static int dump_text_line(struct chunk *out, const char *buf, int bsize, int len
return ptr; return ptr;
} }
/* This function is called to send output to the response buffer. /* This function dumps all captured errors onto the stream intreface's
* It dumps the errors logged in proxies onto the output buffer <rep>. * read buffer. The data_ctx must have been zeroed first, and the flags
* Expects to be called with client socket shut down on input. * properly set. It returns 0 if the output buffer is full and it needs
* s->data_ctx must have been zeroed first, and the flags properly set. * to be called again, otherwise non-zero.
* It returns 0 as long as it does not complete, non-zero upon completion.
*/ */
int stats_dump_errors_to_buffer(struct session *s, struct buffer *rep) int stats_dump_errors_to_buffer(struct stream_interface *si)
{ {
struct session *s = si->applet.private;
extern const char *monthname[12]; extern const char *monthname[12];
struct chunk msg; struct chunk msg;
if (unlikely(rep->flags & (BF_WRITE_ERROR|BF_SHUTW))) if (unlikely(si->ib->flags & (BF_WRITE_ERROR|BF_SHUTW)))
return 1; return 1;
chunk_init(&msg, trash, sizeof(trash)); chunk_init(&msg, trash, sizeof(trash));
@ -3452,7 +3452,7 @@ int stats_dump_errors_to_buffer(struct session *s, struct buffer *rep)
tm.tm_hour, tm.tm_min, tm.tm_sec, (int)(date.tv_usec/1000), tm.tm_hour, tm.tm_min, tm.tm_sec, (int)(date.tv_usec/1000),
error_snapshot_id); error_snapshot_id);
if (buffer_feed_chunk(rep, &msg) >= 0) { if (buffer_feed_chunk(si->ib, &msg) >= 0) {
/* Socket buffer full. Let's try again later from the same point */ /* Socket buffer full. Let's try again later from the same point */
return 0; return 0;
} }
@ -3533,7 +3533,7 @@ int stats_dump_errors_to_buffer(struct session *s, struct buffer *rep)
break; break;
} }
if (buffer_feed_chunk(rep, &msg) >= 0) { if (buffer_feed_chunk(si->ib, &msg) >= 0) {
/* Socket buffer full. Let's try again later from the same point */ /* Socket buffer full. Let's try again later from the same point */
return 0; return 0;
} }
@ -3545,7 +3545,7 @@ int stats_dump_errors_to_buffer(struct session *s, struct buffer *rep)
/* the snapshot changed while we were dumping it */ /* the snapshot changed while we were dumping it */
chunk_printf(&msg, chunk_printf(&msg,
" WARNING! update detected on this snapshot, dump interrupted. Please re-check!\n"); " WARNING! update detected on this snapshot, dump interrupted. Please re-check!\n");
if (buffer_feed_chunk(rep, &msg) >= 0) if (buffer_feed_chunk(si->ib, &msg) >= 0)
return 0; return 0;
goto next; goto next;
} }
@ -3560,7 +3560,7 @@ int stats_dump_errors_to_buffer(struct session *s, struct buffer *rep)
if (newptr == s->data_ctx.errors.ptr) if (newptr == s->data_ctx.errors.ptr)
return 0; return 0;
if (buffer_feed_chunk(rep, &msg) >= 0) { if (buffer_feed_chunk(si->ib, &msg) >= 0) {
/* Socket buffer full. Let's try again later from the same point */ /* Socket buffer full. Let's try again later from the same point */
return 0; return 0;
} }