From 2d89b34bb9df21128c949913ae8dfb035648c52b Mon Sep 17 00:00:00 2001 From: phk Date: Thu, 8 Mar 2007 10:09:18 +0000 Subject: [PATCH] Make Varnish able to accept connections from multiple sockets by specifying a whitespace separated list of addresses to -a (or param.set listen_address). I'm not sure about the error handling, for instance, what is the desirable behaviour if one of multiple sockets fail to open ? Suggested by: git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@1280 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/cache_acceptor.c | 71 +++++++++------ varnish-cache/bin/varnishd/heritage.h | 29 +++--- varnish-cache/bin/varnishd/mgt_child.c | 46 +++++++--- varnish-cache/bin/varnishd/mgt_param.c | 99 ++++++++++++++++----- varnish-cache/bin/varnishd/varnishd.c | 3 +- 5 files changed, 178 insertions(+), 70 deletions(-) diff --git a/varnish-cache/bin/varnishd/cache_acceptor.c b/varnish-cache/bin/varnishd/cache_acceptor.c index ddddaaac..3d267e7b 100644 --- a/varnish-cache/bin/varnishd/cache_acceptor.c +++ b/varnish-cache/bin/varnishd/cache_acceptor.c @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -137,47 +138,65 @@ vca_acct(void *arg) struct sess *sp; socklen_t l; struct sockaddr addr[2]; /* XXX: IPv6 hack */ - int i; + int i, j; + struct pollfd *pfd; + struct listen_sock *ls; (void)arg; + + /* Set up the poll argument */ + pfd = calloc(sizeof *pfd, heritage.nsocks); + AN(pfd); + i = 0; + TAILQ_FOREACH(ls, &heritage.socks, list) { + AZ(setsockopt(ls->sock, SOL_SOCKET, SO_LINGER, + &linger, sizeof linger)); + pfd[i].events = POLLIN; + pfd[i++].fd = ls->sock; + } + need_test = 1; - AZ(setsockopt(heritage.socket, SOL_SOCKET, SO_LINGER, - &linger, sizeof linger)); while (1) { if (params->send_timeout != tv_sndtimeo.tv_sec) { need_test = 1; tv_sndtimeo.tv_sec = params->send_timeout; - AZ(setsockopt(heritage.socket, SOL_SOCKET, - SO_SNDTIMEO, &tv_sndtimeo, sizeof tv_sndtimeo)); + TAILQ_FOREACH(ls, &heritage.socks, list) + AZ(setsockopt(ls->sock, SOL_SOCKET, + SO_SNDTIMEO, &tv_sndtimeo, sizeof tv_sndtimeo)); } if (params->sess_timeout != tv_rcvtimeo.tv_sec) { need_test = 1; tv_rcvtimeo.tv_sec = params->sess_timeout; - AZ(setsockopt(heritage.socket, SOL_SOCKET, - SO_RCVTIMEO, &tv_rcvtimeo, sizeof tv_rcvtimeo)); + TAILQ_FOREACH(ls, &heritage.socks, list) + AZ(setsockopt(ls->sock, SOL_SOCKET, + SO_RCVTIMEO, &tv_rcvtimeo, sizeof tv_rcvtimeo)); } - VSL_stats->client_conn++; - - l = sizeof addr; - i = accept(heritage.socket, addr, &l); - if (i < 0) { - if (errno != EAGAIN) { - VSL(SLT_Debug, heritage.socket, - "Accept failed errno=%d", errno); - /* XXX: stats ? */ + i = poll(pfd, heritage.nsocks, 1000); + for (j = 0; j < heritage.nsocks; j++) { + if (pfd[j].revents == 0) + continue; + VSL_stats->client_conn++; + l = sizeof addr; + i = accept(pfd[j].fd, addr, &l); + if (i < 0) { + if (errno != EAGAIN) { + VSL(SLT_Debug, pfd[j].fd, + "Accept failed errno=%d", errno); + /* XXX: stats ? */ + } + continue; } - continue; - } - sp = SES_New(addr, l); - XXXAN(sp); + sp = SES_New(addr, l); + XXXAN(sp); - sp->fd = i; - sp->id = i; - (void)clock_gettime(CLOCK_REALTIME, &sp->t_open); + sp->fd = i; + sp->id = i; + (void)clock_gettime(CLOCK_REALTIME, &sp->t_open); - http_RecvPrep(sp->http); - sp->step = STP_FIRST; - WRK_QueueSession(sp); + http_RecvPrep(sp->http); + sp->step = STP_FIRST; + WRK_QueueSession(sp); + } } } diff --git a/varnish-cache/bin/varnishd/heritage.h b/varnish-cache/bin/varnishd/heritage.h index 98bd3009..4197b16b 100644 --- a/varnish-cache/bin/varnishd/heritage.h +++ b/varnish-cache/bin/varnishd/heritage.h @@ -31,27 +31,38 @@ * This file contains the heritage passed when mgt forks cache */ +#include "queue.h" + +struct listen_sock { + TAILQ_ENTRY(listen_sock) list; + int sock; + char *host; + char *port; +}; + +TAILQ_HEAD(listen_sock_head, listen_sock); + struct heritage { /* * Two pipe(2)'s for CLI connection between cache and mgt. * cache reads [2] and writes [1]. Mgt reads [0] and writes [3]. */ - int fds[4]; + int fds[4]; - /* Socket from which to accept connections */ - int socket; + /* Sockets from which to accept connections */ + struct listen_sock_head socks; + int nsocks; /* Share memory log fd and size (incl header) */ - int vsl_fd; - unsigned vsl_size; + int vsl_fd; + unsigned vsl_size; /* Storage method */ - struct stevedore *stevedore; + struct stevedore *stevedore; /* Hash method */ - struct hash_slinger *hash; - + struct hash_slinger *hash; }; struct params { @@ -89,8 +100,6 @@ struct params { /* Listen address */ char *listen_address; - char *listen_host; - char *listen_port; /* Listen depth */ unsigned listen_depth; diff --git a/varnish-cache/bin/varnishd/mgt_child.c b/varnish-cache/bin/varnishd/mgt_child.c index 4e85bbda..45a84669 100644 --- a/varnish-cache/bin/varnishd/mgt_child.c +++ b/varnish-cache/bin/varnishd/mgt_child.c @@ -122,6 +122,38 @@ child_poker(struct ev *e, int what) /*--------------------------------------------------------------------*/ +static int +open_sockets(void) +{ + struct listen_sock *ls; + + TAILQ_FOREACH(ls, &heritage.socks, list) { + if (ls->sock >= 0) + continue; + ls->sock = TCP_open(ls->host, ls->port, 1); + if (ls->sock < 0) + return (1); + } + return (0); +} + +/*--------------------------------------------------------------------*/ + +static void +close_sockets(void) +{ + struct listen_sock *ls; + + TAILQ_FOREACH(ls, &heritage.socks, list) { + if (ls->sock < 0) + continue; + close(ls->sock); + ls->sock = -1; + } +} + +/*--------------------------------------------------------------------*/ + static void start_child(void) { @@ -133,12 +165,8 @@ start_child(void) if (child_state != CH_STOPPED && child_state != CH_DIED) return; - if (heritage.socket < 0) { - heritage.socket = - TCP_open(params->listen_host, params->listen_port, 1); - if (heritage.socket < 0) - return; - } + if (open_sockets()) + return; /* XXX ?? */ child_state = CH_STARTING; @@ -219,8 +247,7 @@ stop_child(void) if (child_state != CH_RUNNING) return; - close(heritage.socket); - heritage.socket = -1; + close_sockets(); child_state = CH_STOPPING; if (ev_poker != NULL) { @@ -295,8 +322,7 @@ mgt_sigchld(struct ev *e, int what) if (child_state == CH_DIED && params->auto_restart) start_child(); else if (child_state == CH_DIED) { - close(heritage.socket); - heritage.socket = -1; + close_sockets(); child_state = CH_STOPPED; } else if (child_state == CH_STOPPING) diff --git a/varnish-cache/bin/varnishd/mgt_param.c b/varnish-cache/bin/varnishd/mgt_param.c index 69298cc2..0287346f 100644 --- a/varnish-cache/bin/varnishd/mgt_param.c +++ b/varnish-cache/bin/varnishd/mgt_param.c @@ -277,34 +277,87 @@ tweak_vcl_trace(struct cli *cli, struct parspec *par, const char *arg) /*--------------------------------------------------------------------*/ +static void +clean_listen_sock_head(struct listen_sock_head *lsh) +{ + struct listen_sock *ls, *ls2; + + TAILQ_FOREACH_SAFE(ls, lsh, list, ls2) { + TAILQ_REMOVE(lsh, ls, list); + free(ls->host); + free(ls->port); + free(ls); + } +} + static void tweak_listen_address(struct cli *cli, struct parspec *par, const char *arg) { - char *a, *p; + char **av; + int i; + struct listen_sock *ls; + struct listen_sock_head lsh; (void)par; - if (arg != NULL) { - if (TCP_parse(arg, &a, &p) != 0) { - cli_out(cli, "Invalid listen address"); + if (arg == NULL) { + /* Quote the string if we have more than one socket */ + if (heritage.nsocks > 1) + cli_out(cli, "\"%s\"", params->listen_address); + else + cli_out(cli, "%s", params->listen_address); + return; + } + + av = ParseArgv(arg, 0); + if (av[0] != NULL) { + cli_out(cli, "Parse error: %s", av[0]); + cli_result(cli, CLIS_PARAM); + FreeArgv(av); + return; + } + if (av[1] == NULL) { + cli_out(cli, "Empty listen address"); + cli_result(cli, CLIS_PARAM); + FreeArgv(av); + return; + } + TAILQ_INIT(&lsh); + for (i = 1; av[i] != NULL; i++) { + ls = calloc(sizeof *ls, 1); + AN(ls); + ls->sock = -1; + TAILQ_INSERT_TAIL(&lsh, ls, list); + if (TCP_parse(av[i], &ls->host, &ls->port) != 0) { + cli_out(cli, "Invalid listen address \"%s\"", av[i]); cli_result(cli, CLIS_PARAM); - return; + break; } - if (p == NULL) { - p = strdup("http"); - AN(p); - } - TCP_check(cli, a, p); + if (ls->port == NULL) + ls->port = strdup("http"); + AN(ls->port); + TCP_check(cli, ls->host, ls->port); if (cli->result != CLIS_OK) - return; - free(params->listen_address); - free(params->listen_host); - free(params->listen_port); - params->listen_address = strdup(arg); - AN(params->listen_address); - params->listen_host = a; - params->listen_port = p; - } else - cli_out(cli, "%s", params->listen_address); + break; + } + FreeArgv(av); + if (cli->result != CLIS_OK) { + clean_listen_sock_head(&lsh); + return; + } + + free(params->listen_address); + params->listen_address = strdup(arg); + AN(params->listen_address); + + clean_listen_sock_head(&heritage.socks); + heritage.nsocks = 0; + + while (!TAILQ_EMPTY(&lsh)) { + ls = TAILQ_FIRST(&lsh); + TAILQ_REMOVE(&lsh, ls, list); + TAILQ_INSERT_TAIL(&heritage.socks, ls, list); + heritage.nsocks++; + } } /*--------------------------------------------------------------------*/ @@ -477,9 +530,11 @@ static struct parspec parspec[] = { "default. ", "off", "bool" }, { "listen_address", tweak_listen_address, - "The network address/port where Varnish services requests.\n" + "Whitespace separated list of network endpoints where " + "Varnish will accept requests.\n" + "Possible formats: host, host:port, :port\n" MUST_RESTART, - "0.0.0.0:80" }, + ":80" }, { "listen_depth", tweak_listen_depth, "Listen(2) queue depth.\n" #if defined(__FreeBSD__) diff --git a/varnish-cache/bin/varnishd/varnishd.c b/varnish-cache/bin/varnishd/varnishd.c index 48c23ba1..db1b6ed2 100644 --- a/varnish-cache/bin/varnishd/varnishd.c +++ b/varnish-cache/bin/varnishd/varnishd.c @@ -410,8 +410,6 @@ main(int argc, char *argv[]) XXXAN(cli[0].sb); cli[0].result = CLIS_OK; - heritage.socket = -1; - /* * Set up a temporary param block until VSL_MgtInit() can * replace with shmem backed structure version. @@ -426,6 +424,7 @@ main(int argc, char *argv[]) * XXX: 'param' to static */ + TAILQ_INIT(&heritage.socks); memset(¶m, 0, sizeof param); params = ¶m; mgt_vcc_init(); -- 2.39.5