]> err.no Git - varnish/commitdiff
Disentangle listener and connection, allowing the struct definitions to move
authordes <des@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Fri, 10 Feb 2006 16:05:32 +0000 (16:05 +0000)
committerdes <des@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Fri, 10 Feb 2006 16:05:32 +0000 (16:05 +0000)
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

15 files changed:
Makefile.am
configure.ac
connection.c
connection.h
listener.c
listener.h
log.c
log.h [new file with mode: 0644]
request.c
request.h
system-common.c [new file with mode: 0644]
system-linux-gnu.c [new file with mode: 0644]
system.h [new file with mode: 0644]
varnish.c
varnish.h

index 04d11a2faa598c4b6d646633841d3765dd68859d..e0b8891307fe8c974f522d9753a342dd6c58b189 100644 (file)
@@ -7,4 +7,6 @@ varnish_SOURCES = \
        listener.c \
        log.c \
        request.c \
+       system-common.c \
+       system-@target_os@.c \
        varnish.c
index ca8869dfce356873bc9a0154f7d6fc29d3f270a6..c551b1d6d3985766349bc696bb3656ec1142770a 100644 (file)
@@ -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])
index 4e226407a1eaa5c283c96493ff9605e547a69188..b7d88bdfb472b6301e77c1a9f21f9ca067a93fd3 100644 (file)
 #include <unistd.h>
 
 #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)
 {
index dfabe0b9761d85cd6dd08e5527f46bddac87c1a7..27ef13fb1e8d7c56147e38453e42934a2121a831 100644 (file)
@@ -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
index 9c3190031b29dd7cfcd1c8efb41e25235a1d6392..c284ae5d43a88ffbf61ddd1ff63bfa0023e89b05 100644 (file)
 #include <unistd.h>
 
 #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);
index 15d83ff759c212927d0b95a848c3766c42a51239..e3ba87192a147499f4aaf26a31c395e67b64bb20 100644 (file)
@@ -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 de52de15e561e742ca9773fb97e308d26c1edfb9..4d3207e4fe6ef483ce626d54a28db996d460f653 100644 (file)
--- a/log.c
+++ b/log.c
@@ -2,20 +2,41 @@
  * $Id$
  */
 
+#include <sys/types.h>
 #include <sys/signal.h>
+#include <sys/time.h>
 
 #include <errno.h>
 #include <signal.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <time.h>
+#endif
 #include <unistd.h>
 
 #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 (file)
index 0000000..2d09494
--- /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
index a8d17f67fcd9c7e4bf8f756e91cfa08218ec272e..dd88ddc1ecd3dbc04410ebee5f49722899972ee9 100644 (file)
--- a/request.c
+++ b/request.c
@@ -5,8 +5,14 @@
 #include <stdlib.h>
 
 #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)
 {
index 3fd94d853e71396076c906c6979c35df8d62a298..0f71cfc69bfb19a7d72e2a329f5e42d872903284 100644 (file)
--- 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 (file)
index 0000000..cb87d7c
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * $Id$
+ */
+
+#include <sys/types.h>
+
+#include <unistd.h>
+
+#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 (file)
index 0000000..67f8294
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * $Id$
+ */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#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 (file)
index 0000000..c94fdc8
--- /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
index 3484e3ebfc7bda79127bf6948ee91a83aea868d8..5a605e60b9703cc72ce93477b34acfe3b1fe4b7a 100644 (file)
--- a/varnish.c
+++ b/varnish.c
@@ -2,26 +2,67 @@
  * $Id$
  */
 
+#include <sys/wait.h>
+
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 
 #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);
 }
index 7d3d3c53726dbb4d78c596c6fdf9dc47e7e3c81f..90d87ab515be1d10e1182b96a44e7bd9b307f701 100644 (file)
--- 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