From: des Date: Fri, 10 Feb 2006 16:05:32 +0000 (+0000) Subject: Disentangle listener and connection, allowing the struct definitions to move X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f65dacbf3fef477fdce8f25427196100b275c856;p=varnish Disentangle listener and connection, allowing the struct definitions to move out of the headers into the code, reducing header dependencies. Add code to detect the number of CPU cores on Linux. Fork as many listening child processes as we have CPU cores. Add timestamps and the current PID to log messages. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@6 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/Makefile.am b/Makefile.am index 04d11a2f..e0b88913 100644 --- a/Makefile.am +++ b/Makefile.am @@ -7,4 +7,6 @@ varnish_SOURCES = \ listener.c \ log.c \ request.c \ + system-common.c \ + system-@target_os@.c \ varnish.c diff --git a/configure.ac b/configure.ac index ca8869df..c551b1d6 100644 --- a/configure.ac +++ b/configure.ac @@ -35,6 +35,8 @@ AC_PROG_MAKE_SET # Checks for header files. AC_HEADER_STDC +AC_HEADER_SYS_WAIT +AC_HEADER_TIME AC_CHECK_HEADERS([sys/socket.h]) AC_CHECK_HEADERS([netinet/in.h]) AC_CHECK_HEADERS([stddef.h]) diff --git a/connection.c b/connection.c index 4e226407..b7d88bdf 100644 --- a/connection.c +++ b/connection.c @@ -11,8 +11,66 @@ #include #include "varnish.h" +#include "log.h" #include "connection.h" +struct connection { + int sd; + struct sockaddr_storage addr; +}; + +/* + * Accepts a connection from the provided listening descriptor. Does not + * loop to handle EINTR or other similar conditions. + */ +connection_t * +connection_accept(int ld) +{ + connection_t *c; + socklen_t len; + + if ((c = calloc(1, sizeof *c)) == NULL) + return (NULL); + + len = sizeof c->addr; + if ((c->sd = accept(ld, (struct sockaddr *)&c->addr, &len)) == -1) { + free(c); + return (NULL); + } + switch (c->addr.ss_family) { +#if defined(AF_INET6) + case AF_INET6: { + struct sockaddr_in6 *addr = + (struct sockaddr_in6 *)&c->addr; + uint16_t *ip = (uint16_t *)&addr->sin6_addr; + + log_info("%s(): [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]:%u", + __func__, + ntohs(ip[0]), ntohs(ip[1]), + ntohs(ip[2]), ntohs(ip[3]), + ntohs(ip[4]), ntohs(ip[5]), + ntohs(ip[6]), ntohs(ip[7]), + ntohs(addr->sin6_port)); + break; + } +#endif + case AF_INET: { + struct sockaddr_in *addr = + (struct sockaddr_in *)&c->addr; + uint8_t *ip = (uint8_t *)&addr->sin_addr; + + log_info("%s(): %u.%u.%u.%u:%u", + __func__, + ip[0], ip[1], ip[2], ip[3], + ntohs(addr->sin_port)); + break; + } + default: + LOG_UNREACHABLE(); + } + return (c); +} + void connection_destroy(struct connection *c) { diff --git a/connection.h b/connection.h index dfabe0b9..27ef13fb 100644 --- a/connection.h +++ b/connection.h @@ -5,9 +5,9 @@ #ifndef CONNECTION_H_INCLUDED #define CONNECTION_H_INCLUDED -struct connection { - int sd; - struct sockaddr_storage addr; -}; +typedef struct connection connection_t; + +connection_t *connection_accept(int ld); +void connection_destroy(connection_t *c); #endif diff --git a/listener.c b/listener.c index 9c319003..c284ae5d 100644 --- a/listener.c +++ b/listener.c @@ -13,8 +13,14 @@ #include #include "varnish.h" -#include "listener.h" #include "connection.h" +#include "listener.h" +#include "log.h" + +struct listener { + int sd; + struct sockaddr_storage addr; +}; /* * Create a socket that listens on the specified port. We use an IPv6 TCP @@ -83,50 +89,14 @@ listener_destroy(struct listener *l) free(l); } -struct connection * +connection_t * listener_accept(struct listener *l) { - struct connection *c; - socklen_t len; + connection_t *c; - c = calloc(1, sizeof *c); for (;;) { - len = sizeof c->addr; - c->sd = accept(l->sd, (struct sockaddr *)&c->addr, &len); - if (c->sd != -1) { - switch (c->addr.ss_family) { -#if defined(AF_INET6) - case AF_INET6: { - struct sockaddr_in6 *addr = - (struct sockaddr_in6 *)&c->addr; - uint16_t *ip = (uint16_t *)&addr->sin6_addr; - - log_info("%s(): [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]:%u", - __func__, - ntohs(ip[0]), ntohs(ip[1]), - ntohs(ip[2]), ntohs(ip[3]), - ntohs(ip[4]), ntohs(ip[5]), - ntohs(ip[6]), ntohs(ip[7]), - ntohs(addr->sin6_port)); - break; - } -#endif - case AF_INET: { - struct sockaddr_in *addr = - (struct sockaddr_in *)&c->addr; - uint8_t *ip = (uint8_t *)&addr->sin_addr; - - log_info("%s(): %u.%u.%u.%u:%u", - __func__, - ip[0], ip[1], ip[2], ip[3], - ntohs(addr->sin_port)); - break; - } - default: - LOG_UNREACHABLE(); - } + if ((c = connection_accept(l->sd)) != NULL) return (c); - } if (errno != EINTR) { log_syserr("accept()"); free(c); diff --git a/listener.h b/listener.h index 15d83ff7..e3ba8719 100644 --- a/listener.h +++ b/listener.h @@ -5,9 +5,12 @@ #ifndef LISTENER_H_INCLUDED #define LISTENER_H_INCLUDED -struct listener { - int sd; - struct sockaddr_storage addr; -}; +#include "connection.h" + +typedef struct listener listener_t; + +listener_t *listener_create(int port); +void listener_destroy(listener_t *l); +connection_t *listener_accept(listener_t *l); #endif diff --git a/log.c b/log.c index de52de15..4d3207e4 100644 --- a/log.c +++ b/log.c @@ -2,20 +2,41 @@ * $Id$ */ +#include #include +#include #include #include #include #include #include +#ifdef TIME_WITH_SYS_TIME +#include +#endif #include #include "varnish.h" +#include "log.h" +#include "system.h" + +static void +timestamp(void) +{ + struct timeval now; + + if (gettimeofday(&now, NULL) == -1) + now.tv_sec = now.tv_usec = 0; + fprintf(stderr, "%lu.%06lu [%lu] ", + (unsigned long)now.tv_sec, + (unsigned long)now.tv_usec, + (unsigned long)sys.pid); +} static void emit(const char *fmt, va_list ap) { + timestamp(); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); } @@ -30,6 +51,7 @@ sysemit(const char *fmt, va_list ap) #else snprintf(errstr, sizeof errstr, "%s", strerror(errno)); #endif + timestamp(); vfprintf(stderr, fmt, ap); fprintf(stderr, ": %s\n", errstr); } diff --git a/log.h b/log.h new file mode 100644 index 00000000..2d09494b --- /dev/null +++ b/log.h @@ -0,0 +1,19 @@ +/* + * $Id$ + */ + +#ifndef LOG_H_INCLUDED +#define LOG_H_INCLUDED + + +void log_info(const char *fmt, ...); +void log_err(const char *fmt, ...); +void log_syserr(const char *fmt, ...); +void log_panic(const char *fmt, ...); +void log_syspanic(const char *fmt, ...); + +#define LOG_UNREACHABLE() \ + log_panic("%s(%d): %s(): unreachable code reached", \ + __FILE__, __LINE__, __func__) + +#endif diff --git a/request.c b/request.c index a8d17f67..dd88ddc1 100644 --- a/request.c +++ b/request.c @@ -5,8 +5,14 @@ #include #include "varnish.h" +#include "connection.h" +#include "log.h" #include "request.h" +struct request { + connection_t *conn; +}; + request_t * request_wait(connection_t *c, unsigned int timeout) { diff --git a/request.h b/request.h index 3fd94d85..0f71cfc6 100644 --- a/request.h +++ b/request.h @@ -5,8 +5,9 @@ #ifndef REQUEST_H_INCLUDED #define REQUEST_H_INCLUDED -struct request { - struct connection *conn; -}; +typedef struct request request_t; + +request_t *request_wait(connection_t *c, unsigned int timeout); +void request_destroy(request_t *r); #endif diff --git a/system-common.c b/system-common.c new file mode 100644 index 00000000..cb87d7c7 --- /dev/null +++ b/system-common.c @@ -0,0 +1,35 @@ +/* + * $Id$ + */ + +#include + +#include + +#include "varnish.h" +#include "system.h" + +system_t sys; + +/* + * gather system information at startup + */ +void +system_init(void) +{ + sys.pid = getpid(); + system_init_ncpu(); +} + +/* + * fork() wrapper, updates sys.pid + */ +pid_t +system_fork(void) +{ + pid_t pid; + + if ((pid = fork()) == 0) + sys.pid = getpid(); + return (pid); +} diff --git a/system-linux-gnu.c b/system-linux-gnu.c new file mode 100644 index 00000000..67f82946 --- /dev/null +++ b/system-linux-gnu.c @@ -0,0 +1,31 @@ +/* + * $Id$ + */ + +#include + +#include + +#include "varnish.h" +#include "log.h" +#include "system.h" + +void +system_init_ncpu(void) +{ + FILE *cpuinfo; + char line[256]; + int n; + + sys.ncpu = 0; + if ((cpuinfo = fopen("/proc/cpuinfo", "r")) == NULL) + return; + while (fgets(line, sizeof line, cpuinfo) != NULL) { + if (sscanf(line, "processor : %d", &n) == 1) + sys.ncpu++; + } + fclose(cpuinfo); + if (sys.ncpu == 0) + sys.ncpu = 1; + log_info("%d cpu(s)", sys.ncpu); +} diff --git a/system.h b/system.h new file mode 100644 index 00000000..c94fdc81 --- /dev/null +++ b/system.h @@ -0,0 +1,21 @@ +/* + * $Id$ + */ + +#ifndef SYSTEM_H_INCLUDED +#define SYSTEM_H_INCLUDED + +typedef struct system system_t; + +struct system { + int ncpu; + pid_t pid; +}; + +extern system_t sys; + +void system_init_ncpu(void); +void system_init(void); +pid_t system_fork(void); + +#endif diff --git a/varnish.c b/varnish.c index 3484e3eb..5a605e60 100644 --- a/varnish.c +++ b/varnish.c @@ -2,26 +2,67 @@ * $Id$ */ +#include + +#include #include #include #include #include "varnish.h" +#include "connection.h" +#include "listener.h" +#include "log.h" +#include "request.h" +#include "system.h" static void -varnish(void) +varnish_child(listener_t *l) { - listener_t *l; connection_t *c; request_t *r; - l = listener_create(8080); while ((c = listener_accept(l)) != NULL) { r = request_wait(c, 0); /* ... */ request_destroy(r); connection_destroy(c); } + LOG_UNREACHABLE(); +} + +static void +varnish(void) +{ + listener_t *l; + int i, status; + pid_t pid; + + system_init(); + log_info("starting Varnish"); + l = listener_create(8080); + for (i = 0; i < sys.ncpu; ++i) { + switch ((pid = system_fork())) { + case -1: + log_panic("fork()"); + break; + case 0: + varnish_child(l); + _exit(1); + break; + default: + log_info("forked child %lu", (unsigned long)pid); + break; + } + } + for (;;) { + if ((pid = wait(&status)) == -1) { + if (errno == ECHILD) + return; + } else { + log_info("child %lu exited", (unsigned long)pid); + } + } } static void @@ -50,6 +91,5 @@ main(int argc, char *argv[]) varnish(); - LOG_UNREACHABLE(); exit(1); } diff --git a/varnish.h b/varnish.h index 7d3d3c53..90d87ab5 100644 --- a/varnish.h +++ b/varnish.h @@ -7,32 +7,4 @@ #include "config.h" -/* opaque structures */ -typedef struct listener listener_t; -typedef struct connection connection_t; -typedef struct request request_t; - -/* connection.c */ -void connection_destroy(connection_t *c); - -/* listener.c */ -listener_t *listener_create(int port); -void listener_destroy(listener_t *l); -connection_t *listener_accept(listener_t *l); - -/* log.c */ -void log_info(const char *fmt, ...); -void log_err(const char *fmt, ...); -void log_syserr(const char *fmt, ...); -void log_panic(const char *fmt, ...); -void log_syspanic(const char *fmt, ...); - -#define LOG_UNREACHABLE() \ - log_panic("%s(%d): %s(): unreachable code reached", \ - __FILE__, __LINE__, __func__) - -/* request.c */ -request_t *request_wait(connection_t *c, unsigned int timeout); -void request_destroy(request_t *r); - #endif