r1280 - trunk/varnish-cache/bin/varnishd

phk at projects.linpro.no phk at projects.linpro.no
Thu Mar 8 11:09:18 CET 2007


Author: phk
Date: 2007-03-08 11:09:18 +0100 (Thu, 08 Mar 2007)
New Revision: 1280

Modified:
   trunk/varnish-cache/bin/varnishd/cache_acceptor.c
   trunk/varnish-cache/bin/varnishd/heritage.h
   trunk/varnish-cache/bin/varnishd/mgt_child.c
   trunk/varnish-cache/bin/varnishd/mgt_param.c
   trunk/varnish-cache/bin/varnishd/varnishd.c
Log:
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: <darryl.dixon at winterhouseconsulting.com>



Modified: trunk/varnish-cache/bin/varnishd/cache_acceptor.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_acceptor.c	2007-03-08 09:07:21 UTC (rev 1279)
+++ trunk/varnish-cache/bin/varnishd/cache_acceptor.c	2007-03-08 10:09:18 UTC (rev 1280)
@@ -35,6 +35,7 @@
 
 #include <stdio.h>
 #include <errno.h>
+#include <poll.h>
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -137,47 +138,65 @@
 	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);
+		}
 	}
 }
 

Modified: trunk/varnish-cache/bin/varnishd/heritage.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/heritage.h	2007-03-08 09:07:21 UTC (rev 1279)
+++ trunk/varnish-cache/bin/varnishd/heritage.h	2007-03-08 10:09:18 UTC (rev 1280)
@@ -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 @@
 
 	/* Listen address */
 	char			*listen_address;
-	char			*listen_host;
-	char			*listen_port;
 
 	/* Listen depth */
 	unsigned		listen_depth;

Modified: trunk/varnish-cache/bin/varnishd/mgt_child.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/mgt_child.c	2007-03-08 09:07:21 UTC (rev 1279)
+++ trunk/varnish-cache/bin/varnishd/mgt_child.c	2007-03-08 10:09:18 UTC (rev 1280)
@@ -122,7 +122,39 @@
 
 /*--------------------------------------------------------------------*/
 
+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)
 {
 	int i;
@@ -133,12 +165,8 @@
 	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 @@
 	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 @@
 	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)

Modified: trunk/varnish-cache/bin/varnishd/mgt_param.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/mgt_param.c	2007-03-08 09:07:21 UTC (rev 1279)
+++ trunk/varnish-cache/bin/varnishd/mgt_param.c	2007-03-08 10:09:18 UTC (rev 1280)
@@ -278,33 +278,86 @@
 /*--------------------------------------------------------------------*/
 
 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 @@
 		"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__)

Modified: trunk/varnish-cache/bin/varnishd/varnishd.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/varnishd.c	2007-03-08 09:07:21 UTC (rev 1279)
+++ trunk/varnish-cache/bin/varnishd/varnishd.c	2007-03-08 10:09:18 UTC (rev 1280)
@@ -410,8 +410,6 @@
 	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 @@
 	 * XXX:    'param' to static
 	 */
 
+	TAILQ_INIT(&heritage.socks);
 	memset(&param, 0, sizeof param);
 	params = &param;
 	mgt_vcc_init();




More information about the varnish-commit mailing list