[dovecot-cvs] dovecot/src/lib ioloop-notify-dn.c,NONE,1.1 ioloop-notify-none.c,NONE,1.1 Makefile.am,1.32,1.33 ioloop-internal.h,1.8,1.9 ioloop-poll.c,1.19,1.20 ioloop-select.c,1.14,1.15 ioloop.c,1.18,1.19 ioloop.h,1.10,1.11

cras at procontrol.fi cras at procontrol.fi
Sun Aug 24 16:43:55 EEST 2003


Update of /home/cvs/dovecot/src/lib
In directory danu:/tmp/cvs-serv29796/src/lib

Modified Files:
	Makefile.am ioloop-internal.h ioloop-poll.c ioloop-select.c 
	ioloop.c ioloop.h 
Added Files:
	ioloop-notify-dn.c ioloop-notify-none.c 
Log Message:
Added IO_DIR_NOTIFY and IO_FILE_NOTIFY conditions to io_add(). IO_DIR_NOTIFY
is now implemented for Linux dnotify.



--- NEW FILE: ioloop-notify-dn.c ---
/* Copyright (C) 2003 Timo Sirainen */

/* Logic is pretty much based on dnotify by Oskar Liljeblad. */

#define _GNU_SOURCE
#include "lib.h"

#ifdef IOLOOP_NOTIFY_DNOTIFY

#include "ioloop-internal.h"
#include "write-full.h"

#include <signal.h>
#include <unistd.h>
#include <fcntl.h>

static int event_pipe[2] = { -1, -1 };

static void sigrt_handler(int signo __attr_unused__, siginfo_t *si,
			  void *data __attr_unused__)
{
	if (write_full(event_pipe[1], &si->si_fd, sizeof(int)) < 0)
		i_fatal("write_full(event_pipe) failed: %m");
}

static void event_callback(void *context)
{
	struct ioloop *ioloop = context;
	struct io *io;
	int fd, ret;

	ret = read(event_pipe[0], &fd, sizeof(fd));
	if (ret < 0)
		i_fatal("read(event_pipe) failed: %m");
	if (ret != sizeof(fd))
		i_fatal("read(event_pipe) returned %d != %d", ret, sizeof(fd));

	if (gettimeofday(&ioloop_timeval, &ioloop_timezone) < 0)
		i_fatal("gettimeofday(): %m");
	ioloop_time = ioloop_timeval.tv_sec;

	for (io = ioloop->notifys; io != NULL; io = io->next) {
		if (io->fd == fd) {
			io->callback(io->context);
			break;
		}
	}
}

static int dn_init(void)
{
	struct sigaction act;

	if (pipe(event_pipe) < 0) {
		i_error("pipe() failed: %m");
		return FALSE;
	}

	act.sa_sigaction = sigrt_handler;
	sigemptyset(&act.sa_mask);
	act.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;

	if (sigaction(SIGRTMIN, &act, NULL) < 0) {
		i_error("sigaction(SIGRTMIN) failed: %m");
		close(event_pipe[0]);
		close(event_pipe[1]);
		return FALSE;
	}

	return TRUE;
}

struct io *io_loop_notify_add(struct ioloop *ioloop, int fd,
			      enum io_condition condition,
			      io_callback_t *callback, void *context)
{
	struct io *io;

	if ((condition & IO_FILE_NOTIFY) != 0)
		return NULL;

	if (event_pipe[0] == -1) {
		if (!dn_init())
			return NULL;
	}
	if (ioloop->event_io == NULL) {
		ioloop->event_io =
			io_add(event_pipe[0], IO_READ, event_callback, ioloop);
	}

	if (fcntl(fd, F_SETSIG, SIGRTMIN) < 0) {
		i_error("fcntl(F_SETSIG) failed: %m");
		return FALSE;
	}
	if (fcntl(fd, F_NOTIFY, DN_CREATE | DN_DELETE | DN_RENAME |
		  DN_MULTISHOT) < 0) {
		i_error("fcntl(F_NOTIFY) failed: %m");
		(void)fcntl(fd, F_SETSIG, 0);
		return FALSE;
	}

	io = p_new(ioloop->pool, struct io, 1);
	io->fd = fd;
        io->condition = condition;

	io->callback = callback;
        io->context = context;

	io->next = ioloop->notifys;
	ioloop->notifys = io;
	return io;
}

void io_loop_notify_remove(struct ioloop *ioloop, struct io *io)
{
	struct io **io_p;

	for (io_p = &ioloop->notifys; *io_p != NULL; io_p = &(*io_p)->next) {
		if (*io_p == io) {
			*io_p = io->next;
			break;
		}
	}

	if (fcntl(io->fd, F_SETSIG, 0) < 0)
		i_error("fcntl(F_SETSIG, 0) failed: %m");
	if (fcntl(io->fd, F_NOTIFY, 0) < 0)
		i_error("fcntl(F_NOTIFY, 0) failed: %m");

	p_free(ioloop->pool, io);

	if (ioloop->notifys == NULL) {
		io_remove(ioloop->event_io);
		ioloop->event_io = NULL;
	}
}

