dovecot: Changed io_add_notify() API so that it can return "file...

dovecot at dovecot.org dovecot at dovecot.org
Mon Jul 9 07:04:58 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/772f4e8bd2a9
changeset: 5937:772f4e8bd2a9
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Jul 09 06:59:57 2007 +0300
description:
Changed io_add_notify() API so that it can return "file doesn't exist"
error.

diffstat:

5 files changed, 74 insertions(+), 39 deletions(-)
src/lib-storage/index/index-mailbox-check.c |    2 -
src/lib/ioloop-notify-dn.c                  |   38 +++++++++++++------------
src/lib/ioloop-notify-inotify.c             |   41 +++++++++++++++++++--------
src/lib/ioloop-notify-kqueue.c              |   11 +++----
src/lib/ioloop.h                            |   21 +++++++++++--

diffs (284 lines):

diff -r 2133c966701a -r 772f4e8bd2a9 src/lib-storage/index/index-mailbox-check.c
--- a/src/lib-storage/index/index-mailbox-check.c	Mon Jul 09 06:47:17 2007 +0300
+++ b/src/lib-storage/index/index-mailbox-check.c	Mon Jul 09 06:59:57 2007 +0300
@@ -73,7 +73,7 @@ void index_mailbox_check_add(struct inde
 	struct io *io = NULL;
 	struct index_notify_io *aio;
 
-	io = io_add_notify(path, notify_callback, ibox);
+	(void)io_add_notify(path, notify_callback, ibox, &io);
 	if (io != NULL) {
 		aio = i_new(struct index_notify_io, 1);
 		aio->io = io;
diff -r 2133c966701a -r 772f4e8bd2a9 src/lib/ioloop-notify-dn.c
--- a/src/lib/ioloop-notify-dn.c	Mon Jul 09 06:47:17 2007 +0300
+++ b/src/lib/ioloop-notify-dn.c	Mon Jul 09 06:59:57 2007 +0300
@@ -72,48 +72,51 @@ static void dnotify_input(struct ioloop 
 }
 
 #undef io_add_notify
-struct io *io_add_notify(const char *path, io_callback_t *callback,
-			 void *context)
+enum io_notify_result io_add_notify(const char *path, io_callback_t *callback,
+				    void *context, struct io **io_r)
 {
 	struct ioloop_notify_handler_context *ctx =
 		current_ioloop->notify_handler_context;
-	int fd;
+	int fd, ret;
+
+	*io_r = NULL;
 
 	if (ctx == NULL)
 		ctx = io_loop_notify_handler_init();
 	if (ctx->disabled)
-		return NULL;
+		return IO_NOTIFY_DISABLED;
 
 	fd = open(path, O_RDONLY);
 	if (fd == -1) {
-		i_error("open(%s) for dnotify failed: %m", path);
-		return NULL;
+		if (errno != ENOENT)
+			i_error("open(%s) for dnotify failed: %m", path);
+		return IO_NOTIFY_NOTFOUND;
 	}
 
 	if (fcntl(fd, F_SETSIG, SIGRTMIN) < 0) {
-		if (errno == EINVAL) {
-			/* not supported, disable dnotify */
-			ctx->disabled = TRUE;
-		} else {
+		/* EINVAL means there's no realtime signals and no dnotify */
+		if (errno != EINVAL)
 			i_error("fcntl(F_SETSIG) failed: %m");
-		}
+		ctx->disabled = TRUE;
 		(void)close(fd);
-		return NULL;
+		return IO_NOTIFY_DISABLED;
 	}
 	if (fcntl(fd, F_NOTIFY, DN_CREATE | DN_DELETE | DN_RENAME |
 		  DN_MULTISHOT) < 0) {
 		if (errno == ENOTDIR) {
 			/* we're trying to add dnotify to a non-directory fd.
 			   fail silently. */
-		} else if (errno == EINVAL) {
+			ret = IO_NOTIFY_NOTFOUND;
+		} else {
 			/* dnotify not in kernel. disable it. */
+			if (errno != EINVAL)
+				i_error("fcntl(F_NOTIFY) failed: %m");
 			ctx->disabled = TRUE;
-		} else {
-			i_error("fcntl(F_NOTIFY) failed: %m");
+			ret = IO_NOTIFY_DISABLED;
 		}
 		(void)fcntl(fd, F_SETSIG, 0);
 		(void)close(fd);
-		return NULL;
+		return ret;
 	}
 
 	if (ctx->event_io == NULL) {
@@ -121,7 +124,8 @@ struct io *io_add_notify(const char *pat
 				       dnotify_input, current_ioloop);
 	}
 
-	return io_notify_fd_add(&ctx->fd_ctx, fd, callback, context);
+	*io_r = io_notify_fd_add(&ctx->fd_ctx, fd, callback, context);
+	return IO_NOTIFY_ADDED;
 }
 
 void io_loop_notify_remove(struct ioloop *ioloop, struct io *_io)
diff -r 2133c966701a -r 772f4e8bd2a9 src/lib/ioloop-notify-inotify.c
--- a/src/lib/ioloop-notify-inotify.c	Mon Jul 09 06:47:17 2007 +0300
+++ b/src/lib/ioloop-notify-inotify.c	Mon Jul 09 06:59:57 2007 +0300
@@ -6,6 +6,7 @@
 #ifdef IOLOOP_NOTIFY_INOTIFY
 
 #include "fd-close-on-exec.h"
+#include "fd-set-nonblock.h"
 #include "ioloop-internal.h"
 #include "ioloop-notify-fd.h"
 #include "buffer.h"
@@ -62,12 +63,18 @@ static bool inotify_input_more(struct io
 		pos += sizeof(*event) + event->len;
 
 		io = io_notify_fd_find(&ctx->fd_ctx, event->wd);
-		if (io != NULL)
+		if (io != NULL) {
+			if ((event->mask & IN_IGNORED) != 0) {
+				/* calling inotify_rm_watch() would now give
+				   EINVAL */
+				io->fd = -1;
+			}
 			io->io.callback(io->io.context);
+		}
 	}
 	if (pos != ret)
 		i_error("read(inotify) returned partial event");
-	return TRUE;
+	return (size_t)ret >= sizeof(event_buf)-512;
 }
 
 static void inotify_input(struct ioloop *ioloop)
@@ -76,28 +83,33 @@ static void inotify_input(struct ioloop 
 }
 
 #undef io_add_notify
-struct io *io_add_notify(const char *path, io_callback_t *callback,
-			 void *context)
+enum io_notify_result io_add_notify(const char *path, io_callback_t *callback,
+				    void *context, struct io **io_r)
 {
 	struct ioloop_notify_handler_context *ctx =
 		current_ioloop->notify_handler_context;
-	int fd;
+	int wd;
+
+	*io_r = NULL;
 
 	if (ctx == NULL)
 		ctx = io_loop_notify_handler_init();
 	if (ctx->disabled)
-		return NULL;
+		return IO_NOTIFY_DISABLED;
 
-	fd = inotify_add_watch(ctx->inotify_fd, path,
+	wd = inotify_add_watch(ctx->inotify_fd, path,
 			       IN_CREATE | IN_DELETE | IN_MOVE |
 			       IN_CLOSE | IN_MODIFY);
-	if (fd < 0) {
+	if (wd < 0) {
+		if (errno == ENOENT)
+			return IO_NOTIFY_NOTFOUND;
+
 		/* ESTALE could happen with NFS. Don't bother giving an error
 		   message then. */
 		if (errno != ESTALE)
 			i_error("inotify_add_watch(%s) failed: %m", path);
 		ctx->disabled = TRUE;
-		return NULL;
+		return IO_NOTIFY_DISABLED;
 	}
 
 	if (ctx->event_io == NULL) {
@@ -105,7 +117,8 @@ struct io *io_add_notify(const char *pat
 				       inotify_input, current_ioloop);
 	}
 
-	return io_notify_fd_add(&ctx->fd_ctx, fd, callback, context);
+	*io_r = io_notify_fd_add(&ctx->fd_ctx, wd, callback, context);
+	return IO_NOTIFY_ADDED;
 }
 
 void io_loop_notify_remove(struct ioloop *ioloop, struct io *_io)
@@ -114,8 +127,10 @@ void io_loop_notify_remove(struct ioloop
 		ioloop->notify_handler_context;
 	struct io_notify *io = (struct io_notify *)_io;
 
-	if (inotify_rm_watch(ctx->inotify_fd, io->fd) < 0)
-		i_error("inotify_rm_watch() failed: %m");
+	if (io->fd != -1) {
+		if (inotify_rm_watch(ctx->inotify_fd, io->fd) < 0)
+			i_error("inotify_rm_watch() failed: %m");
+	}
 
 	io_notify_fd_free(&ctx->fd_ctx, io);
 
@@ -142,6 +157,7 @@ static struct ioloop_notify_handler_cont
 		ctx->disabled = TRUE;
 	} else {
 		fd_close_on_exec(ctx->inotify_fd, TRUE);
+		fd_set_nonblock(ctx->inotify_fd, TRUE);
 	}
 	return ctx;
 }
@@ -154,6 +170,7 @@ void io_loop_notify_handler_deinit(struc
 	if (ctx->inotify_fd != -1) {
 		if (close(ctx->inotify_fd) < 0)
 			i_error("close(inotify) failed: %m");
+		ctx->inotify_fd = -1;
 	}
 	i_free(ctx);
 }
diff -r 2133c966701a -r 772f4e8bd2a9 src/lib/ioloop-notify-kqueue.c
--- a/src/lib/ioloop-notify-kqueue.c	Mon Jul 09 06:47:17 2007 +0300
+++ b/src/lib/ioloop-notify-kqueue.c	Mon Jul 09 06:59:57 2007 +0300
@@ -105,8 +105,8 @@ void io_loop_notify_handler_deinit(struc
 }
 
 #undef io_add_notify
-struct io *io_add_notify(const char *path, io_callback_t *callback,
-			 void *context)
+enum io_notify_result io_add_notify(const char *path, io_callback_t *callback,
+				    void *context, struct io **io_r)
 {
 	struct ioloop_notify_handler_context *ctx =
 		current_ioloop->notify_handler_context;
@@ -121,7 +121,7 @@ struct io *io_add_notify(const char *pat
 	if (fd == -1) {
 		if (errno != ENOENT)
 			i_error("open(%s) for kq notify failed: %m", path);
-		return NULL;
+		return IO_NOTIFY_NOTFOUND;
 	}
 	fd_close_on_exec(fd, TRUE);
 
@@ -140,14 +140,15 @@ struct io *io_add_notify(const char *pat
 		i_error("kevent(%d, %s) for notify failed: %m", fd, path);
 		(void)close(fd);
 		i_free(io);
-		return NULL;
+		return IO_NOTIFY_DISABLED;
 	}
 
 	if (ctx->event_io == NULL) {
 		ctx->event_io = io_add(ctx->kq, IO_READ, event_callback,
 				       current_ioloop->notify_handler_context);
 	}
-	return &io->io;
+	*io_r = &io->io;
+	return IO_NOTIFY_ADDED;
 }
 
 void io_loop_notify_remove(struct ioloop *ioloop, struct io *_io)
diff -r 2133c966701a -r 772f4e8bd2a9 src/lib/ioloop.h
--- a/src/lib/ioloop.h	Mon Jul 09 06:47:17 2007 +0300
+++ b/src/lib/ioloop.h	Mon Jul 09 06:59:57 2007 +0300
@@ -17,6 +17,12 @@ enum io_condition {
 	
 	/* internal */
 	IO_NOTIFY	= 0x08
+};
+
+enum io_notify_result {
+	IO_NOTIFY_ADDED,
+	IO_NOTIFY_NOTFOUND,
+	IO_NOTIFY_DISABLED
 };
 
 typedef void io_callback_t(void *context);
@@ -40,10 +46,17 @@ struct io *io_add(int fd, enum io_condit
 #define io_add(fd, condition, callback, context) \
 	CONTEXT_CALLBACK(io_add, io_callback_t, \
 			 callback, context, fd, condition)
-struct io *io_add_notify(const char *path, io_callback_t *callback,
-			 void *context);
-#define io_add_notify(path, callback, context) \
-	CONTEXT_CALLBACK(io_add_notify, io_callback_t, callback, context, path)
+enum io_notify_result io_add_notify(const char *path, io_callback_t *callback,
+				    void *context, struct io **io_r);
+#ifdef CONTEXT_TYPE_SAFETY
+#  define io_add_notify(path, callback, context, io_r) \
+	({(void)(1 ? 0 : callback(context)); \
+	io_add_notify(path, (io_callback_t *)callback, context, io_r); })
+#else
+#  define io_add_notify(path, callback, context, io_r) \
+	io_add_notify(path, (io_callback_t *)callback, context, io_r)
+#endif
+
 /* Remove I/O handler, and set io pointer to NULL. */
 void io_remove(struct io **io);
 


More information about the dovecot-cvs mailing list