]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MINOR] stream_interface: make use of an applet descriptor for IO handlers
authorWilly Tarreau <w@1wt.eu>
Sun, 13 Feb 2011 12:16:36 +0000 (13:16 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 10 Mar 2011 22:32:14 +0000 (23:32 +0100)
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.

include/proto/dumpstats.h
include/proto/stream_interface.h
include/types/stream_interface.h
src/dumpstats.c
src/peers.c
src/proto_http.c
src/session.c
src/stream_interface.c
src/stream_sock.c

index 9cf5eec402636703d9055a4e0e303877c9c55ae6..e33fe944c5077c0bac5079179cdb15fed2f824f8 100644 (file)
@@ -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 */
index 4e7f7341959e1e20c6f0df9124fc546cb4b8fef7..0b90fcba26164f8218386a61b9165c043c3f18eb 100644 (file)
@@ -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);
index cfba687351a8d2004dcfa65b9be68cd1831fc2ef..6af0f63d672bb4936343c1b256c94f3612fbdb29 100644 (file)
@@ -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 */
 
index 081e4cd3714c0921fe06a95f99b0abfb406330f1..2630eed9a41f7594bd12ae98880a2de3b6b8a5d0 100644 (file)
@@ -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 },
index 19b8824121579dff10c249bd63ef6c2903a5cbc7..39f4a359b78f4d0de457dad05520628763989812 100644 (file)
@@ -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 */
index 649f5df6ac449e71f8382b990f395c90444536b4..5119d372538c5528676fd31bf46526c09a826afb 100644 (file)
@@ -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;
index 120f670f7ada88f1d72c85a9ff5f737af56f092c..7bcdb5dcc72a7b13adc40bab7bf4ee83cdacacfe 100644 (file)
@@ -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
index e93048e8db528496153dd844b9f4a058642ddba8..71fc864a047e1025fb3c98dd1e5f11f8b369da74 100644 (file)
@@ -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;
 }
index 25573cb6f6c24e0b293312d356be1ff2cdb27a6b..3c8563e26076c982bc106cc6d8629423f1139844 100644 (file)
@@ -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;
 }