* 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
#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);
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 */
* 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
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);
* 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
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* */
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 */
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;
* 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;
* 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;
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 },
/*
* 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;
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
{
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 {
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;
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 */
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;
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;
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;
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;
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);
/* 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
/*
* 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
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);
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;
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;
*/
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;
}
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;
}