[Dovecot] Patch: More of kqueue() support.

Vaclav Haisman V.Haisman at sh.cvut.cz
Thu Dec 15 23:42:54 EET 2005


Hi,
the attached patch contains these changes:

2005-12-15 22:18  Vaclav Haisman <v.haisman at sh.cvut.cz>

 	* src/lib/ioloop-kqueue.c: Fix IO_ERROR behaviour.
 	* src/lib/ioloop-notify-kqueue.c: New file.
 	* configure.in: Improve kqueue detection and handling. Cleanup.

The configure.in changes that are not related to kqueue are there to make 
autoconf 2.59, automake 1.9.6 and libtool 1.5.20 are happy.

The directory change notification is not really well tested because Dovecot 
doesn't seem to use it that much.

As per Brad's request I have changed all occurrences of FreeBSD to just BSD.


Vaclav Haisman
-------------- next part --------------
Index: configure.in
===================================================================
RCS file: /home/cvs/dovecot/configure.in,v
retrieving revision 1.227
diff -u -p -d -r1.227 configure.in
--- configure.in	14 Dec 2005 21:34:01 -0000	1.227
+++ configure.in	15 Dec 2005 21:29:09 -0000
@@ -1,25 +1,24 @@
-AC_INIT(dovecot, 1.0.alpha5, [dovecot at dovecot.org])
+AC_PREREQ([2.59])
+AC_INIT([dovecot],[1.0.alpha5],[dovecot at dovecot.org])
 AC_CONFIG_SRCDIR([src])
 
-AC_CONFIG_HEADERS([config.h])
 AM_INIT_AUTOMAKE
 
 AM_MAINTAINER_MODE
 
 AC_ISC_POSIX
+AC_GNU_SOURCE
 AC_PROG_CC
 AC_PROG_CPP
 AC_HEADER_STDC
 AC_C_INLINE
-AM_PROG_LIBTOOL
+AC_PROG_LIBTOOL
 AM_ICONV
 
-AC_CHECK_HEADERS(strings.h stdint.h unistd.h dirent.h \
+AC_CHECK_HEADERS(strings.h stdint.h unistd.h dirent.h time.h \
   sys/uio.h sys/sysmacros.h sys/resource.h sys/select.h libgen.h \
-  sys/quota.h sys/fs/ufs_quota.h ufs/ufs/quota.h mntent.h sys/mnttab.h)
-
-# check posix headers
-AC_CHECK_HEADERS(sys/time.h)
+  sys/quota.h sys/fs/ufs_quota.h ufs/ufs/quota.h mntent.h sys/mnttab.h \
+  sys/event.h sys/time.h)
 
 AC_ARG_ENABLE(ipv6,
 [  --enable-ipv6           Enable IPv6 support (default)],
@@ -54,13 +53,14 @@ AC_ARG_WITH(mem-align,
 	mem_align=8)
 
 AC_ARG_WITH(ioloop,
-[  --with-ioloop=IOLOOP    Specify the I/O loop method to use],
+[  --with-ioloop=IOLOOP    Specify the I/O loop method to use
+                          (epoll, kqueue, poll; default is poll)],
 	ioloop=$withval,
 	ioloop=)
 
 AC_ARG_WITH(notify,
 [  --with-notify=IOLOOP    Specify the file system notification method to use
-                          (dnotify, inotify, none;
+                          (dnotify, inotify, kqueue, none;
                            default dnotify if compilable, otherwise none)],
 	notify=$withval,
 	notify=)
@@ -312,7 +312,7 @@ dnl * after -lsocket and -lnsl tests, in
 AC_CHECK_FUNCS(fcntl flock lockf inet_aton sigaction getpagesize madvise \
                strcasecmp stricmp vsnprintf vsyslog writev pread \
 	       setrlimit setproctitle seteuid setreuid setegid setresgid \
-	       strtoull strtouq setpriority quotactl getmntent)
+	       strtoull strtouq setpriority quotactl getmntent kqueue kevent)
 
 dnl * I/O loop function
 have_ioloop=no
@@ -329,12 +329,17 @@ if test "$ioloop" = "epoll"; then
 fi
 
 if test "$ioloop" = "kqueue"; then
-  AC_CHECK_FUNC(kqueue, [
-    AC_DEFINE(IOLOOP_KQUEUE,, [Implement I/O loop with FreeBSD kqueue()])
-    have_ioloop=yes
-  ], [
+  if test "$ac_cv_func_kqueue" != yes ; then
+    AC_MSG_WARN([kqueue ioloop requested but kqueue() is not available])
     ioloop=""
-  ])
+  elif test "$ac_cv_func_kevent" != yes ; then
+    AC_MSG_WARN([kqueue ioloop requested but kevent() is not available])
+    ioloop=""
+  else
+    AC_DEFINE(IOLOOP_KQUEUE,, [Implement I/O loop with BSD kqueue()])
+    ioloop=kqueue
+    have_ioloop=yes
+  fi
 fi
 
 if test "$ioloop" = "" || test "$ioloop" = "poll"; then
@@ -401,6 +406,19 @@ elif test "$notify" = "inotify"; then
   ], [
     AC_MSG_ERROR([inotify requested but not available, check for existence of <linux/inotify.h> and <linux/inotify-syscalls.h>])
   ])
+elif test "$notify" = "kqueue"; then
+  dnl * BSD kqueue() notify
+  if test "$ac_cv_func_kqueue" != yes ; then
+    AC_MSG_WARN([kqueue notify requested but kqueue() is not available])
+    notify=""
+  elif test "$ac_cv_func_kevent" != yes ; then
+    AC_MSG_WARN([kqueue notify requested but kevent() is not available])
+    notify=""
+  else
+    have_notify=kqueue
+    AC_DEFINE(IOLOOP_NOTIFY_KQUEUE,,
+      Use BSD kqueue directory changes notificaton)
+  fi
 else
   AC_MSG_ERROR([Unknown notify method: $notify])
 fi
