mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-20 21:31:28 +02:00
[MINOR] stream_interface: make use of an applet descriptor for IO handlers
I/O handlers are still delicate to manipulate. They have no type, they're just raw functions which have no knowledge of themselves. Let's have them declared as applets once for all. That way we can have multiple applets share the same handler functions and we can store their names there. When we later need to add more parameters (eg: usage stats), we'll be able to do so in the applets themselves. The CLI functions has been prefixed with "cli" instead of "stats" as it's clearly what is going on there. The applet descriptor in the stream interface should get all the applet specific data (st0, ...) but this will be done in the next patch so that we don't pollute this one too much.
This commit is contained in:
parent
dfd7fca26c
commit
b24281b0ff
@ -3,7 +3,7 @@
|
||||
* This file contains definitions of some primitives to dedicated to
|
||||
* statistics output.
|
||||
*
|
||||
* Copyright (C) 2000-2010 Willy Tarreau - w@1wt.eu
|
||||
* Copyright (C) 2000-2011 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -61,6 +61,8 @@
|
||||
#define STAT_STATUS_EXCD "EXCD" /* an error occured becayse the buffer couldn't store all data */
|
||||
#define STAT_STATUS_DENY "DENY" /* action denied */
|
||||
|
||||
extern struct si_applet http_stats_applet;
|
||||
extern struct si_applet cli_applet;
|
||||
|
||||
int stats_accept(struct session *s);
|
||||
int stats_sock_parse_request(struct stream_interface *si, char *line);
|
||||
@ -71,7 +73,6 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri);
|
||||
int stats_dump_sess_to_buffer(struct session *s, struct buffer *rep);
|
||||
int stats_dump_table_to_buffer(struct session *s, struct buffer *rep);
|
||||
int stats_dump_errors_to_buffer(struct session *s, struct buffer *rep);
|
||||
void http_stats_io_handler(struct stream_interface *si);
|
||||
|
||||
|
||||
#endif /* _PROTO_DUMPSTATS_H */
|
||||
|
@ -2,7 +2,7 @@
|
||||
* include/proto/stream_interface.h
|
||||
* This file contains stream_interface function prototypes
|
||||
*
|
||||
* Copyright (C) 2000-2009 Willy Tarreau - w@1wt.eu
|
||||
* Copyright (C) 2000-2011 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -42,7 +42,7 @@ void stream_int_chk_rcv(struct stream_interface *si);
|
||||
void stream_int_chk_snd(struct stream_interface *si);
|
||||
|
||||
struct task *stream_int_register_handler(struct stream_interface *si,
|
||||
void (*fct)(struct stream_interface *));
|
||||
struct si_applet *app);
|
||||
struct task *stream_int_register_handler_task(struct stream_interface *si,
|
||||
struct task *(*fct)(struct task *));
|
||||
void stream_int_unregister_handler(struct stream_interface *si);
|
||||
|
@ -2,7 +2,7 @@
|
||||
* include/types/stream_interface.h
|
||||
* This file describes the stream_interface struct and associated constants.
|
||||
*
|
||||
* Copyright (C) 2000-2010 Willy Tarreau - w@1wt.eu
|
||||
* Copyright (C) 2000-2011 Willy Tarreau - w@1wt.eu
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -78,13 +78,11 @@ enum {
|
||||
|
||||
struct server;
|
||||
struct proxy;
|
||||
struct si_applet;
|
||||
|
||||
/* Note that if an iohandler is set, the update function will not be called by
|
||||
* the session handler, so it may be used to resync flags at the end of the I/O
|
||||
* handler. See stream_int_update_embedded() for reference.
|
||||
* This struct could be optimized, because :
|
||||
* - connect(), fd, conn_retries are only used in stream_sock mode
|
||||
* - iohandler(), private, st0, st1 are only used in iohandler mode
|
||||
/* Note that if an applet is registered, the update function will not be called
|
||||
* by the session handler, so it may be used to resync flags at the end of the
|
||||
* applet handler. See stream_int_update_embedded() for reference.
|
||||
*/
|
||||
struct stream_interface {
|
||||
unsigned int state; /* SI_ST* */
|
||||
@ -101,15 +99,22 @@ struct stream_interface {
|
||||
int (*connect)(struct stream_interface *, struct proxy *, struct server *,
|
||||
struct sockaddr *, struct sockaddr *); /* connect function if any */
|
||||
void (*release)(struct stream_interface *); /* handler to call after the last close() */
|
||||
void (*iohandler)(struct stream_interface *); /* internal I/O handler when embedded */
|
||||
struct buffer *ib, *ob; /* input and output buffers */
|
||||
int conn_retries; /* number of connect retries left */
|
||||
unsigned int err_type; /* first error detected, one of SI_ET_* */
|
||||
void *err_loc; /* commonly the server, NULL when SI_ET_NONE */
|
||||
struct {
|
||||
struct si_applet *handler; /* applet to use instead of doing I/O */
|
||||
} applet;
|
||||
void *private; /* may be used by any function above */
|
||||
unsigned int st0, st1; /* may be used by any function above */
|
||||
};
|
||||
|
||||
/* An applet designed to run in a stream interface */
|
||||
struct si_applet {
|
||||
char *name; /* applet's name to report in logs */
|
||||
void (*fct)(struct stream_interface *); /* internal I/O handler, may never be NULL */
|
||||
};
|
||||
|
||||
#endif /* _TYPES_STREAM_INTERFACE_H */
|
||||
|
||||
|
@ -84,7 +84,7 @@ const char stats_permission_denied_msg[] =
|
||||
int stats_accept(struct session *s)
|
||||
{
|
||||
/* we have a dedicated I/O handler for the stats */
|
||||
stream_int_register_handler(&s->si[1], stats_io_handler);
|
||||
stream_int_register_handler(&s->si[1], &cli_applet);
|
||||
s->si[1].private = s;
|
||||
s->si[1].st1 = 0;
|
||||
s->si[1].st0 = STAT_CLI_INIT;
|
||||
@ -848,7 +848,7 @@ int stats_sock_parse_request(struct stream_interface *si, char *line)
|
||||
* STAT_CLI_* constants. si->st1 is used to indicate whether prompt is enabled
|
||||
* or not.
|
||||
*/
|
||||
void stats_io_handler(struct stream_interface *si)
|
||||
static void cli_io_handler(struct stream_interface *si)
|
||||
{
|
||||
struct session *s = si->private;
|
||||
struct buffer *req = si->ob;
|
||||
@ -1200,7 +1200,7 @@ int stats_http_redir(struct session *s, struct buffer *rep, struct uri_auth *uri
|
||||
* si->st0 becomes non-zero once the transfer is finished. The handler
|
||||
* automatically unregisters itself once transfer is complete.
|
||||
*/
|
||||
void http_stats_io_handler(struct stream_interface *si)
|
||||
static void http_stats_io_handler(struct stream_interface *si)
|
||||
{
|
||||
struct session *s = si->private;
|
||||
struct buffer *req = si->ob;
|
||||
@ -3583,6 +3583,15 @@ int stats_dump_errors_to_buffer(struct session *s, struct buffer *rep)
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct si_applet http_stats_applet = {
|
||||
.name = "<STATS>", /* used for logging */
|
||||
.fct = http_stats_io_handler,
|
||||
};
|
||||
|
||||
struct si_applet cli_applet = {
|
||||
.name = "<CLI>", /* used for logging */
|
||||
.fct = cli_io_handler,
|
||||
};
|
||||
|
||||
static struct cfg_kw_list cfg_kws = {{ },{
|
||||
{ CFG_GLOBAL, "stats", stats_parse_global },
|
||||
|
12
src/peers.c
12
src/peers.c
@ -216,7 +216,7 @@ void peer_session_release(struct stream_interface *si)
|
||||
/*
|
||||
* IO Handler to handle message exchance with a peer
|
||||
*/
|
||||
void peer_io_handler(struct stream_interface *si)
|
||||
static void peer_io_handler(struct stream_interface *si)
|
||||
{
|
||||
struct task *t= (struct task *)si->owner;
|
||||
struct session *s = (struct session *)t->context;
|
||||
@ -1041,6 +1041,10 @@ quit:
|
||||
return;
|
||||
}
|
||||
|
||||
static struct si_applet peer_applet = {
|
||||
.name = "<PEER>", /* used for logging */
|
||||
.fct = peer_io_handler,
|
||||
};
|
||||
|
||||
/*
|
||||
* Use this function to force a close of a peer session
|
||||
@ -1049,7 +1053,7 @@ void peer_session_forceshutdown(struct session * session)
|
||||
{
|
||||
struct stream_interface *oldsi;
|
||||
|
||||
if (session->si[0].iohandler == peer_io_handler) {
|
||||
if (session->si[0].applet.handler == &peer_applet) {
|
||||
oldsi = &session->si[0];
|
||||
}
|
||||
else {
|
||||
@ -1072,7 +1076,7 @@ void peer_session_forceshutdown(struct session * session)
|
||||
int peer_accept(struct session *s)
|
||||
{
|
||||
/* we have a dedicated I/O handler for the stats */
|
||||
stream_int_register_handler(&s->si[1], peer_io_handler);
|
||||
stream_int_register_handler(&s->si[1], &peer_applet);
|
||||
s->si[1].release = peer_session_release;
|
||||
s->si[1].private = s;
|
||||
s->si[1].st0 = PEER_SESSION_ACCEPT;
|
||||
@ -1158,7 +1162,7 @@ struct session *peer_session_create(struct peer *peer, struct peer_session *ps)
|
||||
s->si[0].private = (void *)ps;
|
||||
s->si[0].st0 = PEER_SESSION_CONNECT;
|
||||
|
||||
stream_int_register_handler(&s->si[0], peer_io_handler);
|
||||
stream_int_register_handler(&s->si[0], &peer_applet);
|
||||
s->si[0].release = peer_session_release;
|
||||
|
||||
s->si[1].fd = -1; /* just to help with debugging */
|
||||
|
@ -3226,7 +3226,7 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
|
||||
s->data_source = DATA_SRC_STATS;
|
||||
s->data_state = DATA_ST_INIT;
|
||||
s->task->nice = -32; /* small boost for HTTP statistics */
|
||||
stream_int_register_handler(s->rep->prod, http_stats_io_handler);
|
||||
stream_int_register_handler(s->rep->prod, &http_stats_applet);
|
||||
s->rep->prod->private = s;
|
||||
s->rep->prod->st0 = s->rep->prod->st1 = 0;
|
||||
req->analysers = 0;
|
||||
|
@ -167,7 +167,7 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
|
||||
s->si[0].err_type = SI_ET_NONE;
|
||||
s->si[0].err_loc = NULL;
|
||||
s->si[0].connect = NULL;
|
||||
s->si[0].iohandler = NULL;
|
||||
s->si[0].applet.handler = NULL;
|
||||
s->si[0].release = NULL;
|
||||
s->si[0].exp = TICK_ETERNITY;
|
||||
s->si[0].flags = SI_FL_NONE;
|
||||
@ -190,7 +190,7 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
|
||||
s->si[1].err_type = SI_ET_NONE;
|
||||
s->si[1].err_loc = NULL;
|
||||
s->si[1].connect = NULL;
|
||||
s->si[1].iohandler = NULL;
|
||||
s->si[1].applet.handler = NULL;
|
||||
s->si[1].release = NULL;
|
||||
s->si[1].shutr = stream_int_shutr;
|
||||
s->si[1].shutw = stream_int_shutw;
|
||||
@ -1786,13 +1786,13 @@ struct task *process_session(struct task *t)
|
||||
if (s->req->cons->state == SI_ST_INI) {
|
||||
if (!(s->req->flags & BF_SHUTW)) {
|
||||
if ((s->req->flags & (BF_AUTO_CONNECT|BF_OUT_EMPTY)) != BF_OUT_EMPTY) {
|
||||
/* If we have an iohandler without a connect method, we immediately
|
||||
/* If we have an applet without a connect method, we immediately
|
||||
* switch to the connected state, otherwise we perform a connection
|
||||
* request.
|
||||
*/
|
||||
s->req->cons->state = SI_ST_REQ; /* new connection requested */
|
||||
s->req->cons->conn_retries = s->be->conn_retries;
|
||||
if (unlikely(s->req->cons->iohandler && !s->req->cons->connect)) {
|
||||
if (unlikely(s->req->cons->applet.handler && !s->req->cons->connect)) {
|
||||
s->req->cons->state = SI_ST_EST; /* connection established */
|
||||
s->rep->flags |= BF_READ_ATTACHED; /* producer is now attached */
|
||||
s->req->wex = TICK_ETERNITY;
|
||||
@ -1949,10 +1949,10 @@ struct task *process_session(struct task *t)
|
||||
if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED))
|
||||
session_process_counters(s);
|
||||
|
||||
if (s->rep->cons->state == SI_ST_EST && !s->rep->cons->iohandler)
|
||||
if (s->rep->cons->state == SI_ST_EST && !s->rep->cons->applet.handler)
|
||||
s->rep->cons->update(s->rep->cons);
|
||||
|
||||
if (s->req->cons->state == SI_ST_EST && !s->req->cons->iohandler)
|
||||
if (s->req->cons->state == SI_ST_EST && !s->req->cons->applet.handler)
|
||||
s->req->cons->update(s->req->cons);
|
||||
|
||||
s->req->flags &= ~(BF_READ_NULL|BF_READ_PARTIAL|BF_WRITE_NULL|BF_WRITE_PARTIAL|BF_READ_ATTACHED);
|
||||
@ -1979,11 +1979,11 @@ struct task *process_session(struct task *t)
|
||||
/* Call the stream interfaces' I/O handlers when embedded.
|
||||
* Note that this one may wake the task up again.
|
||||
*/
|
||||
if (s->req->cons->iohandler || s->rep->cons->iohandler) {
|
||||
if (s->req->cons->iohandler)
|
||||
s->req->cons->iohandler(s->req->cons);
|
||||
if (s->rep->cons->iohandler)
|
||||
s->rep->cons->iohandler(s->rep->cons);
|
||||
if (s->req->cons->applet.handler || s->rep->cons->applet.handler) {
|
||||
if (s->req->cons->applet.handler)
|
||||
s->req->cons->applet.handler->fct(s->req->cons);
|
||||
if (s->rep->cons->applet.handler)
|
||||
s->rep->cons->applet.handler->fct(s->rep->cons);
|
||||
if (task_in_rq(t)) {
|
||||
/* If we woke up, we don't want to requeue the
|
||||
* task to the wait queue, but rather requeue
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Functions managing stream_interface structures
|
||||
*
|
||||
* Copyright 2000-2009 Willy Tarreau <w@1wt.eu>
|
||||
* Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -297,14 +297,13 @@ void stream_int_chk_snd(struct stream_interface *si)
|
||||
task_wakeup(si->owner, TASK_WOKEN_IO);
|
||||
}
|
||||
|
||||
/* Register a function to handle a stream_interface as part of the stream
|
||||
/* Register an applet to handle a stream_interface as part of the stream
|
||||
* interface's owner task, which is returned. The SI will wake it up everytime
|
||||
* it is solicited. The task's processing function must call the specified
|
||||
* 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 withing the function itself.
|
||||
* stream_int_unregister_handler(), possibly from within the function itself.
|
||||
*/
|
||||
struct task *stream_int_register_handler(struct stream_interface *si,
|
||||
void (*fct)(struct stream_interface *))
|
||||
struct task *stream_int_register_handler(struct stream_interface *si, struct si_applet *app)
|
||||
{
|
||||
DPRINTF(stderr, "registering handler %p for si %p (was %p)\n", fct, si, si->owner);
|
||||
|
||||
@ -314,7 +313,7 @@ struct task *stream_int_register_handler(struct stream_interface *si,
|
||||
si->chk_rcv = stream_int_chk_rcv;
|
||||
si->chk_snd = stream_int_chk_snd;
|
||||
si->connect = NULL;
|
||||
si->iohandler = fct;
|
||||
si->applet.handler = app;
|
||||
si->release = NULL;
|
||||
si->flags |= SI_FL_WAIT_DATA;
|
||||
return si->owner;
|
||||
@ -338,7 +337,7 @@ struct task *stream_int_register_handler_task(struct stream_interface *si,
|
||||
si->chk_rcv = stream_int_chk_rcv;
|
||||
si->chk_snd = stream_int_chk_snd;
|
||||
si->connect = NULL;
|
||||
si->iohandler = NULL; /* not used when running as an external task */
|
||||
si->applet.handler = NULL; /* not used when running as an external task */
|
||||
si->release = NULL;
|
||||
si->flags |= SI_FL_WAIT_DATA;
|
||||
|
||||
@ -359,12 +358,12 @@ struct task *stream_int_register_handler_task(struct stream_interface *si,
|
||||
*/
|
||||
void stream_int_unregister_handler(struct stream_interface *si)
|
||||
{
|
||||
if (!si->iohandler && si->owner) {
|
||||
if (!si->applet.handler && si->owner) {
|
||||
/* external handler : kill the task */
|
||||
task_delete(si->owner);
|
||||
task_free(si->owner);
|
||||
}
|
||||
si->iohandler = NULL;
|
||||
si->applet.handler = NULL;
|
||||
si->release = NULL;
|
||||
si->owner = NULL;
|
||||
}
|
||||
|
@ -1252,7 +1252,7 @@ void stream_sock_prepare_interface(struct stream_interface *si)
|
||||
si->shutw = stream_sock_shutw;
|
||||
si->chk_rcv = stream_sock_chk_rcv;
|
||||
si->chk_snd = stream_sock_chk_snd;
|
||||
si->iohandler = NULL;
|
||||
si->applet.handler = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user