r645 - trunk/varnish-cache/bin/varnishd
phk at projects.linpro.no
phk at projects.linpro.no
Sat Aug 5 10:19:41 CEST 2006
Author: phk
Date: 2006-08-05 10:19:41 +0200 (Sat, 05 Aug 2006)
New Revision: 645
Added:
trunk/varnish-cache/bin/varnishd/mgt_event.c
trunk/varnish-cache/bin/varnishd/mgt_event.h
Modified:
trunk/varnish-cache/bin/varnishd/Makefile.am
Log:
Add a miniature event engine based on poll(2).
It's general enough to find other uses, but right now it's only for
the manager process.
Modified: trunk/varnish-cache/bin/varnishd/Makefile.am
===================================================================
--- trunk/varnish-cache/bin/varnishd/Makefile.am 2006-08-05 01:17:47 UTC (rev 644)
+++ trunk/varnish-cache/bin/varnishd/Makefile.am 2006-08-05 08:19:41 UTC (rev 645)
@@ -13,6 +13,7 @@
heritage.h \
mgt.h \
mgt_cli.h \
+ mgt_event.h \
stevedore.h \
\
cache_acceptor.c \
@@ -39,6 +40,7 @@
hash_classic.c \
mgt_child.c \
mgt_cli.c \
+ mgt_event.c \
mgt_vcc.c \
rfc2616.c \
shmlog.c \
Added: trunk/varnish-cache/bin/varnishd/mgt_event.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/mgt_event.c 2006-08-05 01:17:47 UTC (rev 644)
+++ trunk/varnish-cache/bin/varnishd/mgt_event.c 2006-08-05 08:19:41 UTC (rev 645)
@@ -0,0 +1,290 @@
+/*
+ * $Id$
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <poll.h>
+#include <time.h>
+#include <stdlib.h>
+
+#include "mgt_event.h"
+#include "miniobj.h"
+#include "binary_heap.h"
+
+struct evbase {
+ unsigned magic;
+#define EVBASE_MAGIC 0x0cfd976f
+ TAILQ_HEAD(,ev) events;
+ struct pollfd *pfd;
+ unsigned npfd;
+ unsigned lpfd;
+ struct binheap *binheap;
+ unsigned char compact_pfd;
+ unsigned char disturbed;
+};
+
+/*--------------------------------------------------------------------*/
+
+static double
+ev_now(void)
+{
+ double t;
+ struct timespec ts;
+
+ assert(clock_gettime(CLOCK_MONOTONIC, &ts) == 0);
+ t = ts.tv_sec + ts.tv_nsec * 1e-9;
+ return (t);
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+ev_bh_update(void *priv, void *a, unsigned u)
+{
+ struct evbase *evb;
+ struct ev *e;
+
+ CAST_OBJ_NOTNULL(evb, priv, EVBASE_MAGIC);
+ CAST_OBJ_NOTNULL(e, a, EV_MAGIC);
+ e->__binheap_idx = u;
+}
+
+static int
+ev_bh_cmp(void *priv, void *a, void *b)
+{
+ struct evbase *evb;
+ struct ev *ea, *eb;
+
+ CAST_OBJ_NOTNULL(evb, priv, EVBASE_MAGIC);
+ CAST_OBJ_NOTNULL(ea, a, EV_MAGIC);
+ CAST_OBJ_NOTNULL(eb, b, EV_MAGIC);
+ return (ea->__when < eb->__when);
+}
+
+/*--------------------------------------------------------------------*/
+
+struct evbase *
+ev_new_base(void)
+{
+ struct evbase *evb;
+
+ evb = calloc(sizeof *evb, 1);
+ if (!evb)
+ return (evb);
+ evb->magic = EVBASE_MAGIC;
+ TAILQ_INIT(&evb->events);
+ evb->npfd = 1;
+ evb->pfd = calloc(sizeof *evb->pfd, evb->npfd);
+ if (evb->pfd == NULL) {
+ free(evb);
+ return (NULL);
+ }
+ evb->binheap = binheap_new(evb, ev_bh_cmp, ev_bh_update);
+ return (evb);
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+ev_destroy_base(struct evbase *evb)
+{
+ CHECK_OBJ_NOTNULL(evb, EVBASE_MAGIC);
+ evb->magic = 0;
+ free(evb);
+}
+
+/*--------------------------------------------------------------------*/
+
+static int
+ev_get_pfd(struct evbase *evb)
+{
+ unsigned u;
+ void *p;
+
+ if (evb->lpfd <= evb->npfd)
+ return (0);
+
+ if (evb->npfd > 256)
+ u = evb->npfd + 256;
+ else
+ u = evb->npfd * 2;
+ p = realloc(evb->pfd, sizeof *evb->pfd * u);
+ if (p == NULL)
+ return (1);
+ evb->npfd = u;
+ evb->pfd = p;
+ return (0);
+}
+
+/*--------------------------------------------------------------------*/
+
+int
+ev_add(struct evbase *evb, struct ev *e)
+{
+
+ CHECK_OBJ_NOTNULL(evb, EVBASE_MAGIC);
+ assert(e->magic != EV_MAGIC);
+ assert(e->callback != NULL);
+
+ if (e->timeout < 0.0)
+ return (EINVAL);
+
+ if (e->fd >= 0) {
+ if (ev_get_pfd(evb))
+ return (ENOMEM);
+ evb->pfd[evb->lpfd].fd = e->fd;
+ evb->pfd[evb->lpfd].events =
+ e->flags & (EV_RD|EV_WR|EV_ERR|EV_HUP);
+ e->__poll_idx = evb->lpfd;
+ evb->lpfd++;
+ }
+
+ if (e->timeout != 0.0) {
+ e->__when += ev_now() + e->timeout;
+ binheap_insert(evb->binheap, e);
+ } else {
+ e->__when = 0.0;
+ }
+
+ e->magic = EV_MAGIC;
+ e->__evb = evb;
+ e->__binheap_idx = 0;
+ e->__privflags = 0;
+ e->__poll_idx = -1;
+ if (e->fd < 0)
+ TAILQ_INSERT_TAIL(&evb->events, e, __list);
+ else
+ TAILQ_INSERT_HEAD(&evb->events, e, __list);
+
+ return (0);
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+ev_del(struct evbase *evb, struct ev *e)
+{
+ CHECK_OBJ_NOTNULL(evb, EVBASE_MAGIC);
+ CHECK_OBJ_NOTNULL(e, EV_MAGIC);
+ assert(evb == e->__evb);
+
+ if (e->__binheap_idx != 0)
+ binheap_delete(evb->binheap, e->__binheap_idx);
+ assert(e->__binheap_idx == 0);
+
+ if (e->fd >= 0) {
+ evb->pfd[e->__poll_idx].fd = -1;
+ evb->compact_pfd++;
+ e->fd = -1;
+ }
+
+ TAILQ_REMOVE(&evb->events, e, __list);
+
+ e->magic = 0;
+ e->__evb = NULL;
+
+ evb->disturbed = 1;
+}
+
+/*--------------------------------------------------------------------*/
+
+int
+ev_schedule(struct evbase *evb)
+{
+ int i;
+
+ CHECK_OBJ_NOTNULL(evb, EVBASE_MAGIC);
+ do
+ i = ev_schedule(evb);
+ while (i == 1);
+ return (i);
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+ev_compact_pfd(struct evbase *evb)
+{
+ /* XXX TBD */
+ evb->compact_pfd = 0;
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+ev_sched_timeout(struct evbase *evb, struct ev *e, double t)
+{
+ int i;
+
+ i = e->callback(e, 0);
+ if (i) {
+ ev_del(evb, e);
+ } else {
+ e->__when += t + e->timeout;
+ binheap_delete(evb->binheap, 0);
+ binheap_insert(evb->binheap, e);
+ }
+}
+
+int
+ev_schedule_one(struct evbase *evb)
+{
+ double t;
+ struct ev *e, *e2;
+ int i, j, tmo;
+ struct pollfd *pfd;
+
+ CHECK_OBJ_NOTNULL(evb, EVBASE_MAGIC);
+ e = binheap_root(evb->binheap);
+ if (e != NULL) {
+ CHECK_OBJ_NOTNULL(e, EV_MAGIC);
+ t = ev_now();
+ if (e->__when <= t) {
+ ev_sched_timeout(evb, e, t);
+ return (1);
+ }
+ tmo = (e->__when - t) * 1e3;
+ } else
+ tmo = INFTIM;
+
+ if (evb->compact_pfd)
+ ev_compact_pfd(evb);
+
+ if (tmo == INFTIM && evb->lpfd == 0)
+ return (0);
+ i = poll(evb->pfd, evb->lpfd, tmo);
+ if (i == 0) {
+ assert(e != NULL);
+ t = ev_now();
+ if (e->__when <= t)
+ ev_sched_timeout(evb, e, t);
+ return (1);
+ }
+ evb->disturbed = 0;
+ TAILQ_FOREACH_SAFE(e, &evb->events, __list, e2) {
+ if (i == 0)
+ break;
+ if (e->fd < 0)
+ continue;
+ assert(e->__poll_idx < evb->lpfd);
+ pfd = &evb->pfd[e->__poll_idx];
+ assert(pfd->fd == e->fd);
+ assert(pfd->events == e->flags);
+ if (!pfd->revents)
+ continue;
+ j = e->callback(e, pfd->revents);
+ i--;
+ if (evb->disturbed) {
+ TAILQ_FOREACH(e2, &evb->events, __list)
+ if (e2 == e)
+ break;
+ assert(e2 == e);
+ e2 = TAILQ_NEXT(e, __list);
+ evb->disturbed = 0;
+ }
+ if (j)
+ ev_del(evb, e);
+ }
+ return (1);
+}
Added: trunk/varnish-cache/bin/varnishd/mgt_event.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/mgt_event.h 2006-08-05 01:17:47 UTC (rev 644)
+++ trunk/varnish-cache/bin/varnishd/mgt_event.h 2006-08-05 08:19:41 UTC (rev 645)
@@ -0,0 +1,41 @@
+
+#include "queue.h"
+
+struct ev;
+struct evbase;
+
+typedef int ev_cb_f(struct ev *, unsigned what);
+
+struct ev {
+ unsigned magic;
+#define EV_MAGIC 0x15c8134b
+
+ /* pub */
+ int fd;
+ unsigned flags;
+#define EV_RD POLLIN
+#define EV_WR POLLOUT
+#define EV_ERR POLLERR
+#define EV_HUP POLLHUP
+ double timeout;
+ ev_cb_f *callback;
+ void *priv;
+
+ /* priv */
+ double __when;
+ TAILQ_ENTRY(ev) __list;
+ unsigned __binheap_idx;
+ unsigned __privflags;
+ struct evbase *__evb;
+ int __poll_idx;
+};
+
+struct evbase;
+
+struct evbase *ev_new_base(void);
+void ev_destroy_base(struct evbase *evb);
+int ev_add(struct evbase *evb, struct ev *e);
+void ev_del(struct evbase *evb, struct ev *e);
+
+int ev_schedule_one(struct evbase *evb);
+int ev_schedule(struct evbase *evb);
More information about the varnish-commit
mailing list