@@ -1494,6 +1512,7 @@ AC_DEFINE_UNQUOTED(CAPABILITY_STRING, "$
 
 CFLAGS="$CFLAGS $EXTRA_CFLAGS"
 
+AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_FILES([
 Makefile
 doc/Makefile
Index: src/lib/ioloop-kqueue.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/ioloop-kqueue.c,v
retrieving revision 1.1
diff -u -p -d -r1.1 ioloop-kqueue.c
--- src/lib/ioloop-kqueue.c	14 Dec 2005 18:51:52 -0000	1.1
+++ src/lib/ioloop-kqueue.c	15 Dec 2005 21:29:09 -0000
@@ -1,5 +1,5 @@
 /*
- * FreeBSD kqueue() based ioloop handler.
+ * BSD kqueue() based ioloop handler.
  *
  * Copyright (c) 2005 Vaclav Haisman <v.haisman at sh.cvut.cz>
  *
@@ -16,6 +16,7 @@
 
 #ifdef IOLOOP_KQUEUE
 
+#include <unistd.h>
 #include <sys/types.h>
 #include <sys/event.h>
 #include <sys/time.h>
@@ -24,6 +25,8 @@
 #  define INITIAL_BUF_SIZE 128
 #endif
 
+#define MASK (IO_READ | IO_WRITE | IO_ERROR)
+
 struct ioloop_handler_context {
         int kq;
         size_t evbuf_size;
@@ -57,6 +60,7 @@ void io_loop_handler_init(struct ioloop 
 
 void io_loop_handler_deinit(struct ioloop *ioloop)
 {
+        close(ioloop->handler_context->kq);
         p_free(ioloop->pool, ioloop->handler_context->evbuf);
         p_free(ioloop->pool, ioloop->handler_context->fds);
         p_free(ioloop->pool, ioloop->handler_context);
@@ -66,8 +70,8 @@ void io_loop_handle_add(struct ioloop *i
 {
         struct ioloop_handler_context *ctx = ioloop->handler_context;
         const int fd = io->fd;
-        struct kevent ev = {fd, 0, EV_ADD | EV_CLEAR | EV_EOF, 0, 0, NULL};
-        enum io_condition condition = io->condition;
+        struct kevent ev = { fd, 0, EV_ADD | EV_EOF, 0, 0, NULL };
+        enum io_condition condition = io->condition & MASK;
 
         /* grow ctx->fds array if necessary */
         if ((size_t)fd >= ctx->fds_size) {
@@ -103,10 +107,10 @@ void io_loop_handle_add(struct ioloop *i
 void io_loop_handle_remove(struct ioloop *ioloop, struct io *io)
 {
         struct ioloop_handler_context *ctx = ioloop->handler_context;
+        const int fd = io->fd;
         struct kevent ev = { fd, 0, EV_DELETE, 0, 0, NULL };
         struct fdrecord *const fds = ctx->fds;
-        const int fd = io->fd;
-        const enum io_condition condition = io->condition;
+        const enum io_condition condition = io->condition & MASK;
 
         i_assert((size_t)fd < ctx->fds_size);
         i_assert(fds[fd].mode != 0);
@@ -160,7 +164,8 @@ void io_loop_handler_run(struct ioloop *
                 struct io *io = ctx->evbuf[i].udata;
 
                 i_assert(ctx->evbuf[i].ident < ctx->fds_size);
-                if (ctx->fds[ctx->evbuf[i].ident].mode & IO_ERROR) {
+                if ((ctx->fds[ctx->evbuf[i].ident].mode & IO_ERROR)
+                    && (ctx->evbuf[i].flags & EV_EOF)) {
                         struct io *errio = ctx->fds[ctx->evbuf[i].ident].errio;
 
                         t_id = t_push();
@@ -171,8 +176,8 @@ void io_loop_handler_run(struct ioloop *
 					(void *)errio->callback);
 			}
                 }
-
-                if (ctx->fds[ctx->evbuf[i].ident].mode & (IO_WRITE | IO_READ)) {
+                else if (ctx->fds[ctx->evbuf[i].ident].mode
+                         & (IO_WRITE | IO_READ)) {
                         t_id = t_push();
                         io->callback(io->context);
 			if (t_pop() != t_id) {
@@ -181,6 +186,8 @@ void io_loop_handler_run(struct ioloop *
 					(void *)io->callback);
 			}
                 }
+                else
+                        i_panic("Unrecognized event");
         }
 }
 
Index: src/lib/Makefile.am
===================================================================
RCS file: /home/cvs/dovecot/src/lib/Makefile.am,v
retrieving revision 1.56
diff -u -p -d -r1.56 Makefile.am
--- src/lib/Makefile.am	14 Dec 2005 18:51:52 -0000	1.56
+++ src/lib/Makefile.am	15 Dec 2005 21:29:09 -0000
@@ -32,6 +32,7 @@ liblib_a_SOURCES = \
 	ioloop-notify-none.c \
 	ioloop-notify-dn.c \
 	ioloop-notify-inotify.c \
+	ioloop-notify-kqueue.c \
 	ioloop-poll.c \
 	ioloop-select.c \
 	ioloop-epoll.c \
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ioloop-notify-kqueue.c
Type: text/x-csrc
Size: 3416 bytes
Desc: The new file
Url : http://dovecot.org/pipermail/dovecot/attachments/20051215/b0a8fb4d/ioloop-notify-kqueue.c


More information about the dovecot mailing list