Commit 96c3aaf0 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Integrate Solaris patches, with a bit of polishing.

Don't look for umem on FreeBSD, which have dummy stub version for
dtrace or ZFS compatibility.

Generally restrict probes for Solaris specific stuff to when we
run on solaris, no need to make configure slower than it is.

Don't pretend we can get anywhere without poll(2) we use it for
lots of things:  Remove #if conditionals around poll-acceptor.

Sort a couple of lists, before they get too unsorted.

Submitted by:	Theo Schlossnagle



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@3113 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent c7a770b3
......@@ -9,8 +9,9 @@ dist_man_MANS = varnishd.1
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 \
......@@ -27,19 +28,19 @@ varnishd_SOURCES = \
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 \
......@@ -51,15 +52,16 @@ varnishd_SOURCES = \
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 \
......
......@@ -46,7 +46,6 @@
#include <sys/types.h>
#include <sys/socket.h>
#include "config.h"
#include "cli.h"
#include "cli_priv.h"
#include "shmlog.h"
......@@ -60,9 +59,10 @@ static struct acceptor *vca_acceptors[] = {
#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,
};
......
......@@ -48,8 +48,10 @@ extern struct acceptor acceptor_epoll;
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 */
......
......@@ -32,8 +32,6 @@
#include "config.h"
#if defined(HAVE_POLL)
#include <stdio.h>
#include <errno.h>
#include <string.h>
......@@ -167,5 +165,3 @@ struct acceptor acceptor_poll = {
.name = "poll",
.init = vca_poll_init,
};
#endif /* defined(HAVE_POLL) */
/*-
* 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) */
......@@ -52,6 +52,8 @@
#include <sys/socket.h>
#elif defined(__linux__)
#include <sys/sendfile.h>
#elif defined(__sun)
#include <sys/sendfile.h>
#else
#error Unknown sendfile() implementation
#endif
......@@ -191,6 +193,37 @@ WRK_Sendfile(struct worker *w, int fd, off_t off, unsigned len)
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
......
/*-
* 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 */
......@@ -38,6 +38,9 @@
#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>
......
......@@ -113,10 +113,16 @@ arg_ul(const char *p)
/*--------------------------------------------------------------------*/
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 }
};
......@@ -214,6 +220,9 @@ usage(void)
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>");
......
......@@ -129,6 +129,20 @@ case $host in
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])
;;
......@@ -191,23 +205,17 @@ else
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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment