]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] make it possible to change the buffer size in the configuration
authorWilly Tarreau <w@1wt.eu>
Mon, 17 Aug 2009 05:23:33 +0000 (07:23 +0200)
committerWilly Tarreau <w@1wt.eu>
Mon, 17 Aug 2009 20:56:56 +0000 (22:56 +0200)
The new tune.bufsize and tune.maxrewrite global directives allow one to
change the buffer size and the maxrewrite size. Right now, setting bufsize
too low will block stats sockets which will not be able to write at all.
An error checking must be added to buffer_write_chunk() so that if it
cannot write its message to an empty buffer, it causes the caller to abort.

doc/configuration.txt
include/types/global.h
src/buffers.c
src/cfgparse.c
src/client.c
src/haproxy.c
src/proto_uxst.c
src/session.c

index 50f82e577d54f31c04662b4764b66b0adf70ae3d..84fc9c9218fb42f6cd5e3633930ad281c47b105c 100644 (file)
@@ -381,8 +381,10 @@ The following keywords are supported in the "global" section :
    - nosepoll
    - nosplice
    - spread-checks
+   - tune.bufsize
    - tune.maxaccept
    - tune.maxpollevents
+   - tune.maxrewrite
   
  * Debugging
    - debug
@@ -557,6 +559,16 @@ spread-checks <0..50, in percent>
   some randomness in the check interval between 0 and +/- 50%. A value between
   2 and 5 seems to show good results. The default value remains at 0.
 
+tune.bufsize <number>
+  Sets the buffer size to this size (in bytes). Lower values allow more
+  sessions to coexist in the same amount of RAM, and higher values allow some
+  applications with very large cookies to work. The default value is 16384 and
+  can be changed at build time. It is strongly recommended not to change this
+  from the default value, as very low values will break some services such as
+  statistics, and values larger than default size will increase memory usage,
+  possibly causing the system to run out of memory. At least the global maxconn
+  parameter should be decreased by the same factor as this one is increased.
+
 tune.maxaccept <number>
   Sets the maximum number of consecutive accepts that a process may perform on
   a single wake up. High values give higher priority to high connection rates,
@@ -574,6 +586,18 @@ tune.maxpollevents <number>
   latency at the expense of network bandwidth, and increasing it above 200
   tends to trade latency for slightly increased bandwidth.
 
+tune.maxrewrite <number>
+  Sets the reserved buffer space to this size in bytes. The reserved space is
+  used for header rewriting or appending. The first reads on sockets will never
+  fill more than bufsize-maxrewrite. Historically it has defaulted to half of
+  bufsize, though that does not make much sense since there are rarely large
+  numbers of headers to add. Setting it too high prevents processing of large
+  requests or responses. Setting it too low prevents addition of new headers
+  to already large requests or to POST requests. It is generally wise to set it
+  to about 1024. It is automatically readjusted to half of bufsize if it is
+  larger than that. This means you don't have to worry about it when changing
+  bufsize.
+
 
 3.3. Debugging
 --------------
index aefee3226093466b63aff81675903b8372530954..4d349c3136985b697524902e64422fbcd7a57256 100644 (file)
@@ -79,6 +79,8 @@ struct global {
                int maxaccept;     /* max number of consecutive accept() */
                int options;       /* various tuning options */
                int recv_enough;   /* how many input bytes at once are "enough" */
+               int bufsize;       /* buffer size in bytes, defaults to BUFSIZE */
+               int maxrewrite;    /* buffer max rewrite size in bytes, defaults to MAXREWRITE */
        } tune;
        struct listener stats_sock; /* unix socket listener for statistics */
        struct proxy *stats_fe;     /* the frontend holding the stats settings */
index 55b79639b7ea289a8aac50055cd30511791a80eb..a20f3f499b814c65076e1b6d1a779c62e68b95e6 100644 (file)
@@ -17,6 +17,7 @@
 #include <common/config.h>
 #include <common/memory.h>
 #include <proto/buffers.h>
+#include <types/global.h>
 
 struct pool_head *pool2_buffer;
 
@@ -24,7 +25,7 @@ struct pool_head *pool2_buffer;
 /* perform minimal intializations, report 0 in case of error, 1 if OK. */
 int init_buffer()
 {
-       pool2_buffer = create_pool("buffer", sizeof(struct buffer) + BUFSIZE, MEM_F_SHARED);
+       pool2_buffer = create_pool("buffer", sizeof(struct buffer) + global.tune.bufsize, MEM_F_SHARED);
        return pool2_buffer != NULL;
 }
 
index a6b9f07ce3e941945139dd3a3a6d411e4483f5c6..3828812255e315aec7a5b1fdb8efe3c51ff38458 100644 (file)
@@ -445,6 +445,26 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
                }
                global.tune.maxaccept = atol(args[1]);
        }
