[REORG] session: move the data_ctx struct to the stream interface's applet

This is in fact where those parts belong to. The old data_state was replaced
by applet.state and is now initialized when the applet is registered. It's
worth noting that the applet does not need to know the session nor the
buffer anymore since everything is brought by the stream interface.

It is possible that having a separate applet struct would simplify the
code but that's not a big deal.
This commit is contained in:
Willy Tarreau 2011-03-10 11:25:07 +01:00
parent 5ec29ffa42
commit 295a837726
9 changed files with 418 additions and 431 deletions

View File

@ -27,7 +27,7 @@
#include <types/buffers.h>
#include <types/session.h>
/* Flags for session->data_ctx.stats.flags */
/* Flags for applet.ctx.stats.flags */
#define STAT_FMT_CSV 0x00000001 /* dump the stats in CSV format instead of HTML */
#define STAT_SHOW_STAT 0x00000002 /* dump the stats part */
#define STAT_SHOW_INFO 0x00000004 /* dump the info part */

View File

@ -81,7 +81,7 @@ void manage_client_side_appsession(struct session *t, const char *buf, int len);
void manage_client_side_cookies(struct session *t, struct buffer *req);
void manage_server_side_cookies(struct session *t, struct buffer *rtr);
void check_response_for_cacheability(struct session *t, struct buffer *rtr);
int stats_check_uri(struct session *s, struct proxy *backend);
int stats_check_uri(struct stream_interface *si, struct http_txn *txn, struct proxy *backend);
void init_proto_http();
int http_find_header2(const char *name, int len,
char *sol, struct hdr_idx *idx,

View File

@ -186,28 +186,6 @@
#define HTTP_MSG_CLOSED 35 // shutdown_w done, all bytes sent
#define HTTP_MSG_TUNNEL 36 // tunneled data after DONE
/* data transmission states for the stats responses */
enum {
DATA_ST_INIT = 0,
DATA_ST_HEAD,
DATA_ST_INFO,
DATA_ST_LIST,
DATA_ST_END,
DATA_ST_FIN,
};
/* data transmission states for the stats responses inside a proxy */
enum {
DATA_ST_PX_INIT = 0,
DATA_ST_PX_TH,
DATA_ST_PX_FE,
DATA_ST_PX_LI,
DATA_ST_PX_SV,
DATA_ST_PX_BE,
DATA_ST_PX_END,
DATA_ST_PX_FIN,
};
/* Redirect flags */
enum {
REDIRECT_FLAG_NONE = 0,

View File

@ -203,44 +203,6 @@ struct session {
void (*do_log)(struct session *s); /* the function to call in order to log (or NULL) */
void (*srv_error)(struct session *s, /* the function to call upon unrecoverable server errors (or NULL) */
struct stream_interface *si);
short int data_state; /* where to get the data we generate ourselves */
union {
struct {
struct proxy *px;
struct server *sv;
struct listener *l;
short px_st, sv_st; /* DATA_ST_INIT or DATA_ST_DATA */
unsigned int flags; /* STAT_* */
int iid, type, sid; /* proxy id, type and service id if bounding of stats is enabled */
const char *st_code; /* pointer to the status code returned by an action */
} stats;
struct {
struct bref bref; /* back-reference from the session being dumped */
void *target; /* session we want to dump, or NULL for all */
unsigned int uid; /* if non-null, the uniq_id of the session being dumped */
int section; /* section of the session being dumped */
int pos; /* last position of the current session's buffer */
} sess;
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 buf; /* buffer being dumped, 0 = req, 1 = rep */
unsigned int sid; /* session 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 {
void *target; /* table we want to dump, or NULL for all */
struct proxy *proxy; /* table being currently dumped (first if NULL) */
struct stksess *entry; /* last entry we were trying to dump (or first if NULL) */
long long value; /* value to compare against */
signed char data_type; /* type of data to compare, or -1 if none */
signed char data_op; /* operator (STD_OP_*) when data_type set */
} table;
struct {
const char *msg; /* pointer to a persistent message to be returned in PRINT state */
} cli;
} data_ctx; /* used by stats I/O handlers to dump the stats */
unsigned int uniq_id; /* unique ID used for the traces */
};

View File

@ -136,8 +136,46 @@ struct stream_interface {
int conn_retries; /* number of connect retries left */
int fd; /* file descriptor for a stream driver when known */
struct {
int state; /* applet state, initialized to zero */
void *private; /* may be used by any function above */
unsigned int st0, st1; /* may be used by any function above */
union {
struct {
struct proxy *px;
struct server *sv;
struct listener *l;
int px_st; /* STAT_PX_ST* */
unsigned int flags; /* STAT_* */
int iid, type, sid; /* proxy id, type and service id if bounding of stats is enabled */
const char *st_code; /* pointer to the status code returned by an action */
} stats;
struct {
struct bref bref; /* back-reference from the session being dumped */
void *target; /* session we want to dump, or NULL for all */
unsigned int uid; /* if non-null, the uniq_id of the session being dumped */
int section; /* section of the session being dumped */
int pos; /* last position of the current session's buffer */
} sess;
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 buf; /* buffer being dumped, 0 = req, 1 = rep */
unsigned int sid; /* session 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 {
void *target; /* table we want to dump, or NULL for all */
struct proxy *proxy; /* table being currently dumped (first if NULL) */
struct stksess *entry; /* last entry we were trying to dump (or first if NULL) */
long long value; /* value to compare against */
signed char data_type; /* type of data to compare, or -1 if none */
signed char data_op; /* operator (STD_OP_*) when data_type set */
} table;
struct {
const char *msg; /* pointer to a persistent message to be returned in PRINT state */
} cli;
} ctx; /* used by stats I/O handlers to dump the stats */
} applet;
union {
struct {

File diff suppressed because it is too large Load Diff

View File

@ -75,8 +75,6 @@ int frontend_accept(struct session *s)
s->logs.prx_queue_size = 0; /* we get the number of pending conns before us */
s->logs.srv_queue_size = 0; /* we will get this number soon */
s->data_state = DATA_ST_INIT;
/* FIXME: the logs are horribly complicated now, because they are
* defined in <p>, <p>, and later <be> and <be>.
*/

View File

@ -2878,9 +2878,8 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit)
* Parse the posted data and enable/disable servers if necessary.
* Returns 1 if request was parsed or zero if it needs more data.
*/
int http_process_req_stat_post(struct session *s, struct buffer *req)
int http_process_req_stat_post(struct stream_interface *si, struct http_txn *txn, struct buffer *req)
{
struct http_txn *txn = &s->txn;
struct proxy *px;
struct server *sv;
@ -2896,18 +2895,18 @@ int http_process_req_stat_post(struct session *s, struct buffer *req)
if (end_params >= req->data + req->size - global.tune.maxrewrite) {
/* Prevent buffer overflow */
s->data_ctx.stats.st_code = STAT_STATUS_EXCD;
si->applet.ctx.stats.st_code = STAT_STATUS_EXCD;
return 1;
}
else if (end_params > req->data + req->l) {
/* we need more data */
s->data_ctx.stats.st_code = STAT_STATUS_NONE;
si->applet.ctx.stats.st_code = STAT_STATUS_NONE;
return 0;
}
*end_params = '\0';
s->data_ctx.stats.st_code = STAT_STATUS_NONE;
si->applet.ctx.stats.st_code = STAT_STATUS_NONE;
/*
* Parse the parameters in reverse order to only store the last value.
@ -2958,7 +2957,7 @@ int http_process_req_stat_post(struct session *s, struct buffer *req)
/* Not already in maintenance, we can change the server state */
sv->state |= SRV_MAINTAIN;
set_server_down(sv);
s->data_ctx.stats.st_code = STAT_STATUS_DONE;
si->applet.ctx.stats.st_code = STAT_STATUS_DONE;
}
break;
case 2:
@ -2966,7 +2965,7 @@ int http_process_req_stat_post(struct session *s, struct buffer *req)
/* Already in maintenance, we can change the server state */
set_server_up(sv);
sv->health = sv->rise; /* up, but will fall down at first failure */
s->data_ctx.stats.st_code = STAT_STATUS_DONE;
si->applet.ctx.stats.st_code = STAT_STATUS_DONE;
}
break;
}
@ -3031,7 +3030,7 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
}
}
do_stats = stats_check_uri(s, px);
do_stats = stats_check_uri(s->rep->prod, txn, px);
list_for_each_entry(req_acl, (do_stats?&px->uri_auth->req_acl:&px->req_acl), list) {
int ret = 1;
@ -3207,14 +3206,14 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
if (ret) {
/* no rule, or the rule matches */
s->data_ctx.stats.flags |= STAT_ADMIN;
s->rep->prod->applet.ctx.stats.flags |= STAT_ADMIN;
break;
}
}
/* Was the status page requested with a POST ? */
if (txn->meth == HTTP_METH_POST) {
if (s->data_ctx.stats.flags & STAT_ADMIN) {
if (s->rep->prod->applet.ctx.stats.flags & STAT_ADMIN) {
if (msg->msg_state < HTTP_MSG_100_SENT) {
/* If we have HTTP/1.1 and Expect: 100-continue, then we must
* send an HTTP/1.1 100 Continue intermediate response.
@ -3231,19 +3230,18 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
msg->msg_state = HTTP_MSG_100_SENT;
s->logs.tv_request = now; /* update the request timer to reflect full request */
}
if (!http_process_req_stat_post(s, req)) {
if (!http_process_req_stat_post(s->rep->prod, txn, req)) {
/* we need more data */
req->analysers |= an_bit;
buffer_dont_connect(req);
return 0;
}
} else {
s->data_ctx.stats.st_code = STAT_STATUS_DENY;
s->rep->prod->applet.ctx.stats.st_code = STAT_STATUS_DENY;
}
}
s->logs.tv_request = now;
s->data_state = DATA_ST_INIT;
s->task->nice = -32; /* small boost for HTTP statistics */
stream_int_register_handler(s->rep->prod, &http_stats_applet);
s->rep->prod->applet.private = s;
@ -7266,13 +7264,12 @@ void get_srv_from_appsession(struct session *t, const char *begin, int len)
* for the current backend.
*
* It is assumed that the request is either a HEAD, GET, or POST and that the
* t->be->uri_auth field is valid.
* uri_auth field is valid.
*
* Returns 1 if stats should be provided, otherwise 0.
*/
int stats_check_uri(struct session *t, struct proxy *backend)
int stats_check_uri(struct stream_interface *si, struct http_txn *txn, struct proxy *backend)
{
struct http_txn *txn = &t->txn;
struct uri_auth *uri_auth = backend->uri_auth;
char *h;
@ -7282,7 +7279,7 @@ int stats_check_uri(struct session *t, struct proxy *backend)
if (txn->meth != HTTP_METH_GET && txn->meth != HTTP_METH_HEAD && txn->meth != HTTP_METH_POST)
return 0;
memset(&t->data_ctx.stats, 0, sizeof(t->data_ctx.stats));
memset(&si->applet.ctx.stats, 0, sizeof(si->applet.ctx.stats));
/* check URI size */
if (uri_auth->uri_len > txn->req.sl.rq.u_l)
@ -7297,7 +7294,7 @@ int stats_check_uri(struct session *t, struct proxy *backend)
h += uri_auth->uri_len;
while (h <= txn->req.sol + txn->req.sl.rq.u + txn->req.sl.rq.u_l - 3) {
if (memcmp(h, ";up", 3) == 0) {
t->data_ctx.stats.flags |= STAT_HIDE_DOWN;
si->applet.ctx.stats.flags |= STAT_HIDE_DOWN;
break;
}
h++;
@ -7307,7 +7304,7 @@ int stats_check_uri(struct session *t, struct proxy *backend)
h = txn->req.sol + txn->req.sl.rq.u + uri_auth->uri_len;
while (h <= txn->req.sol + txn->req.sl.rq.u + txn->req.sl.rq.u_l - 10) {
if (memcmp(h, ";norefresh", 10) == 0) {
t->data_ctx.stats.flags |= STAT_NO_REFRESH;
si->applet.ctx.stats.flags |= STAT_NO_REFRESH;
break;
}
h++;
@ -7317,7 +7314,7 @@ int stats_check_uri(struct session *t, struct proxy *backend)
h = txn->req.sol + txn->req.sl.rq.u + uri_auth->uri_len;
while (h <= txn->req.sol + txn->req.sl.rq.u + txn->req.sl.rq.u_l - 4) {
if (memcmp(h, ";csv", 4) == 0) {
t->data_ctx.stats.flags |= STAT_FMT_CSV;
si->applet.ctx.stats.flags |= STAT_FMT_CSV;
break;
}
h++;
@ -7329,21 +7326,21 @@ int stats_check_uri(struct session *t, struct proxy *backend)
h += 4;
if (memcmp(h, STAT_STATUS_DONE, 4) == 0)
t->data_ctx.stats.st_code = STAT_STATUS_DONE;
si->applet.ctx.stats.st_code = STAT_STATUS_DONE;
else if (memcmp(h, STAT_STATUS_NONE, 4) == 0)
t->data_ctx.stats.st_code = STAT_STATUS_NONE;
si->applet.ctx.stats.st_code = STAT_STATUS_NONE;
else if (memcmp(h, STAT_STATUS_EXCD, 4) == 0)
t->data_ctx.stats.st_code = STAT_STATUS_EXCD;
si->applet.ctx.stats.st_code = STAT_STATUS_EXCD;
else if (memcmp(h, STAT_STATUS_DENY, 4) == 0)
t->data_ctx.stats.st_code = STAT_STATUS_DENY;
si->applet.ctx.stats.st_code = STAT_STATUS_DENY;
else
t->data_ctx.stats.st_code = STAT_STATUS_UNKN;
si->applet.ctx.stats.st_code = STAT_STATUS_UNKN;
break;
}
h++;
}
t->data_ctx.stats.flags |= STAT_SHOW_STAT | STAT_SHOW_INFO;
si->applet.ctx.stats.flags |= STAT_SHOW_STAT | STAT_SHOW_INFO;
return 1;
}

View File

@ -302,6 +302,7 @@ void stream_int_chk_snd(struct stream_interface *si)
* it is solicited. The task's processing function must call the applet's
* function before returning. It must be deleted by the task handler using
* stream_int_unregister_handler(), possibly from within the function itself.
* It also pre-initializes applet.state to zero.
*/
struct task *stream_int_register_handler(struct stream_interface *si, struct si_applet *app)
{
@ -315,6 +316,7 @@ struct task *stream_int_register_handler(struct stream_interface *si, struct si_
si->connect = NULL;
si->target.type = TARG_TYPE_APPLET;
si->target.ptr.a = app;
si->applet.state = 0;
si->release = NULL;
si->flags |= SI_FL_WAIT_DATA;
return si->owner;