source: bin/varnishd/mgt_param.c @ 7e8d11

Revision 7e8d11, 26.8 KB checked in by Poul-Henning Kamp <phk@…>, 5 years ago (diff)

Remove some unnecessary #includes

git-svn-id:  http://www.varnish-cache.org/svn/trunk/varnish-cache@4234 d4fa192b-c00b-0410-8231-f00ffab90ce4

  • Property mode set to 100644
Line 
1/*-
2 * Copyright (c) 2006 Verdens Gang AS
3 * Copyright (c) 2006-2009 Linpro AS
4 * All rights reserved.
5 *
6 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include "config.h"
31
32#include "svnid.h"
33SVNID("$Id$")
34
35#include <sys/types.h>
36#include <sys/stat.h>
37
38#include <grp.h>
39#include <limits.h>
40#include <pwd.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <unistd.h>
45
46#include "cli.h"
47#include "cli_priv.h"
48#include "cli_common.h"
49#include "mgt.h"
50#include "mgt_cli.h"
51
52#include "heritage.h"
53#include "vparam.h"
54
55#include "vss.h"
56
57#define MAGIC_INIT_STRING       "\001"
58struct params master;
59static int nparspec;
60static struct parspec const ** parspec;
61static int margin;
62
63/*--------------------------------------------------------------------*/
64
65static const struct parspec *
66mcf_findpar(const char *name)
67{
68        int i;
69
70        for (i = 0; i < nparspec; i++)
71                if (!strcmp(parspec[i]->name, name)) 
72                        return (parspec[i]);
73        return (NULL);
74}
75
76/*--------------------------------------------------------------------*/
77
78static void
79tweak_generic_timeout(struct cli *cli, volatile unsigned *dst, const char *arg)
80{
81        unsigned u;
82
83        if (arg != NULL) {
84                u = strtoul(arg, NULL, 0);
85                if (u == 0) {
86                        cli_out(cli, "Timeout must be greater than zero\n");
87                        cli_result(cli, CLIS_PARAM);
88                        return;
89                }
90                *dst = u;
91        } else
92                cli_out(cli, "%u", *dst);
93}
94
95static void
96tweak_generic_timeout_double(struct cli *cli, volatile double *dst, const char *arg)
97{
98        double u;
99
100        if (arg != NULL) {
101                u = strtod(arg, NULL);
102                if (u < 0) {
103                        cli_out(cli,
104                            "Timeout must be greater or equal to zero\n");
105                        cli_result(cli, CLIS_PARAM);
106                        return;
107                }
108                *dst = u;
109        } else
110                cli_out(cli, "%f", *dst);
111}
112
113
114/*--------------------------------------------------------------------*/
115
116void
117tweak_timeout(struct cli *cli, const struct parspec *par, const char *arg)
118{
119        volatile unsigned *dest;
120
121        dest = par->priv;
122        tweak_generic_timeout(cli, dest, arg);
123}
124
125static void
126tweak_timeout_double(struct cli *cli, const struct parspec *par, const char *arg)
127{
128        volatile double *dest;
129
130        dest = par->priv;
131        tweak_generic_timeout_double(cli, dest, arg);
132}
133/*--------------------------------------------------------------------*/
134
135static void
136tweak_generic_bool(struct cli *cli, volatile unsigned *dest, const char *arg)
137{
138        if (arg != NULL) {
139                if (!strcasecmp(arg, "off"))
140                        *dest = 0;
141                else if (!strcasecmp(arg, "disable"))
142                        *dest = 0;
143                else if (!strcasecmp(arg, "no"))
144                        *dest = 0;
145                else if (!strcasecmp(arg, "false"))
146                        *dest = 0;
147                else if (!strcasecmp(arg, "on"))
148                        *dest = 1;
149                else if (!strcasecmp(arg, "enable"))
150                        *dest = 1;
151                else if (!strcasecmp(arg, "yes"))
152                        *dest = 1;
153                else if (!strcasecmp(arg, "true"))
154                        *dest = 1;
155                else {
156                        cli_out(cli, "use \"on\" or \"off\"\n");
157                        cli_result(cli, CLIS_PARAM);
158                        return;
159                }
160        } else
161                cli_out(cli, *dest ? "on" : "off");
162}
163
164/*--------------------------------------------------------------------*/
165
166static void
167tweak_bool(struct cli *cli, const struct parspec *par, const char *arg)
168{
169        volatile unsigned *dest;
170
171        dest = par->priv;
172        tweak_generic_bool(cli, dest, arg);
173}
174
175/*--------------------------------------------------------------------*/
176
177void
178tweak_generic_uint(struct cli *cli, volatile unsigned *dest, const char *arg,
179    unsigned min, unsigned max)
180{
181        unsigned u;
182
183        if (arg != NULL) {
184                if (!strcasecmp(arg, "unlimited"))
185                        u = UINT_MAX;
186                else
187                        u = strtoul(arg, NULL, 0);
188                if (u < min) {
189                        cli_out(cli, "Must be at least %u\n", min);
190                        cli_result(cli, CLIS_PARAM);
191                        return;
192                }
193                if (u > max) {
194                        cli_out(cli, "Must be no more than %u\n", max);
195                        cli_result(cli, CLIS_PARAM);
196                        return;
197                }
198                *dest = u;
199        } else if (*dest == UINT_MAX) {
200                cli_out(cli, "unlimited", *dest);
201        } else {
202                cli_out(cli, "%u", *dest);
203        }
204}
205
206/*--------------------------------------------------------------------*/
207
208void
209tweak_uint(struct cli *cli, const struct parspec *par, const char *arg)
210{
211        volatile unsigned *dest;
212
213        dest = par->priv;
214        tweak_generic_uint(cli, dest, arg, par->umin, par->umax);
215}
216
217/*--------------------------------------------------------------------
218 * XXX: slightly magic.  We want to initialize to "nobody" (XXX: shouldn't
219 * XXX: that be something autocrap found for us ?) but we don't want to
220 * XXX: fail initialization if that user doesn't exists, even though we
221 * XXX: do want to fail it, in subsequent sets.
222 * XXX: The magic init string is a hack for this.
223 */
224
225static void
226tweak_user(struct cli *cli, const struct parspec *par, const char *arg)
227{
228        struct passwd *pw;
229        struct group *gr;
230
231        (void)par;
232        if (arg != NULL) {
233                if (!strcmp(arg, MAGIC_INIT_STRING)) {
234                        pw = getpwnam("nobody");
235                        if (pw == NULL) {
236                                master.uid = getuid();
237                                return;
238                        }
239                } else
240                        pw = getpwnam(arg);
241                if (pw == NULL) {
242                        cli_out(cli, "Unknown user");
243                        cli_result(cli, CLIS_PARAM);
244                        return;
245                }
246                REPLACE(master.user, pw->pw_name);
247                master.uid = pw->pw_uid;
248                master.gid = pw->pw_gid;
249
250                /* set group to user's primary group */
251                if ((gr = getgrgid(pw->pw_gid)) != NULL &&
252                    (gr = getgrnam(gr->gr_name)) != NULL &&
253                    gr->gr_gid == pw->pw_gid)
254                        REPLACE(master.group, gr->gr_name);
255        } else if (master.user) {
256                cli_out(cli, "%s (%d)", master.user, (int)master.uid);
257        } else {
258                cli_out(cli, "%d", (int)master.uid);
259        }
260}
261
262/*--------------------------------------------------------------------
263 * XXX: see comment for tweak_user, same thing here.
264 */
265
266static void
267tweak_group(struct cli *cli, const struct parspec *par, const char *arg)
268{
269        struct group *gr;
270
271        (void)par;
272        if (arg != NULL) {
273                if (!strcmp(arg, MAGIC_INIT_STRING)) {
274                        gr = getgrnam("nogroup");
275                        if (gr == NULL) {
276                                /* Only replace if tweak_user didn't */
277                                if (master.gid == 0)
278                                        master.gid = getgid();
279                                return;
280                        }
281                } else
282                        gr = getgrnam(arg);
283                if (gr == NULL) {
284                        cli_out(cli, "Unknown group");
285                        cli_result(cli, CLIS_PARAM);
286                        return;
287                }
288                REPLACE(master.group, gr->gr_name);
289                master.gid = gr->gr_gid;
290        } else if (master.group) {
291                cli_out(cli, "%s (%d)", master.group, (int)master.gid);
292        } else {
293                cli_out(cli, "%d", (int)master.gid);
294        }
295}
296
297/*--------------------------------------------------------------------*/
298
299static void
300clean_listen_sock_head(struct listen_sock_head *lsh)
301{
302        struct listen_sock *ls, *ls2;
303
304        VTAILQ_FOREACH_SAFE(ls, lsh, list, ls2) {
305                VTAILQ_REMOVE(lsh, ls, list);
306                free(ls->name);
307                free(ls->addr);
308                free(ls);
309        }
310}
311
312static void
313tweak_listen_address(struct cli *cli, const struct parspec *par,
314    const char *arg)
315{
316        char **av;
317        int i;
318        struct listen_sock              *ls;
319        struct listen_sock_head         lsh;
320
321        (void)par;
322        if (arg == NULL) {
323                cli_quote(cli, master.listen_address);
324                return;
325        }
326
327        av = ParseArgv(arg, ARGV_COMMA);
328        if (av == NULL) {
329                cli_out(cli, "Parse error: out of memory");
330                cli_result(cli, CLIS_PARAM);
331                return;
332        }
333        if (av[0] != NULL) {
334                cli_out(cli, "Parse error: %s", av[0]);
335                cli_result(cli, CLIS_PARAM);
336                FreeArgv(av);
337                return;
338        }
339        if (av[1] == NULL) {
340                cli_out(cli, "Empty listen address");
341                cli_result(cli, CLIS_PARAM);
342                FreeArgv(av);
343                return;
344        }
345        VTAILQ_INIT(&lsh);
346        for (i = 1; av[i] != NULL; i++) {
347                struct vss_addr **ta;
348                char *host, *port;
349                int j, n;
350
351                if (VSS_parse(av[i], &host, &port) != 0) {
352                        cli_out(cli, "Invalid listen address ");
353                        cli_quote(cli, av[i]);
354                        cli_result(cli, CLIS_PARAM);
355                        break;
356                }
357                n = VSS_resolve(host, port ? port : "http", &ta);
358                free(host);
359                free(port);
360                if (n == 0) {
361                        cli_out(cli, "Invalid listen address ");
362                        cli_quote(cli, av[i]);
363                        cli_result(cli, CLIS_PARAM);
364                        break;
365                }
366                for (j = 0; j < n; ++j) {
367                        ls = calloc(sizeof *ls, 1);
368                        AN(ls);
369                        ls->sock = -1;
370                        ls->addr = ta[j];
371                        ls->name = strdup(av[i]);
372                        AN(ls->name);
373                        VTAILQ_INSERT_TAIL(&lsh, ls, list);
374                }
375                free(ta);
376        }
377        FreeArgv(av);
378        if (cli != NULL && cli->result != CLIS_OK) {
379                clean_listen_sock_head(&lsh);
380                return;
381        }
382
383        REPLACE(master.listen_address, arg);
384
385        clean_listen_sock_head(&heritage.socks);
386        heritage.nsocks = 0;
387
388        while (!VTAILQ_EMPTY(&lsh)) {
389                ls = VTAILQ_FIRST(&lsh);
390                VTAILQ_REMOVE(&lsh, ls, list);
391                VTAILQ_INSERT_TAIL(&heritage.socks, ls, list);
392                heritage.nsocks++;
393        }
394}
395
396/*--------------------------------------------------------------------*/
397
398static void
399tweak_cc_command(struct cli *cli, const struct parspec *par, const char *arg)
400{
401
402        /* XXX should have tweak_generic_string */
403        (void)par;
404        if (arg == NULL) {
405                cli_quote(cli, mgt_cc_cmd);
406        } else {
407                free(mgt_cc_cmd);
408                mgt_cc_cmd = strdup(arg);
409                XXXAN(mgt_cc_cmd);
410        }
411}
412
413/*--------------------------------------------------------------------*/
414
415static void
416tweak_waiter(struct cli *cli, const struct parspec *par, const char *arg)
417{
418
419        /* XXX should have tweak_generic_string */
420        (void)par;
421        VCA_tweak_waiter(cli, arg);
422}
423
424/*--------------------------------------------------------------------*/
425
426static void
427tweak_diag_bitmap(struct cli *cli, const struct parspec *par, const char *arg)
428{
429        unsigned u;
430
431        (void)par;
432        if (arg != NULL) {
433                u = strtoul(arg, NULL, 0);
434                master.diag_bitmap = u;
435        } else {
436                cli_out(cli, "0x%x", master.diag_bitmap);
437        }
438}
439
440/*--------------------------------------------------------------------*/
441
442/*
443 * Make sure to end all lines with either a space or newline of the
444 * formatting will go haywire.
445 */
446
447#define DELAYED_EFFECT_TEXT \
448        "\nNB: This parameter may take quite some time to take (full) effect."
449
450#define MUST_RESTART_TEXT \
451        "\nNB: This parameter will not take any effect until the " \
452        "child process has been restarted."
453
454#define MUST_RELOAD_TEXT \
455        "\nNB: This parameter will not take any effect until the " \
456        "VCL programs have been reloaded."
457
458#define EXPERIMENTAL_TEXT \
459        "\nNB: We do not know yet if it is a good idea to change " \
460        "this parameter, or if the default value is even sensible.  " \
461        "Caution is advised, and feedback is most welcome."
462
463/*
464 * Remember to update varnishd.1 whenever you add / remove a parameter or
465 * change its default value.
466 * XXX: we should generate the relevant section of varnishd.1 from here.
467 */
468static const struct parspec input_parspec[] = {
469        { "user", tweak_user, NULL, 0, 0,
470                "The unprivileged user to run as.  Setting this will "
471                "also set \"group\" to the specified user's primary group.",
472                MUST_RESTART,
473                MAGIC_INIT_STRING },
474        { "group", tweak_group, NULL, 0, 0,
475                "The unprivileged group to run as.",
476                MUST_RESTART,
477                MAGIC_INIT_STRING },
478        { "default_ttl", tweak_uint, &master.default_ttl, 0, UINT_MAX,
479                "The TTL assigned to objects if neither the backend nor "
480                "the VCL code assigns one.\n"
481                "Objects already cached will not be affected by changes "
482                "made until they are fetched from the backend again.\n"
483                "To force an immediate effect at the expense of a total "
484                "flush of the cache use \"url.purge .\"",
485                0,
486                "120", "seconds" },
487        { "sess_workspace", tweak_uint, &master.sess_workspace, 1024, UINT_MAX,
488                "Bytes of HTTP protocol workspace allocated for sessions. "
489                "This space must be big enough for the entire HTTP protocol "
490                "header and any edits done to it in the VCL code.\n"
491                "Minimum is 1024 bytes.",
492                DELAYED_EFFECT,
493                "16384", "bytes" },
494        { "obj_workspace", tweak_uint, &master.obj_workspace, 0, UINT_MAX,
495                "Bytes of HTTP protocol workspace allocated for objects. "
496                "This space must be big enough for the entire HTTP protocol "
497                "header and any edits done to it in the VCL code while it "
498                "is cached.\n"
499                "Minimum is 1024 bytes.",
500                DELAYED_EFFECT,
501                "0", "bytes" },
502        { "shm_workspace", tweak_uint, &master.shm_workspace, 4096, UINT_MAX,
503                "Bytes of shmlog workspace allocated for worker threads. "
504                "If too big, it wastes some ram, if too small it causes "
505                "needless flushes of the SHM workspace.\n"
506                "These flushes show up in stats as "
507                "\"SHM flushes due to overflow\".\n"
508                "Minimum is 4096 bytes.",
509                DELAYED_EFFECT,
510                "8192", "bytes" },
511        { "shm_reclen", tweak_uint, &master.shm_reclen, 16, 65535,
512                "Maximum number of bytes in SHM log record.\n"
513                "Maximum is 65535 bytes.",
514                0,
515                "255", "bytes" },
516        { "default_grace", tweak_uint, &master.default_grace, 0, UINT_MAX,
517                "Default grace period.  We will deliver an object "
518                "this long after it has expired, provided another thread "
519                "is attempting to get a new copy.",
520                DELAYED_EFFECT,
521                "10" "seconds" },
522        { "sess_timeout", tweak_timeout, &master.sess_timeout, 0, 0,
523                "Idle timeout for persistent sessions. "
524                "If a HTTP request has not been received in this many "
525                "seconds, the session is closed.",
526                0,
527                "5", "seconds" },
528        { "pipe_timeout", tweak_timeout, &master.pipe_timeout, 0, 0,
529                "Idle timeout for PIPE sessions. "
530                "If nothing have been received in either direction for "
531                "this many seconds, the session is closed.\n",
532                0,
533                "60", "seconds" },
534        { "send_timeout", tweak_timeout, &master.send_timeout, 0, 0,
535                "Send timeout for client connections. "
536                "If no data has been sent to the client in this many seconds, "
537                "the session is closed.\n"
538                "See setsockopt(2) under SO_SNDTIMEO for more information.",
539                DELAYED_EFFECT,
540                "600", "seconds" },
541        { "auto_restart", tweak_bool, &master.auto_restart, 0, 0,
542                "Restart child process automatically if it dies.\n",
543                0,
544                "on", "bool" },
545        { "fetch_chunksize",
546                tweak_uint, &master.fetch_chunksize, 4, UINT_MAX / 1024,
547                "The default chunksize used by fetcher. "
548                "This should be bigger than the majority of objects with "
549                "short TTLs.\n"
550                "Internal limits in the storage_file module makes increases "
551                "above 128kb a dubious idea.",
552                EXPERIMENTAL,
553                "128", "kilobytes" },
554#ifdef SENDFILE_WORKS
555        { "sendfile_threshold",
556                tweak_uint, &master.sendfile_threshold, 0, UINT_MAX,
557                "The minimum size of objects transmitted with sendfile.",
558                EXPERIMENTAL,
559                "-1", "bytes" },
560#endif /* SENDFILE_WORKS */
561        { "vcl_trace", tweak_bool,  &master.vcl_trace, 0, 0,
562                "Trace VCL execution in the shmlog.\n"
563                "Enabling this will allow you to see the path each "
564                "request has taken through the VCL program.\n"
565                "This generates a lot of logrecords so it is off by "
566                "default.",
567                0,
568                "off", "bool" },
569        { "listen_address", tweak_listen_address, NULL, 0, 0,
570                "Whitespace separated list of network endpoints where "
571                "Varnish will accept requests.\n"
572                "Possible formats: host, host:port, :port",
573                MUST_RESTART,
574                ":80" },
575        { "listen_depth", tweak_uint, &master.listen_depth, 0, UINT_MAX,
576                "Listen queue depth.",
577                MUST_RESTART,
578                "1024", "connections" },
579        { "client_http11", tweak_bool, &master.client_http11, 0, 0,
580                "Force all client responses to be HTTP/1.1.\n"
581                "By default we copy the protocol version from the "
582                "backend response.",
583                EXPERIMENTAL,
584                "off", "bool" },
585        { "cli_timeout", tweak_timeout, &master.cli_timeout, 0, 0,
586                "Timeout for the childs replies to CLI requests from "
587                "the master.",
588                0,
589                "10", "seconds" },
590        { "ping_interval", tweak_uint, &master.ping_interval, 0, UINT_MAX,
591                "Interval between pings from parent to child.\n"
592                "Zero will disable pinging entirely, which makes "
593                "it possible to attach a debugger to the child.",
594                MUST_RESTART,
595                "3", "seconds" },
596        { "lru_interval", tweak_timeout, &master.lru_timeout, 0, 0,
597                "Grace period before object moves on LRU list.\n"
598                "Objects are only moved to the front of the LRU "
599                "list if they have not been moved there already inside "
600                "this timeout period.  This reduces the amount of lock "
601                "operations necessary for LRU list access.",
602                EXPERIMENTAL,
603                "2", "seconds" },
604        { "cc_command", tweak_cc_command, NULL, 0, 0,
605                "Command used for compiling the C source code to a "
606                "dlopen(3) loadable object.  Any occurrence of %s in "
607                "the string will be replaced with the source file name, "
608                "and %o will be replaced with the output file name.",
609                MUST_RELOAD,
610                VCC_CC
611                , NULL },
612        { "max_restarts", tweak_uint, &master.max_restarts, 0, UINT_MAX,
613                "Upper limit on how many times a request can restart."
614                "\nBe aware that restarts are likely to cause a hit against "
615                "the backend, so don't increase thoughtlessly.\n",
616                0,
617                "4", "restarts" },
618        { "esi_syntax",
619                tweak_uint, &master.esi_syntax, 0, UINT_MAX,
620                "Bitmap controlling ESI parsing code:\n"
621                "  0x00000001 - Don't check if it looks like XML\n"
622                "  0x00000002 - Ignore non-esi elements\n"
623                "  0x00000004 - Emit parsing debug records\n"
624                "Use 0x notation and do the bitor in your head :-)\n",
625                0,
626                "0", "bitmap" },
627        { "max_esi_includes",
628                tweak_uint, &master.max_esi_includes, 0, UINT_MAX,
629                "Maximum depth of esi:include processing.\n",
630                0,
631                "5", "includes" },
632        { "cache_vbe_conns", tweak_bool,  &master.cache_vbe_conns, 0, 0,
633                "Cache vbe_conn's or rely on malloc, that's the question.",
634                EXPERIMENTAL,
635                "off", "bool" },
636        { "connect_timeout", tweak_timeout_double,
637                &master.connect_timeout,0, UINT_MAX,
638                "Default connection timeout for backend connections. "
639                "We only try to connect to the backend for this many "
640                "seconds before giving up. "
641                "VCL can override this default value for each backend and "
642                "backend request.",
643                0,
644                "0.4", "s" },
645        { "first_byte_timeout", tweak_timeout_double,
646                &master.first_byte_timeout,0, UINT_MAX,
647                "Default timeout for receiving first byte from backend. "
648                "We only wait for this many seconds for the first "
649                "byte before giving up. A value of 0 means it will never time out. "
650                "VCL can override this default value for each backend and "
651                "backend request. This parameter does not apply to pipe.",
652                0,
653                "60", "s" },
654        { "between_bytes_timeout", tweak_timeout_double,
655                &master.between_bytes_timeout,0, UINT_MAX,
656                "Default timeout between bytes when receiving data from backend. "
657                "We only wait for this many seconds between bytes "
658                "before giving up. A value of 0 means it will never time out. "
659                "VCL can override this default value for each backend request and "
660                "backend request. This parameter does not apply to pipe.",
661                0,
662                "60", "s" },
663        { "accept_fd_holdoff", tweak_timeout,
664                &master.accept_fd_holdoff, 0,  3600*1000,
665                "If we run out of file descriptors, the accept thread will "
666                "sleep.  This parameter control for how long it will sleep.",
667                EXPERIMENTAL,
668                "50", "ms" },
669        { "clock_skew", tweak_uint, &master.clock_skew, 0, UINT_MAX,
670                "How much clockskew we are willing to accept between the "
671                "backend and our own clock.",
672                0,
673                "10", "s" },
674        { "prefer_ipv6", tweak_bool, &master.prefer_ipv6, 0, 0,
675                "Prefer IPv6 address when connecting to backends which "
676                "have both IPv4 and IPv6 addresses.",
677                0,
678                "off", "bool" },
679        { "session_max", tweak_uint,
680                &master.max_sess, 1000, UINT_MAX,
681                "Maximum number of sessions we will allocate "
682                "before just dropping connections.\n"
683                "This is mostly an anti-DoS measure, and setting it plenty "
684                "high should not hurt, as long as you have the memory for "
685                "it.\n",
686                0,
687                "100000", "sessions" },
688        { "session_linger", tweak_uint,
689                &master.session_linger,0, UINT_MAX,
690                "How long time the workerthread lingers on the session "
691                "to see if a new request appears right away.\n"
692                "If sessions are reused, as much as half of all reuses "
693                "happen within the first 100 msec of the previous request "
694                "completing.\n"
695                "Setting this too high results in worker threads not doing "
696                "anything for their keep, setting it too low just means that "
697                "more sessions take a detour around the waiter.",
698                EXPERIMENTAL,
699                "50", "ms" },
700        { "cli_buffer", tweak_uint, &master.cli_buffer, 4096, UINT_MAX,
701                "Size of buffer for CLI input."
702                "\nYou may need to increase this if you have big VCL files "
703                "and use the vcl.inline CLI command.\n"
704                "NB: Must be specified with -p to have effect.\n",
705                0,
706                "8192", "bytes" },
707        { "log_hashstring", tweak_bool, &master.log_hash, 0, 0,
708                "Log the hash string to shared memory log.\n",
709                0,
710                "off", "bool" },
711        { "purge_hash", tweak_bool, &master.save_hash, 0, 0,
712                "Enable purge.hash command.\n"
713                "NB: this increases storage requirement per object "
714                "by the length of the hash string.\n",
715                MUST_RESTART,
716                "off", "bool" },
717        { "log_local_address", tweak_bool, &master.log_local_addr, 0, 0,
718                "Log the local address on the TCP connection in the "
719                "SessionOpen shared memory record.\n",
720                0,
721                "off", "bool" },
722        { "waiter", tweak_waiter, NULL, 0, 0,
723                "Select the waiter kernel interface.\n",
724                EXPERIMENTAL | MUST_RESTART,
725                "default", NULL },
726        { "diag_bitmap", tweak_diag_bitmap, 0, 0, 0,
727                "Bitmap controlling diagnostics code:\n"
728                "  0x00000001 - CNT_Session states.\n"
729                "  0x00000002 - workspace debugging.\n"
730                "  0x00000004 - kqueue debugging.\n"
731                "  0x00000008 - mutex logging.\n"
732                "  0x00000010 - mutex contests.\n"
733                "  0x00000020 - waiting list.\n"
734                "  0x00000040 - object workspace.\n"
735                "  0x00001000 - do not core-dump child process.\n"
736                "  0x00002000 - only short panic message.\n"
737                "  0x00004000 - panic to stderr.\n"
738#ifdef HAVE_ABORT2
739                "  0x00008000 - panic to abort2().\n"
740#endif
741                "  0x00010000 - synchronize shmlog.\n"
742                "  0x00020000 - synchronous start of persistence.\n"
743                "  0x80000000 - do edge-detection on digest.\n"
744                "Use 0x notation and do the bitor in your head :-)\n",
745                0,
746                "0", "bitmap" },
747        { "err_ttl", tweak_uint, &master.err_ttl, 0, UINT_MAX,
748                "The TTL assigned to the synthesized error pages\n",
749                0,
750                "0", "seconds" },
751        { "purge_dups", tweak_bool, &master.purge_dups, 0, 0,
752                "Detect and eliminate duplicate purges.\n",
753                0,
754                "off", "bool" },
755        { "cli_banner", tweak_bool, &master.cli_banner, 0, 0,
756                "Emit CLI banner on connect.\n"
757                "Set to off for compatibility with pre 2.1 versions.\n",
758                0,
759                "on", "bool" },
760        { "ban_lurker_sleep", tweak_timeout_double,
761                &master.ban_lurker_sleep, 0.0, UINT_MAX,
762                "How long time does the ban lurker thread sleeps between "
763                "successfull attempts to push the last item up the purge "
764                " list.  It always sleeps a second when nothing can be done.\n"
765                "A value of zero disables the ban lurker.",
766                0,
767                "0.0", "s" },
768        { NULL, NULL, NULL }
769};
770
771/*--------------------------------------------------------------------*/
772
773#define WIDTH 76
774
775static void
776mcf_wrap(struct cli *cli, const char *text)
777{
778        const char *p, *q;
779
780        /* Format text to COLUMNS width */
781        for (p = text; *p != '\0'; ) {
782                q = strchr(p, '\n');
783                if (q == NULL)
784                        q = strchr(p, '\0');
785                if (q > p + WIDTH - margin) {
786                        q = p + WIDTH - margin;
787                        while (q > p && *q != ' ')
788                                q--;
789                        AN(q);
790                }
791                cli_out(cli, "%*s %.*s\n", margin, "", (int)(q - p), p);
792                p = q;
793                if (*p == ' ' || *p == '\n')
794                        p++;
795        }
796}
797
798void
799mcf_param_show(struct cli *cli, const char * const *av, void *priv)
800{
801        int i;
802        const struct parspec *pp;
803        int lfmt;
804
805        (void)priv;
806        if (av[2] == NULL || strcmp(av[2], "-l"))
807                lfmt = 0;
808        else
809                lfmt = 1;
810        for (i = 0; i < nparspec; i++) {
811                pp = parspec[i];
812                if (av[2] != NULL && !lfmt && strcmp(pp->name, av[2]))
813                        continue;
814                cli_out(cli, "%-*s ", margin, pp->name);
815                if (pp->func == NULL) {
816                        cli_out(cli, "Not implemented.\n");
817                        if (av[2] != NULL && !lfmt)
818                                return;
819                        else
820                                continue;
821                }
822                pp->func(cli, pp, NULL);
823                if (pp->units != NULL)
824                        cli_out(cli, " [%s]\n", pp->units);
825                else
826                        cli_out(cli, "\n");
827                if (av[2] != NULL) {
828                        cli_out(cli, "%-*s Default is %s\n",
829                            margin, "", pp->def);
830                        mcf_wrap(cli, pp->descr);
831                        if (pp->flags & DELAYED_EFFECT)
832                                mcf_wrap(cli, DELAYED_EFFECT_TEXT);
833                        if (pp->flags & EXPERIMENTAL)
834                                mcf_wrap(cli, EXPERIMENTAL_TEXT);
835                        if (pp->flags & MUST_RELOAD)
836                                mcf_wrap(cli, MUST_RELOAD_TEXT);
837                        if (pp->flags & MUST_RESTART)
838                                mcf_wrap(cli, MUST_RESTART_TEXT);
839                        if (!lfmt)
840                                return;
841                        else
842                                cli_out(cli, "\n");
843                }
844        }
845        if (av[2] != NULL && !lfmt) {
846                cli_result(cli, CLIS_PARAM);
847                cli_out(cli, "Unknown parameter \"%s\".", av[2]);
848        }
849}
850
851/*--------------------------------------------------------------------*/
852
853void
854MCF_ParamSync(void)
855{
856        if (params != &master)
857                *params = master;
858}
859
860/*--------------------------------------------------------------------*/
861
862void
863MCF_ParamSet(struct cli *cli, const char *param, const char *val)
864{
865        const struct parspec *pp;
866
867        pp = mcf_findpar(param);
868        if (pp != NULL) {
869                pp->func(cli, pp, val);
870                if (cli->result != CLIS_OK) {
871                } else if (child_pid >= 0 && pp->flags & MUST_RESTART) {
872                        cli_out(cli, "Change will take effect"
873                            " when child is restarted");
874                } else if (pp->flags & MUST_RELOAD) {
875                        cli_out(cli, "Change will take effect"
876                            " when VCL script is reloaded");
877                }
878                MCF_ParamSync();
879                return;
880        }
881        cli_result(cli, CLIS_PARAM);
882        cli_out(cli, "Unknown parameter \"%s\".", param);
883}
884
885
886/*--------------------------------------------------------------------*/
887
888void
889mcf_param_set(struct cli *cli, const char * const *av, void *priv)
890{
891
892        (void)priv;
893        MCF_ParamSet(cli, av[2], av[3]);
894}
895
896/*--------------------------------------------------------------------
897 * Add a group of parameters to the global set and sort by name.
898 */
899
900static int
901parspec_cmp(const void *a, const void *b)
902{
903        struct parspec * const * pa = a;
904        struct parspec * const * pb = b;
905        return (strcmp((*pa)->name, (*pb)->name));
906}
907
908static void
909MCF_AddParams(const struct parspec *ps)
910{
911        const struct parspec *pp;
912        int n;
913
914        n = 0;
915        for (pp = ps; pp->name != NULL; pp++) {
916                if (mcf_findpar(pp->name) != NULL)
917                        fprintf(stderr, "Duplicate param: %s\n", pp->name);
918                if (strlen(pp->name) + 1 > margin)
919                        margin = strlen(pp->name) + 1;
920                n++;
921        }
922        parspec = realloc(parspec, (nparspec + n + 1) * sizeof *parspec);
923        XXXAN(parspec);
924        for (pp = ps; pp->name != NULL; pp++)
925                parspec[nparspec++] = pp;
926        parspec[nparspec] = NULL;
927        qsort (parspec, nparspec, sizeof parspec[0], parspec_cmp);
928}
929
930/*--------------------------------------------------------------------
931 * Set defaults for all parameters
932 */
933
934static void
935MCF_SetDefaults(struct cli *cli)
936{
937        const struct parspec *pp;
938        int i;
939
940        for (i = 0; i < nparspec; i++) {
941                pp = parspec[i];
942                if (cli != NULL)
943                        cli_out(cli,
944                            "Set Default for %s = %s\n", pp->name, pp->def);
945                pp->func(cli, pp, pp->def);
946                if (cli != NULL && cli->result != CLIS_OK)
947                        return;
948        }
949}
950
951/*--------------------------------------------------------------------*/
952
953void
954MCF_ParamInit(struct cli *cli)
955{
956
957        MCF_AddParams(input_parspec);
958        MCF_AddParams(WRK_parspec);
959
960        /* XXX: We do this twice, to get past any interdependencies */
961        MCF_SetDefaults(NULL);
962        MCF_SetDefaults(cli);
963
964        params = &master;
965}
Note: See TracBrowser for help on using the repository browser.