+       else if (!strcmp(args[0], "tune.bufsize")) {
+               if (*(args[1]) == 0) {
+                       Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
+               }
+               global.tune.bufsize = atol(args[1]);
+               if (global.tune.maxrewrite >= global.tune.bufsize / 2)
+                       global.tune.maxrewrite = global.tune.bufsize / 2;
+       }
+       else if (!strcmp(args[0], "tune.maxrewrite")) {
+               if (*(args[1]) == 0) {
+                       Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
+               }
+               global.tune.maxrewrite = atol(args[1]);
+               if (global.tune.maxrewrite >= global.tune.bufsize / 2)
+                       global.tune.maxrewrite = global.tune.bufsize / 2;
+       }
        else if (!strcmp(args[0], "uid")) {
                if (global.uid != 0) {
                        Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
@@ -3482,13 +3502,13 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
                        goto out;
                }
 
-               if (stat.st_size <= BUFSIZE) {
+               if (stat.st_size <= global.tune.bufsize) {
                        errlen = stat.st_size;
                } else {
                        Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
-                               file, linenum, args[2], BUFSIZE);
+                               file, linenum, args[2], global.tune.bufsize);
                        err_code |= ERR_WARN;
-                       errlen = BUFSIZE;
+                       errlen = global.tune.bufsize;
                }
 
                err = malloc(errlen); /* malloc() must succeed during parsing */
index 92baefc63bb8580f1f4a2bc86326c289a6caf9ef..76ea122c988a5e6f720e6b2a6ab32bd0f5b53eea 100644 (file)
@@ -384,7 +384,7 @@ int event_accept(int fd) {
                if ((s->req = pool_alloc2(pool2_buffer)) == NULL)
                        goto out_fail_req; /* no memory */
 
-               s->req->size = BUFSIZE;
+               s->req->size = global.tune.bufsize;
                buffer_init(s->req);
                s->req->prod = &s->si[0];
                s->req->cons = &s->si[1];
@@ -393,7 +393,7 @@ int event_accept(int fd) {
                s->req->flags |= BF_READ_ATTACHED; /* the producer is already connected */
 
                if (p->mode == PR_MODE_HTTP) { /* reserve some space for header rewriting */
-                       s->req->max_len -= MAXREWRITE;
+                       s->req->max_len -= global.tune.maxrewrite;
                        s->req->flags |= BF_READ_DONTWAIT; /* one read is usually enough */
                }
 
@@ -411,7 +411,7 @@ int event_accept(int fd) {
                if ((s->rep = pool_alloc2(pool2_buffer)) == NULL)
                        goto out_fail_rep; /* no memory */
 
-               s->rep->size = BUFSIZE;
+               s->rep->size = global.tune.bufsize;
                buffer_init(s->rep);
                s->rep->prod = &s->si[1];
                s->rep->cons = &s->si[0];
index 09f828809df51c93ae7ff838cd668758469d6b87..dd03e32aa48cbe583460b81a55df59882e8c47b6 100644 (file)
@@ -122,7 +122,11 @@ struct global global = {
                                 .mode = 0,
                         }
                 }
-       }
+       },
+       .tune = {
+               .bufsize = BUFSIZE,
+               .maxrewrite = MAXREWRITE,
+       },
        /* others NULL OK */
 };
 
@@ -177,7 +181,10 @@ void display_build_opts()
 #ifdef BUILD_OPTIONS
               "\n  OPTIONS = " BUILD_OPTIONS
 #endif
-              "\n\n");
+              "\n\nDefault settings :"
+              "\n  maxconn = %d, bufsize = %d, maxrewrite = %d, maxpollevents = %d"
+              "\n\n",
+              DEFAULT_MAXCONN, BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
 }
 
 /*
@@ -604,6 +611,9 @@ void init(int argc, char **argv)
        if (global.tune.recv_enough == 0)
                global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
 
+       if (global.tune.maxrewrite >= global.tune.bufsize / 2)
+               global.tune.maxrewrite = global.tune.bufsize / 2;
+
        if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
                /* command line debug mode inhibits configuration mode */
                global.mode &= ~(MODE_DAEMON | MODE_QUIET);
index 0cd6a35865c34210be4c9e33daca3be8d88d4d75..c811f64a84564b97339700ed9b215d336b0f316d 100644 (file)
@@ -482,7 +482,7 @@ int uxst_event_accept(int fd) {
                if ((s->req = pool_alloc2(pool2_buffer)) == NULL)
                        goto out_free_task;
 
-               s->req->size = BUFSIZE;
+               s->req->size = global.tune.bufsize;
                buffer_init(s->req);
                s->req->prod = &s->si[0];
                s->req->cons = &s->si[1];
@@ -499,7 +499,7 @@ int uxst_event_accept(int fd) {
                if ((s->rep = pool_alloc2(pool2_buffer)) == NULL)
                        goto out_free_req;
 
-               s->rep->size = BUFSIZE;
+               s->rep->size = global.tune.bufsize;
                buffer_init(s->rep);
 
                s->rep->prod = &s->si[1];
index 23c4409c6884045a90fcc2faf7a755673d2a4462..f0c2d8658eeca00ac51ea3581ceabd19cfe7db23 100644 (file)
@@ -330,7 +330,7 @@ void sess_establish(struct session *s, struct stream_interface *si)
                }
        }
        else {
-               buffer_set_rlim(rep, req->size - MAXREWRITE); /* rewrite needed */
+               buffer_set_rlim(rep, req->size - global.tune.maxrewrite); /* rewrite needed */
                s->txn.rsp.msg_state = HTTP_MSG_RPBEFORE;
                /* reset hdr_idx which was already initialized by the request.
                 * right now, the http parser does it.