r4085 - trunk/varnish-cache/bin/varnishd
phk at projects.linpro.no
phk at projects.linpro.no
Wed May 20 12:46:02 CEST 2009
Author: phk
Date: 2009-05-20 12:46:01 +0200 (Wed, 20 May 2009)
New Revision: 4085
Modified:
trunk/varnish-cache/bin/varnishd/cache.h
trunk/varnish-cache/bin/varnishd/cache_waiter_epoll.c
Log:
Overhaul of the epoll waiter, kindly submitted by Rog?\195?\169rio Schneider.
Fixes: #492
Modified: trunk/varnish-cache/bin/varnishd/cache.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache.h 2009-05-19 18:21:36 UTC (rev 4084)
+++ trunk/varnish-cache/bin/varnishd/cache.h 2009-05-20 10:46:01 UTC (rev 4085)
@@ -48,6 +48,10 @@
#include <limits.h>
#include <unistd.h>
+#if defined(HAVE_EPOLL_CTL)
+#include <sys/epoll.h>
+#endif
+
#include "vqueue.h"
#include "vsb.h"
@@ -413,6 +417,10 @@
unsigned ihashptr;
unsigned lhashptr;
const char **hashptr;
+
+#if defined(HAVE_EPOLL_CTL)
+ struct epoll_event ev;
+#endif
};
Modified: trunk/varnish-cache/bin/varnishd/cache_waiter_epoll.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_waiter_epoll.c 2009-05-19 18:21:36 UTC (rev 4084)
+++ trunk/varnish-cache/bin/varnishd/cache_waiter_epoll.c 2009-05-20 10:46:01 UTC (rev 4085)
@@ -3,6 +3,8 @@
* Copyright (c) 2006-2009 Linpro AS
* All rights reserved.
*
+ * Author: Rogerio Carvalho Schneider <stockrt at gmail.com>
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -35,9 +37,14 @@
#if defined(HAVE_EPOLL_CTL)
+#ifndef EPOLLRDHUP
+# define EPOLLRDHUP 0
+#endif
+
#include <stdio.h>
+#include <string.h>
#include <errno.h>
-#include <string.h>
+#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
@@ -47,77 +54,141 @@
#include "cache.h"
#include "cache_waiter.h"
+#define NEEV 100
+
static pthread_t vca_epoll_thread;
+static pthread_t vca_epoll_timeout_thread;;
static int epfd = -1;
static VTAILQ_HEAD(,sess) sesshead = VTAILQ_HEAD_INITIALIZER(sesshead);
+int dotimer_pipe[2];
static void
-vca_add(int fd, void *data)
+vca_modadd(int fd, void *data, short arm)
{
- struct epoll_event ev = { EPOLLIN | EPOLLPRI, { data } };
- AZ(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev));
+
+ assert(fd >= 0);
+ if (data == vca_pipes || data == dotimer_pipe) {
+ struct epoll_event ev = {
+ EPOLLIN | EPOLLPRI | EPOLLET, { data }
+ };
+ AZ(epoll_ctl(epfd, arm, fd, &ev));
+ } else {
+ struct sess *sp = (struct sess *)data;
+ CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+ sp->ev.data.ptr = data;
+ sp->ev.events = EPOLLIN | EPOLLPRI | EPOLLONESHOT | EPOLLRDHUP;
+ AZ(epoll_ctl(epfd, arm, fd, &sp->ev));
+ }
}
static void
-vca_del(int fd)
+vca_cond_modadd(int fd, void *data)
{
- struct epoll_event ev = { 0, { 0 } };
- AZ(epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev));
+ struct sess *sp = (struct sess *)data;
+
+ assert(fd >= 0);
+ CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+ if (sp->ev.data.ptr)
+ AZ(epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &sp->ev));
+ else {
+ sp->ev.data.ptr = data;
+ sp->ev.events = EPOLLIN | EPOLLPRI | EPOLLONESHOT | EPOLLRDHUP;
+ AZ(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &sp->ev));
+ }
}
+static void
+vca_eev(const struct epoll_event *ep)
+{
+ struct sess *ss[NEEV], *sp;
+ int i, j;
+
+ AN(ep->data.ptr);
+ if (ep->data.ptr == vca_pipes) {
+ if (ep->events & EPOLLIN || ep->events & EPOLLPRI) {
+ j = 0;
+ i = read(vca_pipes[0], ss, sizeof ss);
+ if (i == -1 && errno == EAGAIN)
+ return;
+ while (i >= sizeof ss[0]) {
+ CHECK_OBJ_NOTNULL(ss[j], SESS_MAGIC);
+ assert(ss[j]->fd >= 0);
+ AZ(ss[j]->obj);
+ VTAILQ_INSERT_TAIL(&sesshead, ss[j], list);
+ vca_cond_modadd(ss[j]->fd, ss[j]);
+ j++;
+ i -= sizeof ss[0];
+ }
+ assert(i == 0);
+ }
+ } else {
+ CAST_OBJ_NOTNULL(sp, ep->data.ptr, SESS_MAGIC);
+ if (ep->events & EPOLLIN || ep->events & EPOLLPRI) {
+ i = HTC_Rx(sp->htc);
+ if (i == 0) {
+ vca_modadd(sp->fd, sp, EPOLL_CTL_MOD);
+ return; /* more needed */
+ }
+ VTAILQ_REMOVE(&sesshead, sp, list);
+ vca_handover(sp, i);
+ } else if (ep->events & EPOLLERR) {
+ VTAILQ_REMOVE(&sesshead, sp, list);
+ vca_close_session(sp, "ERR");
+ SES_Delete(sp);
+ } else if (ep->events & EPOLLHUP) {
+ VTAILQ_REMOVE(&sesshead, sp, list);
+ vca_close_session(sp, "HUP");
+ SES_Delete(sp);
+ } else if (ep->events & EPOLLRDHUP) {
+ VTAILQ_REMOVE(&sesshead, sp, list);
+ vca_close_session(sp, "RHUP");
+ SES_Delete(sp);
+ }
+ }
+}
+
+/*--------------------------------------------------------------------*/
+
static void *
vca_main(void *arg)
{
- struct epoll_event ev;
+ struct epoll_event ev[NEEV], *ep;
+ struct sess *sp;
double deadline;
- int dotimer = 0;
- double last_timeout = 0, tmp_timeout;
- struct sess *sp, *sp2;
- int i;
+ int dotimer, i, n;
THR_SetName("cache-epoll");
(void)arg;
- epfd = epoll_create(16);
+ epfd = epoll_create(1);
assert(epfd >= 0);
- vca_add(vca_pipes[0], vca_pipes);
+ vca_modadd(vca_pipes[0], vca_pipes, EPOLL_CTL_ADD);
+ vca_modadd(dotimer_pipe[0], dotimer_pipe, EPOLL_CTL_ADD);
while (1) {
- if ((dotimer = epoll_wait(epfd, &ev, 1, 100)) > 0) {
- if (ev.data.ptr == vca_pipes) {
- i = read(vca_pipes[0], &sp, sizeof sp);
- assert(i == sizeof sp);
- CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
- VTAILQ_INSERT_TAIL(&sesshead, sp, list);
- vca_add(sp->fd, sp);
- } else {
- CAST_OBJ_NOTNULL(sp, ev.data.ptr, SESS_MAGIC);
- i = HTC_Rx(sp->htc);
- if (i != 0) {
- VTAILQ_REMOVE(&sesshead, sp, list);
- vca_del(sp->fd);
- vca_handover(sp, i);
- }
- }
+ dotimer = 0;
+ n = epoll_wait(epfd, ev, NEEV, -1);
+ for (ep = ev, i = 0; i < n; i++, ep++) {
+ if (ep->data.ptr == dotimer_pipe &&
+ (ep->events == EPOLLIN || ep->events == EPOLLPRI))
+ dotimer = 1;
+ else
+ vca_eev(ep);
}
- tmp_timeout = TIM_mono();
- if ((tmp_timeout - last_timeout) > 60) {
- last_timeout = tmp_timeout;
- } else {
- if (dotimer > 0)
- continue;
- }
+ if (!dotimer)
+ continue;
/* check for timeouts */
deadline = TIM_real() - params->sess_timeout;
- VTAILQ_FOREACH_SAFE(sp, &sesshead, list, sp2) {
- CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+ for (;;) {
+ sp = VTAILQ_FIRST(&sesshead);
+ if (sp == NULL)
+ break;
if (sp->t_open > deadline)
- continue;
+ break;
VTAILQ_REMOVE(&sesshead, sp, list);
- vca_del(sp->fd);
vca_close_session(sp, "timeout");
SES_Delete(sp);
}
@@ -126,10 +197,45 @@
/*--------------------------------------------------------------------*/
+static void *
+vca_sess_timeout_ticker(void *arg)
+{
+ char ticker = 'R';
+ char junk;
+
+ THR_SetName("cache-epoll-sess_timeout_ticker");
+ (void)arg;
+
+ while (1) {
+ /* ticking */
+ assert(write(dotimer_pipe[1], &ticker, 1));
+ TIM_sleep(100 * 1e-3);
+ assert(read(dotimer_pipe[0], &junk, 1));
+ }
+}
+
+/*--------------------------------------------------------------------*/
+
static void
vca_epoll_init(void)
{
+ int i;
+ i = fcntl(vca_pipes[0], F_GETFL);
+ assert(i != -1);
+ i |= O_NONBLOCK;
+ i = fcntl(vca_pipes[0], F_SETFL, i);
+ assert(i != -1);
+
+ AZ(pipe(dotimer_pipe));
+ i = fcntl(dotimer_pipe[0], F_GETFL);
+ assert(i != -1);
+ i |= O_NONBLOCK;
+ i = fcntl(dotimer_pipe[0], F_SETFL, i);
+ assert(i != -1);
+
+ AZ(pthread_create(&vca_epoll_timeout_thread,
+ NULL, vca_sess_timeout_ticker, NULL));
AZ(pthread_create(&vca_epoll_thread, NULL, vca_main, NULL));
}
More information about the varnish-commit
mailing list