#endif

--- NEW FILE: ioloop-notify-none.c ---
/* Copyright (C) 2003 Timo Sirainen */

#include "lib.h"
#include "ioloop-internal.h"

#ifdef IOLOOP_NOTIFY_NONE

struct io *io_loop_notify_add(struct ioloop *ioloop __attr_unused__,
			      int fd __attr_unused__,
			      enum io_condition condition __attr_unused__,
			      io_callback_t *callback __attr_unused__,
			      void *context __attr_unused__)
{
	return FALSE;
}

void io_loop_notify_remove(struct ioloop *ioloop __attr_unused__,
			   struct io *io __attr_unused__)
{
}

#endif

Index: Makefile.am
===================================================================
RCS file: /home/cvs/dovecot/src/lib/Makefile.am,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- Makefile.am	6 Aug 2003 19:56:20 -0000	1.32
+++ Makefile.am	24 Aug 2003 12:43:53 -0000	1.33
@@ -25,6 +25,8 @@
 	istream-file.c \
 	istream-mmap.c \
 	ioloop.c \
+	ioloop-notify-none.c \
+	ioloop-notify-dn.c \
 	ioloop-poll.c \
 	ioloop-select.c \
 	lib.c \

Index: ioloop-internal.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib/ioloop-internal.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- ioloop-internal.h	23 May 2003 14:40:50 -0000	1.8
+++ ioloop-internal.h	24 Aug 2003 12:43:53 -0000	1.9
@@ -9,7 +9,8 @@
 	pool_t pool;
 	int highest_fd;
 
-	struct io *ios; /* sorted by priority */
+	struct io *ios;
+	struct io *notifys, *event_io;
 	struct timeout *timeouts; /* sorted by next_run */
 
         struct ioloop_handler_data *handler_data;
@@ -52,10 +53,17 @@
 void timeout_destroy(struct ioloop *ioloop, struct timeout **timeout_p);
 
 /* I/O handler calls */
-void io_loop_handle_add(struct ioloop *ioloop, int fd, int condition);
-void io_loop_handle_remove(struct ioloop *ioloop, int fd, int condition);
+void io_loop_handle_add(struct ioloop *ioloop, int fd,
+			enum io_condition condition);
+void io_loop_handle_remove(struct ioloop *ioloop, int fd,
+			   enum io_condition condition);
 
 void io_loop_handler_init(struct ioloop *ioloop);
 void io_loop_handler_deinit(struct ioloop *ioloop);
+
+struct io *io_loop_notify_add(struct ioloop *ioloop, int fd,
+			      enum io_condition condition,
+			      io_callback_t *callback, void *context);
+void io_loop_notify_remove(struct ioloop *ioloop, struct io *io);
 
 #endif

Index: ioloop-poll.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/ioloop-poll.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- ioloop-poll.c	26 May 2003 13:07:12 -0000	1.19
+++ ioloop-poll.c	24 Aug 2003 12:43:53 -0000	1.20
@@ -68,7 +68,8 @@
 #define IO_POLL_INPUT (POLLIN|POLLPRI|POLLERR|POLLHUP|POLLNVAL)
 #define IO_POLL_OUTPUT (POLLOUT|POLLERR|POLLHUP|POLLNVAL)
 
-void io_loop_handle_add(struct ioloop *ioloop, int fd, int condition)
+void io_loop_handle_add(struct ioloop *ioloop, int fd,
+			enum io_condition condition)
 {
 	struct ioloop_handler_data *data = ioloop->handler_data;
 	unsigned int old_size;
@@ -119,7 +120,8 @@
 		data->fds[index].events |= IO_POLL_OUTPUT;
 }
 
-void io_loop_handle_remove(struct ioloop *ioloop, int fd, int condition)
+void io_loop_handle_remove(struct ioloop *ioloop, int fd,
+			   enum io_condition condition)
 {
 	struct ioloop_handler_data *data = ioloop->handler_data;
 	int index;

Index: ioloop-select.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/ioloop-select.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- ioloop-select.c	16 Jun 2003 08:31:51 -0000	1.14
+++ ioloop-select.c	24 Aug 2003 12:43:53 -0000	1.15
@@ -53,7 +53,8 @@
         p_free(ioloop->pool, ioloop->handler_data);
 }
 
-void io_loop_handle_add(struct ioloop *ioloop, int fd, int condition)
+void io_loop_handle_add(struct ioloop *ioloop, int fd,
+			enum io_condition condition)
 {
 	i_assert(fd >= 0);
 
@@ -66,7 +67,8 @@
 		FD_SET(fd, &ioloop->handler_data->write_fds);
 }
 
