]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] reintroduce BF_HIJACK with produce_content
authorWilly Tarreau <w@1wt.eu>
Thu, 28 Aug 2008 14:01:32 +0000 (16:01 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 2 Nov 2008 09:19:06 +0000 (10:19 +0100)
The stats dump are back. Even very large config files with
5000 servers work fast and well. The SN_SELF_GEN flag has
completely been removed.

include/proto/buffers.h
include/types/buffers.h
include/types/session.h
src/dumpstats.c
src/proto_http.c

index 3b5e2bdc7038d2e459f0f1052069a0166ac4fb44..194f4ee121c92d5c9bbcd6d85cdb71362c5f96d2 100644 (file)
@@ -108,6 +108,18 @@ static inline void buffer_abort(struct buffer *buf)
        buf->flags |= BF_SHUTR_NOW | BF_SHUTW_NOW;
 }
 
+/* set the buffer to hijacking mode */
+static inline void buffer_start_hijack(struct buffer *buf)
+{
+       buf->flags |= BF_HIJACK;
+}
+
+/* releases the buffer from hijacking mode */
+static inline void buffer_stop_hijack(struct buffer *buf)
+{
+       buf->flags &= ~BF_HIJACK;
+}
+
 /* returns the maximum number of bytes writable at once in this buffer */
 static inline int buffer_max(const struct buffer *buf)
 {
index bc8a184904296cfe7dd5e49fb7e5cd313f3b9764..d67c9324169265d74f6a7c71eb8e70612939c0b3 100644 (file)
@@ -72,6 +72,7 @@
 #define BF_MASK_INTERFACE       (BF_MASK_INTF_I | BF_MASK_INTF_O)
 
 #define BF_MASK_ANALYSER        (BF_FULL|BF_READ_NULL|BF_READ_ERROR|BF_READ_TIMEOUT|BF_SHUTR|BF_WRITE_ERROR)
+#define BF_MASK_INJECTER        (BF_FULL|BF_WRITE_STATUS|BF_WRITE_TIMEOUT|BF_SHUTW)
 
 /* Analysers (buffer->analysers).
  * Those bits indicate that there are some processing to do on the buffer
index 2d0439b7d6cc1ddd9132fde98f1e722d2605ef32..8b87be21af36d72fce8ae5c4b19aaf7c02b86719 100644 (file)
@@ -47,7 +47,7 @@
 #define SN_BE_ASSIGNED 0x00000008      /* a backend was assigned. Conns are accounted. */
 #define SN_CONN_CLOSED 0x00000010      /* "Connection: close" was present or added */
 #define SN_MONITOR     0x00000020      /* this session comes from a monitoring system */
-#define SN_SELF_GEN    0x00000040      /* the proxy generates data for the client (eg: stats) */
+/* unused:              0x00000040 */
 #define SN_FRT_ADDR_SET        0x00000080      /* set if the frontend address has been filled */
 #define SN_REDISP      0x00000100      /* set if this session was redispatched from one server to another */
 #define SN_CONN_TAR    0x00000200      /* set if this session is turning around before reconnecting */
index 1b7e1924c353b598cc054e90ecfcc582dc61fd9f..e4ef0b65599e2596267b5d49d1d59a14b3788684 100644 (file)
@@ -290,7 +290,7 @@ int stats_dump_raw(struct session *s, struct uri_auth *uri)
 /*
  * Produces statistics data for the session <s>. Expects to be called with
  * client socket shut down on input. It stops by itself by unsetting the
- * SN_SELF_GEN flag from the session, which it uses to keep on being called
+ * BF_HIJACK flag from the buffer, which it uses to keep on being called
  * when there is free space in the buffer, of simply by letting an empty buffer
  * upon return.s->data_ctx must have been zeroed before the first call, and the
  * flags set. It returns 0 if it had to stop writing data and an I/O is needed,
@@ -310,7 +310,7 @@ int stats_dump_http(struct session *s, struct uri_auth *uri)
        switch (s->data_state) {
        case DATA_ST_INIT:
                /* the function had not been called yet */
-               s->flags |= SN_SELF_GEN;  // more data will follow
+               buffer_start_hijack(rep);
 
                chunk_printf(&msg, sizeof(trash),
                             "HTTP/1.0 200 OK\r\n"
@@ -337,7 +337,7 @@ int stats_dump_http(struct session *s, struct uri_auth *uri)
                if (s->txn.meth == HTTP_METH_HEAD) {
                        /* that's all we return in case of HEAD request */
                        s->data_state = DATA_ST_FIN;
-                       s->flags &= ~SN_SELF_GEN;
+                       buffer_stop_hijack(rep);
                        return 1;
                }
 
@@ -570,12 +570,12 @@ int stats_dump_http(struct session *s, struct uri_auth *uri)
                /* fall through */
 
        case DATA_ST_FIN:
-               s->flags &= ~SN_SELF_GEN;
+               buffer_stop_hijack(rep);
                return 1;
 
        default:
                /* unknown state ! */
-               s->flags &= ~SN_SELF_GEN;
+               buffer_stop_hijack(rep);
                return -1;
        }
 }
