[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.
diff --git a/include/proto/dumpstats.h b/include/proto/dumpstats.h
index 9cf5eec..e33fe94 100644
--- a/include/proto/dumpstats.h
+++ b/include/proto/dumpstats.h
@@ -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_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 */
diff --git a/include/proto/stream_interface.h b/include/proto/stream_interface.h
index 4e7f734..0b90fcb 100644
--- a/include/proto/stream_interface.h
+++ b/include/proto/stream_interface.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_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);
diff --git a/include/types/stream_interface.h b/include/types/stream_interface.h
index cfba687..6af0f63 100644
--- a/include/types/stream_interface.h
+++ b/include/types/stream_interface.h
@@ -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 @@
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 @@
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 */
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 081e4cd..2630eed 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -84,7 +84,7 @@
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 @@
* 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 @@
* 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 @@
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 },
diff --git a/src/peers.c b/src/peers.c
index 19b8824..39f4a35 100644
--- a/src/peers.c
+++ b/src/peers.c
@@ -216,7 +216,7 @@
/*
* 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 @@
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 @@
{
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 @@
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 @@
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 */
diff --git a/src/proto_http.c b/src/proto_http.c
index 649f5df..5119d37 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -3226,7 +3226,7 @@
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;
diff --git a/src/session.c b/src/session.c
index 120f670..7bcdb5d 100644
--- a/src/session.c
+++ b/src/session.c
@@ -167,7 +167,7 @@
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 @@
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 @@
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 @@
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 @@
/* 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
diff --git a/src/stream_interface.c b/src/stream_interface.c
index e93048e..71fc864 100644
--- a/src/stream_interface.c
+++ b/src/stream_interface.c
@@ -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 @@
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 @@
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 @@
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 @@
*/
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;
}
diff --git a/src/stream_sock.c b/src/stream_sock.c
index 25573cb..3c8563e 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -1252,7 +1252,7 @@
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;
}