-void io_loop_handle_remove(struct ioloop *ioloop, int fd, int condition)
+void io_loop_handle_remove(struct ioloop *ioloop, int fd,
+			   enum io_condition condition)
 {
 	i_assert(fd >= 0 && fd < FD_SETSIZE);
 
@@ -84,8 +86,8 @@
 {
 	struct timeval tv;
 	struct io *io, **io_p;
-        unsigned int t_id;
-	int ret, fd, condition;
+	unsigned int t_id;
+	int ret;
 
 	/* get the time left for next timeout task */
 	io_loop_get_wait_time(ioloop->timeouts, &tv, NULL);
@@ -117,10 +119,7 @@
 
 		i_assert(io->fd >= 0);
 
-		fd = io->fd;
-		condition = io->condition;
-
-		if (io_check_condition(fd, condition)) {
+		if (io_check_condition(io->fd, io->condition)) {
 			ret--;
 
 			t_id = t_push();

Index: ioloop.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/ioloop.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- ioloop.c	24 May 2003 15:16:47 -0000	1.18
+++ ioloop.c	24 Aug 2003 12:43:53 -0000	1.19
@@ -56,13 +56,19 @@
 	}
 }
 
-struct io *io_add(int fd, int condition, io_callback_t *callback, void *context)
+struct io *io_add(int fd, enum io_condition condition,
+		  io_callback_t *callback, void *context)
 {
 	struct io *io, **io_p;
 
 	i_assert(fd >= 0);
 	i_assert(callback != NULL);
 
+	if ((condition & IO_NOTIFY_MASK) != 0) {
+		return io_loop_notify_add(current_ioloop, fd, condition,
+					  callback, context);
+	}
+
 	io = p_new(current_ioloop->pool, struct io, 1);
 	io->fd = fd;
         io->condition = condition;
@@ -71,9 +77,9 @@
         io->context = context;
 
 	if (io->fd > current_ioloop->highest_fd)
-                current_ioloop->highest_fd = io->fd;
+		current_ioloop->highest_fd = io->fd;
 
-        io_loop_handle_add(current_ioloop, io->fd, io->condition);
+	io_loop_handle_add(current_ioloop, io->fd, io->condition);
 
 	/* have to append it, or io_destroy() breaks */
         io_p = &current_ioloop->ios;
@@ -87,14 +93,20 @@
 {
 	i_assert(io != NULL);
 	i_assert(io->fd >= 0);
+
+	if ((io->condition & IO_NOTIFY_MASK) != 0) {
+		io_loop_notify_remove(current_ioloop, io);
+		return;
+	}
+
 	i_assert(io->fd <= current_ioloop->highest_fd);
 
-        /* notify the real I/O handler */
+	/* notify the real I/O handler */
 	io_loop_handle_remove(current_ioloop, io->fd, io->condition);
 
-        /* check if we removed the highest fd */
+	/* check if we removed the highest fd */
 	if (io->fd == current_ioloop->highest_fd)
-                update_highest_fd(current_ioloop);
+		update_highest_fd(current_ioloop);
 
 	io->destroyed = TRUE;
 	io->fd = -1;

Index: ioloop.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib/ioloop.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- ioloop.h	23 May 2003 14:40:50 -0000	1.10
+++ ioloop.h	24 Aug 2003 12:43:53 -0000	1.11
@@ -4,13 +4,19 @@
 #include <sys/time.h>
 #include <time.h>
 
-#define IO_READ			(1 << 0)
-#define IO_WRITE		(1 << 1)
-
 struct io;
 struct timeout;
 struct ioloop;
 
+enum io_condition {
+	IO_READ		= 0x01,
+	IO_WRITE	= 0x02,
+	IO_DIR_NOTIFY	= 0x04,
+	IO_FILE_NOTIFY	= 0x08,
+
+	IO_NOTIFY_MASK	= IO_DIR_NOTIFY | IO_FILE_NOTIFY
+};
+
 typedef void io_callback_t(void *context);
 typedef void timeout_callback_t(void *context);
 
@@ -22,8 +28,12 @@
 
 /* I/O listeners - you can create different handlers for IO_READ and IO_WRITE,
    but make sure you don't create multiple handlers of same type, it's not
-   checked and removing one will stop the other from working as well. */
-struct io *io_add(int fd, int condition, io_callback_t *callback, void *context);
+   checked and removing one will stop the other from working as well.
+
+   If IO_DIR_NOTIFY or IO_FILE_NOTIFY isn't supported by operating system
+   directly, this function returns NULL. */
+struct io *io_add(int fd, enum io_condition condition,
+		  io_callback_t *callback, void *context);
 void io_remove(struct io *io);
 
 /* Timeout handlers */



More information about the dovecot-cvs mailing list