index e8bd63142ba0cab1c9a9c11a7d444f3fe09ea268..66f8e169bd3918e96ea136a33d54b6f474fa99d9 100644 (file)
@@ -772,15 +772,25 @@ void process_session(struct task *t, int *next)
                        rqf_req = s->req->flags;
                }
 
-               if ((rpf_rep ^ s->rep->flags) & BF_MASK_ANALYSER) {
-                       /* the analysers must block it themselves */
-                       if (s->rep->prod->state >= SI_ST_EST) {
+               if (unlikely(s->rep->flags & BF_HIJACK)) {
+                       /* In inject mode, we wake up everytime something has
+                        * happened on the write side of the buffer.
+                        */
+                       if ((s->rep->flags & (BF_PARTIAL_WRITE|BF_WRITE_ERROR|BF_SHUTW)) &&
+                           !(s->rep->flags & BF_FULL)) {
+                               if (produce_content(s) != 0)
+                                       resync = 1; /* completed, better re-check flags */
+                       }
+               }
+               else if (s->rep->prod->state >= SI_ST_EST) {
+                       if ((rpf_rep ^ s->rep->flags) & BF_MASK_ANALYSER) {
+                               /* the analysers must block it themselves */
                                resync = 1;
                                s->rep->flags |= BF_MAY_FORWARD;
                                if (s->rep->analysers)
                                        process_response(s);
+                               rpf_rep = s->rep->flags;
                        }
-                       rpf_rep = s->rep->flags;
                }
 
        } while (resync);
@@ -3895,15 +3905,15 @@ int process_srv_conn(struct session *t)
 /*
  * Produces data for the session <s> depending on its source. Expects to be
  * called with client socket shut down on input. Right now, only statistics can
- * be produced. It stops by itself by unsetting the SN_SELF_GEN flag from the
- * session, which it uses to keep on being called when there is free space in
+ * be produced. It stops by itself by unsetting the BF_HIJACK flag from the
+ * buffer, which it uses to keep on being called when there is free space in
  * the buffer, or simply by letting an empty buffer upon return. It returns 1
  * when it wants to stop sending data, otherwise 0.
  */
 int produce_content(struct session *s)
 {
        if (s->data_source == DATA_SRC_NONE) {
-               s->flags &= ~SN_SELF_GEN;
+               buffer_stop_hijack(s->rep);
                return 1;
        }
        else if (s->data_source == DATA_SRC_STATS) {
@@ -3922,7 +3932,7 @@ int produce_content(struct session *s)
                s->flags |= SN_ERR_PRXCOND;
        if (!(s->flags & SN_FINST_MASK))
                s->flags |= SN_FINST_R;
-       s->flags &= ~SN_SELF_GEN;
+       buffer_stop_hijack(s->rep);
        return 1;
 }
 
@@ -5297,10 +5307,9 @@ int stats_check_uri_auth(struct session *t, struct proxy *backend)
        /* The request is valid, the user is authenticated. Let's start sending
         * data.
         */
-       EV_FD_CLR(t->req->prod->fd, DIR_RD);
-       buffer_shutr(t->req);
-       buffer_shutr(t->rep);
-       buffer_set_rlim(t->req, BUFSIZE); /* no more rewrite needed */
+       buffer_shutw_now(t->req);
+       buffer_shutr_now(t->rep);
+       buffer_start_hijack(t->rep);
        t->logs.tv_request = now;
        t->data_source = DATA_SRC_STATS;
        t->data_state  = DATA_ST_INIT;