varnishd_SOURCES = \
cache_acceptor.c \
cache_acceptor_epoll.c \
- cache_acceptor_poll.c \
cache_acceptor_kqueue.c \
+ cache_acceptor_poll.c \
+ cache_acceptor_ports.c \
cache_backend.c \
cache_backend_cfg.c \
cache_backend_poll.c \
cache_httpconn.c \
cache_main.c \
cache_panic.c \
- cache_pool.c \
cache_pipe.c \
+ cache_pool.c \
cache_response.c \
cache_session.c \
cache_vary.c \
cache_vcl.c \
cache_vrt.c \
cache_vrt_acl.c \
- cache_vrt_re.c \
cache_vrt_esi.c \
+ cache_vrt_re.c \
cache_ws.c \
- hash_simple_list.c \
hash_classic.c \
+ hash_simple_list.c \
instance.c \
mgt_child.c \
mgt_cli.c \
storage_file.c \
storage_malloc.c \
storage_synth.c \
+ storage_umem.c \
tcp.c \
varnishd.c
noinst_HEADERS = \
acct_fields.h \
cache.h \
+ cache_acceptor.h \
cache_backend.h \
cache_backend_poll.h \
- cache_acceptor.h \
common.h \
default_vcl.h \
hash_slinger.h \
#include <sys/types.h>
#include <sys/socket.h>
-#include "config.h"
#include "cli.h"
#include "cli_priv.h"
#include "shmlog.h"
#if defined(HAVE_EPOLL_CTL)
&acceptor_epoll,
#endif
-#if defined(HAVE_POLL)
- &acceptor_poll,
+#if defined(HAVE_PORT_CREATE)
+ &acceptor_ports,
#endif
+ &acceptor_poll,
NULL,
};
extern struct acceptor acceptor_kqueue;
#endif
-#if defined(HAVE_POLL)
extern struct acceptor acceptor_poll;
+
+#if defined(HAVE_PORT_CREATE)
+extern struct acceptor acceptor_ports;
#endif
/* vca_acceptor.c */
#include "config.h"
-#if defined(HAVE_POLL)
-
#include <stdio.h>
#include <errno.h>
#include <string.h>
.name = "poll",
.init = vca_poll_init,
};
-
-#endif /* defined(HAVE_POLL) */
--- /dev/null
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006 Linpro AS
+ * Copyright (c) 2007 OmniTI Computer Consulting, Inc.
+ * Copyright (c) 2007 Theo Schlossnagle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id$
+ *
+ * XXX: We need to pass sessions back into the event engine when they are
+ * reused. Not sure what the most efficient way is for that. For now
+ * write the session pointer to a pipe which the event engine monitors.
+ */
+
+#include "config.h"
+#if defined(HAVE_PORT_CREATE)
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <port.h>
+
+#ifndef HAVE_CLOCK_GETTIME
+#include "compat/clock_gettime.h"
+#endif
+
+#include "shmlog.h"
+#include "cache.h"
+#include "cache_acceptor.h"
+
+#define MAX_EVENTS 256
+static pthread_t vca_ports_thread;
+int solaris_dport = -1;
+
+static VTAILQ_HEAD(,sess) sesshead = VTAILQ_HEAD_INITIALIZER(sesshead);
+
+static void
+vca_add(int fd, void *data)
+{
+ AZ(port_associate(solaris_dport, PORT_SOURCE_FD, fd, POLLIN | POLLERR | POLLPRI, data));
+}
+
+static void
+vca_del(int fd)
+{
+ port_dissociate(solaris_dport, PORT_SOURCE_FD, fd);
+}
+
+static void
+vca_port_ev(port_event_t *ev) {
+ struct sess *sp;
+ if(ev->portev_source == PORT_SOURCE_USER) {
+ sp = ev->portev_user;
+ CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+ assert(sp->fd >= 0);
+ AZ(sp->obj);
+ VTAILQ_INSERT_TAIL(&sesshead, sp, list);
+ vca_add(sp->fd, sp);
+ } else {
+ int i;
+ CAST_OBJ_NOTNULL(sp, ev->portev_user, SESS_MAGIC);
+ if(ev->portev_events & POLLERR) {
+ VTAILQ_REMOVE(&sesshead, sp, list);
+ vca_close_session(sp, "EOF");
+ SES_Delete(sp);
+ return;
+ }
+ i = HTC_Rx(sp->htc);
+ if (i == 0)
+ return;
+ if (i > 0) {
+ VTAILQ_REMOVE(&sesshead, sp, list);
+ if (sp->fd != -1)
+ vca_del(sp->fd);
+ vca_handover(sp, i);
+ }
+ }
+ return;
+}
+
+static void *
+vca_main(void *arg)
+{
+ struct sess *sp;
+
+ (void)arg;
+
+ solaris_dport = port_create();
+ assert(solaris_dport >= 0);
+
+ while (1) {
+ port_event_t ev[MAX_EVENTS];
+ int nevents, ei;
+ double deadline;
+ struct timespec ts;
+ ts.tv_sec = 0L;
+ ts.tv_nsec = 50L /*ms*/ * 1000L /*us*/ * 1000L /*ns*/;
+ nevents = 1;
+ if (port_getn(solaris_dport, ev, MAX_EVENTS, &nevents, &ts) == 0) {
+ for (ei=0; ei<nevents; ei++) {
+ vca_port_ev(ev + ei);
+ }
+ }
+ /* check for timeouts */
+ deadline = TIM_real() - params->sess_timeout;
+ for (;;) {
+ sp = VTAILQ_FIRST(&sesshead);
+ if (sp == NULL)
+ break;
+ if (sp->t_open > deadline)
+ break;
+ VTAILQ_REMOVE(&sesshead, sp, list);
+ if(sp->fd != -1)
+ vca_del(sp->fd);
+ vca_close_session(sp, "timeout");
+ SES_Delete(sp);
+ }
+ }
+}
+
+static void
+vca_ports_pass(struct sess *sp)
+{
+ int r;
+ while((r = port_send(solaris_dport, 0, sp)) == -1 &&
+ errno == EAGAIN);
+ AZ(r);
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+vca_ports_init(void)
+{
+
+ AZ(pthread_create(&vca_ports_thread, NULL, vca_main, NULL));
+}
+
+struct acceptor acceptor_ports = {
+ .name = "ports",
+ .init = vca_ports_init,
+ .pass = vca_ports_pass
+};
+
+#endif /* defined(HAVE_PORT_CREATE) */
#include <sys/socket.h>
#elif defined(__linux__)
#include <sys/sendfile.h>
+#elif defined(__sun)
+#include <sys/sendfile.h>
#else
#error Unknown sendfile() implementation
#endif
sendfile(*w->wfd, fd, &off, len) != len)
w->werr++;
} while (0);
+#elif defined(__sun)
+#ifdef HAVE_SENDFILEV
+ do {
+ sendfilevec_t svvec[HTTP_HDR_MAX * 2 + 1];
+ size_t xferred = 0, expected = 0;
+ int i;
+ for (i = 0; i < w->niov; i++) {
+ svvec[i].sfv_fd = SFV_FD_SELF;
+ svvec[i].sfv_flag = 0;
+ svvec[i].sfv_off = (off_t) w->iov[i].iov_base;
+ svvec[i].sfv_len = w->iov[i].iov_len;
+ expected += svvec[i].sfv_len;
+ }
+ svvec[i].sfv_fd = fd;
+ svvec[i].sfv_flag = 0;
+ svvec[i].sfv_off = off;
+ svvec[i].sfv_len = len;
+ expected += svvec[i].sfv_len;
+ if (sendfilev(*w->wfd, svvec, i, &xferred) == -1 ||
+ xferred != expected)
+ w->werr++;
+ w->liov = 0;
+ w->niov = 0;
+ } while (0);
+#else
+ do {
+ if (WRK_Flush(w) == 0 &&
+ sendfile(*w->wfd, fd, &off, len) != len)
+ w->werr++;
+ } while (0);
+#endif
#else
#error Unknown sendfile() implementation
#endif
--- /dev/null
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2008 Linpro AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: storage_umem.c 3036 2008-07-31 09:24:25Z phk $
+ *
+ * Storage method based on umem_alloc(3MALLOC)
+ */
+
+#include "config.h"
+
+#ifdef HAVE_UMEM_H
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#include <umem.h>
+
+#include "config.h"
+#include "shmlog.h"
+#include "cache.h"
+#include "stevedore.h"
+
+static size_t smu_max = SIZE_MAX;
+static MTX smu_mtx;
+
+struct smu {
+ struct storage s;
+ size_t sz;
+};
+
+static struct storage *
+smu_alloc(struct stevedore *st, size_t size)
+{
+ struct smu *smu;
+
+ LOCK(&smu_mtx);
+ VSL_stats->sma_nreq++;
+ if (VSL_stats->sma_nbytes + size > smu_max)
+ size = 0;
+ else {
+ VSL_stats->sma_nobj++;
+ VSL_stats->sma_nbytes += size;
+ VSL_stats->sma_balloc += size;
+ }
+ UNLOCK(&smu_mtx);
+
+ if (size == 0)
+ return (NULL);
+
+ smu = umem_zalloc(sizeof *smu, UMEM_DEFAULT);
+ if (smu == NULL)
+ return (NULL);
+ smu->sz = size;
+ smu->s.priv = smu;
+ smu->s.ptr = umem_alloc(size, UMEM_DEFAULT);
+ XXXAN(smu->s.ptr);
+ smu->s.len = 0;
+ smu->s.space = size;
+ smu->s.fd = -1;
+ smu->s.stevedore = st;
+ smu->s.magic = STORAGE_MAGIC;
+ return (&smu->s);
+}
+
+/*lint -e{818} not const-able */
+static void
+smu_free(struct storage *s)
+{
+ struct smu *smu;
+
+ CHECK_OBJ_NOTNULL(s, STORAGE_MAGIC);
+ smu = s->priv;
+ assert(smu->sz == smu->s.space);
+ LOCK(&smu_mtx);
+ VSL_stats->sma_nobj--;
+ VSL_stats->sma_nbytes -= smu->sz;
+ VSL_stats->sma_bfree += smu->sz;
+ UNLOCK(&smu_mtx);
+ umem_free(smu->s.ptr, smu->s.space);
+ umem_free(smu, sizeof *smu);
+}
+
+static void
+smu_trim(const struct storage *s, size_t size)
+{
+ struct smu *smu;
+ void *p;
+
+ CHECK_OBJ_NOTNULL(s, STORAGE_MAGIC);
+ smu = s->priv;
+ assert(smu->sz == smu->s.space);
+ if ((p = umem_alloc(size, UMEM_DEFAULT)) != NULL) {
+ memcpy(p, smu->s.ptr, size);
+ umem_free(smu->s.ptr, smu->s.space);
+ LOCK(&smu_mtx);
+ VSL_stats->sma_nbytes -= (smu->sz - size);
+ VSL_stats->sma_bfree += smu->sz - size;
+ smu->sz = size;
+ UNLOCK(&smu_mtx);
+ smu->s.ptr = p;
+ smu->s.space = size;
+ }
+}
+
+static void
+smu_init(struct stevedore *parent, int ac, char * const *av)
+{
+ const char *e;
+ uintmax_t u;
+
+ (void)parent;
+
+ AZ(av[ac]);
+ if (ac > 1)
+ ARGV_ERR("(-sumem) too many arguments\n");
+
+ if (ac == 0 || *av[0] == '\0')
+ return;
+
+ e = str2bytes(av[0], &u, 0);
+ if (e != NULL)
+ ARGV_ERR("(-sumem) size \"%s\": %s\n", av[0], e);
+ if ((u != (uintmax_t)(size_t)u))
+ ARGV_ERR("(-sumem) size \"%s\": too big\n", av[0]);
+ smu_max = u;
+}
+
+static void
+smu_open(const struct stevedore *st)
+{
+ (void)st;
+ AZ(pthread_mutex_init(&smu_mtx, NULL));
+}
+
+struct stevedore smu_stevedore = {
+ .magic = STEVEDORE_MAGIC,
+ .name = "umem",
+ .init = smu_init,
+ .open = smu_open,
+ .alloc = smu_alloc,
+ .free = smu_free,
+ .trim = smu_trim,
+};
+
+#endif /* HAVE_UMEM_H */
#include <errno.h>
#include <sys/ioctl.h>
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
#include <netdb.h>
#include <poll.h>
#include <stdio.h>
/*--------------------------------------------------------------------*/
extern struct stevedore sma_stevedore;
extern struct stevedore smf_stevedore;
+#ifdef HAVE_LIBUMEM
+extern struct stevedore smu_stevedore;
+#endif
static struct choice stv_choice[] = {
{ "file", &smf_stevedore },
{ "malloc", &sma_stevedore },
+#ifdef HAVE_LIBUMEM
+ { "umem", &smu_stevedore },
+#endif
{ NULL, NULL }
};
fprintf(stderr, FMT,
"-s kind[,storageoptions]", "Backend storage specification");
fprintf(stderr, FMT, "", " -s malloc");
+#ifdef HAVE_LIBUMEM
+ fprintf(stderr, FMT, "", " -s umem");
+#endif
fprintf(stderr, FMT, "", " -s file [default: use /tmp]");
fprintf(stderr, FMT, "", " -s file,<dir_or_file>");
fprintf(stderr, FMT, "", " -s file,<dir_or_file>,<size>");
AC_DEFINE([SENDFILE_WORKS], [1], [Define if SENDFILE works])
fi
;;
+*-*-solaris*)
+ AC_CHECK_HEADERS([sys/filio.h])
+ AC_CHECK_LIB(sendfile, sendfile)
+ AC_CHECK_LIB(umem, malloc)
+ AC_CHECK_HEADERS([umem.h])
+
+ if test "$ac_cv_lib_sendfile_sendfile" = yes; then
+ save_LIBS="${LIBS}"
+ LIBS="${NET_LIBS}"
+ AC_CHECK_FUNCS([sendfile])
+ AC_CHECK_FUNCS([sendfilev])
+ LIBS="${save_LIBS}"
+ fi
+ ;;
*)
AC_MSG_WARN([won't look for sendfile() on $host])
;;
ac_cv_func_epoll_ctl=no
fi
-# --enable-poll
-AC_ARG_ENABLE(poll,
- AS_HELP_STRING([--enable-poll],
- [use poll if available (default is YES)]),
+# --enable-ports
+AC_ARG_ENABLE(ports,
+ AS_HELP_STRING([--enable-ports],
+ [use ports if available (default is YES)]),
,
- [enable_poll=yes])
+ [enable_ports=yes])
-if test "$enable_poll" = yes; then
- AC_CHECK_FUNCS([poll])
+if test "$enable_ports" = yes; then
+ AC_CHECK_FUNCS([port_create])
else
- ac_cv_func_poll=no
-fi
-
-if test "$ac_cv_func_kqueue" != yes &&
- test "$ac_cv_func_epoll_ctl" != yes &&
- test "$ac_cv_func_poll" != yes; then
- AC_MSG_ERROR([no usable acceptor mechanism])
+ ac_cv_func_port_create=no
fi
# Solaris defines SO_{RCV,SND}TIMEO, but does not implement them.