[dovecot-cvs] dovecot/src/lib Makefile.am, 1.69, 1.70 ioloop-epoll.c, 1.20, 1.21 ioloop-internal.h, 1.18, 1.19 ioloop-iolist.c, 1.2, 1.3 ioloop-iolist.h, 1.2, 1.3 ioloop-kqueue.c, 1.15, 1.16 ioloop-notify-dn.c, 1.18, 1.19 ioloop-notify-fd.c, NONE, 1.1 ioloop-notify-fd.h, NONE, 1.1 ioloop-notify-inotify.c, 1.12, 1.13 ioloop-notify-kqueue.c, 1.8, 1.9 ioloop-poll.c, 1.34, 1.35 ioloop-select.c, 1.24, 1.25 ioloop.c, 1.43, 1.44 ioloop.h, 1.20, 1.21
tss at dovecot.org
tss at dovecot.org
Fri Mar 9 00:04:24 EET 2007
Update of /var/lib/cvs/dovecot/src/lib
In directory talvi:/tmp/cvs-serv6162
Modified Files:
Makefile.am ioloop-epoll.c ioloop-internal.h ioloop-iolist.c
ioloop-iolist.h ioloop-kqueue.c ioloop-notify-dn.c
ioloop-notify-inotify.c ioloop-notify-kqueue.c ioloop-poll.c
ioloop-select.c ioloop.c ioloop.h
Added Files:
ioloop-notify-fd.c ioloop-notify-fd.h
Log Message:
Various cleanups to ioloop code.
Index: Makefile.am
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/Makefile.am,v
retrieving revision 1.69
retrieving revision 1.70
diff -u -d -r1.69 -r1.70
--- Makefile.am 22 Feb 2007 21:50:49 -0000 1.69
+++ Makefile.am 8 Mar 2007 22:04:21 -0000 1.70
@@ -37,6 +37,7 @@
ioloop.c \
ioloop-iolist.c \
ioloop-notify-none.c \
+ ioloop-notify-fd.c \
ioloop-notify-dn.c \
ioloop-notify-inotify.c \
ioloop-notify-kqueue.c \
@@ -124,6 +125,7 @@
ioloop.h \
ioloop-iolist.h \
ioloop-internal.h \
+ ioloop-notify-fd.h \
lib.h \
lib-signals.h \
macros.h \
Index: ioloop-epoll.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/ioloop-epoll.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- ioloop-epoll.c 3 Dec 2006 14:27:57 -0000 1.20
+++ ioloop-epoll.c 8 Mar 2007 22:04:21 -0000 1.21
@@ -29,11 +29,10 @@
{
struct ioloop_handler_context *ctx;
- ioloop->handler_context = ctx =
- p_new(ioloop->pool, struct ioloop_handler_context, 1);
+ ioloop->handler_context = ctx = i_new(struct ioloop_handler_context, 1);
- p_array_init(&ctx->events, ioloop->pool, IOLOOP_INITIAL_FD_COUNT);
- p_array_init(&ctx->fd_index, ioloop->pool, IOLOOP_INITIAL_FD_COUNT);
+ i_array_init(&ctx->events, IOLOOP_INITIAL_FD_COUNT);
+ i_array_init(&ctx->fd_index, IOLOOP_INITIAL_FD_COUNT);
ctx->epfd = epoll_create(IOLOOP_INITIAL_FD_COUNT);
if (ctx->epfd < 0)
@@ -49,13 +48,13 @@
list = array_get_modifiable(&ctx->fd_index, &count);
for (i = 0; i < count; i++)
- p_free(ioloop->pool, list[i]);
+ i_free(list[i]);
if (close(ctx->epfd) < 0)
i_error("close(epoll) failed: %m");
array_free(&ioloop->handler_context->fd_index);
array_free(&ioloop->handler_context->events);
- p_free(ioloop->pool, ioloop->handler_context);
+ i_free(ioloop->handler_context);
}
#define IO_EPOLL_ERROR (EPOLLERR | EPOLLHUP)
@@ -65,7 +64,7 @@
static int epoll_event_mask(struct io_list *list)
{
int events = 0, i;
- struct io *io;
+ struct io_file *io;
for (i = 0; i < IOLOOP_IOLIST_IOS_PER_FD; i++) {
io = list->ios[i];
@@ -73,18 +72,18 @@
if (io == NULL)
continue;
- if (io->condition & IO_READ)
+ if (io->io.condition & IO_READ)
events |= IO_EPOLL_INPUT;
- if (io->condition & IO_WRITE)
+ if (io->io.condition & IO_WRITE)
events |= IO_EPOLL_OUTPUT;
- if (io->condition & IO_ERROR)
+ if (io->io.condition & IO_ERROR)
events |= IO_EPOLL_ERROR;
}
return events;
}
-void io_loop_handle_add(struct ioloop *ioloop, struct io *io)
+void io_loop_handle_add(struct ioloop *ioloop, struct io_file *io)
{
struct ioloop_handler_context *ctx = ioloop->handler_context;
struct io_list **list;
@@ -94,7 +93,7 @@
list = array_idx_modifiable(&ctx->fd_index, io->fd);
if (*list == NULL)
- *list = p_new(ioloop->pool, struct io_list, 1);
+ *list = i_new(struct io_list, 1);
first = ioloop_iolist_add(*list, io);
@@ -119,7 +118,7 @@
}
}
-void io_loop_handle_remove(struct ioloop *ioloop, struct io *io)
+void io_loop_handle_remove(struct ioloop *ioloop, struct io_file *io)
{
struct ioloop_handler_context *ctx = ioloop->handler_context;
struct io_list **list;
@@ -147,6 +146,7 @@
insteading of appending to the events array */
ctx->deleted_count++;
}
+ i_free(io);
}
void io_loop_handler_run(struct ioloop *ioloop)
@@ -155,7 +155,7 @@
struct epoll_event *events;
const struct epoll_event *event;
struct io_list *list;
- struct io *io;
+ struct io_file *io;
struct timeval tv;
unsigned int events_count, t_id;
int msecs, ret, i, j;
@@ -189,20 +189,20 @@
call = FALSE;
if ((event->events & (EPOLLHUP | EPOLLERR)) != 0)
call = TRUE;
- else if ((io->condition & IO_READ) != 0)
+ else if ((io->io.condition & IO_READ) != 0)
call = (event->events & EPOLLIN) != 0;
- else if ((io->condition & IO_WRITE) != 0)
+ else if ((io->io.condition & IO_WRITE) != 0)
call = (event->events & EPOLLOUT) != 0;
- else if ((io->condition & IO_ERROR) != 0)
+ else if ((io->io.condition & IO_ERROR) != 0)
call = (event->events & IO_EPOLL_ERROR) != 0;
if (call) {
t_id = t_push();
- io->callback(io->context);
+ io->io.callback(io->io.context);
if (t_pop() != t_id) {
i_panic("Leaked a t_pop() call in "
"I/O handler %p",
- (void *)io->callback);
+ (void *)io->io.callback);
}
}
}
Index: ioloop-internal.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/ioloop-internal.h,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- ioloop-internal.h 17 Aug 2006 18:46:42 -0000 1.18
+++ ioloop-internal.h 8 Mar 2007 22:04:21 -0000 1.19
@@ -10,11 +10,8 @@
struct ioloop {
struct ioloop *prev;
- pool_t pool;
-
- struct io *ios;
- struct io *notifys;
- struct io *next_io;
+ struct io_file *io_files;
+ struct io_file *next_io_file;
struct timeout *timeouts; /* sorted by next_run */
struct ioloop_handler_context *handler_context;
@@ -24,18 +21,22 @@
};
struct io {
- /* use a doubly linked list so that io_remove() is quick */
- struct io *prev, *next;
-
- int refcount;
-
- int fd;
enum io_condition condition;
io_callback_t *callback;
void *context;
};
+struct io_file {
+ struct io io;
+
+ /* use a doubly linked list so that io_remove() is quick */
+ struct io_file *prev, *next;
+
+ int refcount;
+ int fd;
+};
+
struct timeout {
struct timeout *next;
@@ -53,21 +54,14 @@
struct timeval *tv_now);
void io_loop_handle_timeouts(struct ioloop *ioloop);
-/* call only when timeout->destroyed is TRUE */
-void timeout_destroy(struct ioloop *ioloop, struct timeout **timeout_p);
-
/* I/O handler calls */
-void io_loop_handle_add(struct ioloop *ioloop, struct io *io);
-void io_loop_handle_remove(struct ioloop *ioloop, struct io *io);
+void io_loop_handle_add(struct ioloop *ioloop, struct io_file *io);
+void io_loop_handle_remove(struct ioloop *ioloop, struct io_file *io);
void io_loop_handler_init(struct ioloop *ioloop);
void io_loop_handler_deinit(struct ioloop *ioloop);
-void io_loop_notify_handler_init(struct ioloop *ioloop);
-void io_loop_notify_handler_deinit(struct ioloop *ioloop);
-
-struct io *io_loop_notify_add(struct ioloop *ioloop, const char *path,
- io_callback_t *callback, void *context);
void io_loop_notify_remove(struct ioloop *ioloop, struct io *io);
+void io_loop_notify_handler_deinit(struct ioloop *ioloop);
#endif
Index: ioloop-iolist.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/ioloop-iolist.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- ioloop-iolist.c 16 Aug 2006 15:54:58 -0000 1.2
+++ ioloop-iolist.c 8 Mar 2007 22:04:21 -0000 1.3
@@ -8,15 +8,15 @@
#include "ioloop-internal.h"
#include "ioloop-iolist.h"
-bool ioloop_iolist_add(struct io_list *list, struct io *io)
+bool ioloop_iolist_add(struct io_list *list, struct io_file *io)
{
int i, idx;
- if ((io->condition & IO_READ) != 0)
+ if ((io->io.condition & IO_READ) != 0)
idx = IOLOOP_IOLIST_INPUT;
- else if ((io->condition & IO_WRITE) != 0)
+ else if ((io->io.condition & IO_WRITE) != 0)
idx = IOLOOP_IOLIST_OUTPUT;
- else if ((io->condition & IO_ERROR) != 0)
+ else if ((io->io.condition & IO_ERROR) != 0)
idx = IOLOOP_IOLIST_ERROR;
else {
i_unreached();
@@ -34,7 +34,7 @@
return TRUE;
}
-bool ioloop_iolist_del(struct io_list *list, struct io *io)
+bool ioloop_iolist_del(struct io_list *list, struct io_file *io)
{
bool last = TRUE;
int i;
Index: ioloop-iolist.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/ioloop-iolist.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- ioloop-iolist.h 16 Aug 2006 15:54:58 -0000 1.2
+++ ioloop-iolist.h 8 Mar 2007 22:04:21 -0000 1.3
@@ -10,10 +10,10 @@
};
struct io_list {
- struct io *ios[IOLOOP_IOLIST_IOS_PER_FD];
+ struct io_file *ios[IOLOOP_IOLIST_IOS_PER_FD];
};
-bool ioloop_iolist_add(struct io_list *list, struct io *io);
-bool ioloop_iolist_del(struct io_list *list, struct io *io);
+bool ioloop_iolist_add(struct io_list *list, struct io_file *io);
+bool ioloop_iolist_del(struct io_list *list, struct io_file *io);
#endif
Index: ioloop-kqueue.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/ioloop-kqueue.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- ioloop-kqueue.c 3 Dec 2006 14:27:57 -0000 1.15
+++ ioloop-kqueue.c 8 Mar 2007 22:04:21 -0000 1.16
@@ -37,22 +37,20 @@
int kq;
unsigned int deleted_count;
- array_t ARRAY_DEFINE(events, struct kevent);
+ ARRAY_DEFINE(events, struct kevent);
};
void io_loop_handler_init(struct ioloop *ioloop)
{
struct ioloop_handler_context *ctx;
- ioloop->handler_context = ctx =
- p_new(ioloop->pool, struct ioloop_handler_context, 1);
-
+ ioloop->handler_context = ctx = i_new(struct ioloop_handler_context, 1);
ctx->kq = kqueue();
if (ctx->kq < 0)
i_fatal("kqueue() in io_loop_handler_init() failed: %m");
fd_close_on_exec(ctx->kq, TRUE);
- p_array_init(&ctx->events, ioloop->pool, IOLOOP_INITIAL_FD_COUNT);
+ i_array_init(&ctx->events, IOLOOP_INITIAL_FD_COUNT);
}
void io_loop_handler_deinit(struct ioloop *ioloop)
@@ -60,20 +58,20 @@
if (close(ioloop->handler_context->kq) < 0)
i_error("close(kqueue) in io_loop_handler_deinit() failed: %m");
array_free(&ioloop->handler_context->events);
- p_free(ioloop->pool, ioloop->handler_context);
+ i_free(ioloop->handler_context);
}
-void io_loop_handle_add(struct ioloop *ioloop, struct io *io)
+void io_loop_handle_add(struct ioloop *ioloop, struct io_file *io)
{
struct ioloop_handler_context *ctx = ioloop->handler_context;
struct kevent ev;
- if ((io->condition & (IO_READ | IO_ERROR)) != 0) {
+ if ((io->io.condition & (IO_READ | IO_ERROR)) != 0) {
MY_EV_SET(&ev, io->fd, EVFILT_READ, EV_ADD, 0, 0, io);
if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0)
i_fatal("kevent(EV_ADD, %d) failed: %m", io->fd);
}
- if ((io->condition & IO_WRITE) != 0) {
+ if ((io->io.condition & IO_WRITE) != 0) {
MY_EV_SET(&ev, io->fd, EVFILT_WRITE, EV_ADD, 0, 0, io);
if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0)
i_fatal("kevent(EV_ADD, %d) failed: %m", io->fd);
@@ -87,17 +85,17 @@
(void)array_append_space(&ctx->events);
}
-void io_loop_handle_remove(struct ioloop *ioloop, struct io *io)
+void io_loop_handle_remove(struct ioloop *ioloop, struct io_file *io)
{
struct ioloop_handler_context *ctx = ioloop->handler_context;
struct kevent ev;
- if ((io->condition & (IO_READ | IO_ERROR)) != 0) {
+ if ((io->io.condition & (IO_READ | IO_ERROR)) != 0) {
MY_EV_SET(&ev, io->fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0)
i_error("kevent(EV_DELETE, %d) failed: %m", io->fd);
}
- if ((io->condition & IO_WRITE) != 0) {
+ if ((io->io.condition & IO_WRITE) != 0) {
MY_EV_SET(&ev, io->fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0)
i_error("kevent(EV_DELETE, %d) failed: %m", io->fd);
@@ -107,6 +105,10 @@
deleted counter so next handle_add() can just decrease it
insteading of appending to the events array */
ctx->deleted_count++;
+
+ i_assert(io->refcount > 0);
+ if (--io->refcount == 0)
+ i_free(io);
}
void io_loop_handler_run(struct ioloop *ioloop)
@@ -116,7 +118,7 @@
const struct kevent *event;
struct timeval tv;
struct timespec ts;
- struct io *io;
+ struct io_file *io;
unsigned int events_count, t_id;
int msecs, ret, i;
@@ -147,19 +149,19 @@
io = (void *)event->udata;
/* callback is NULL if io_remove() was already called */
- if (io->callback != NULL) {
+ if (io->io.callback != NULL) {
t_id = t_push();
- io->callback(io->context);
+ io->io.callback(io->io.context);
if (t_pop() != t_id) {
i_panic("Leaked a t_pop() call in "
"I/O handler %p",
- (void *)io->callback);
+ (void *)io->io.callback);
}
}
i_assert(io->refcount > 0);
if (--io->refcount == 0)
- p_free(current_ioloop->pool, io);
+ i_free(io);
}
}
Index: ioloop-notify-dn.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/ioloop-notify-dn.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- ioloop-notify-dn.c 17 Jan 2007 17:59:13 -0000 1.18
+++ ioloop-notify-dn.c 8 Mar 2007 22:04:21 -0000 1.19
@@ -8,6 +8,7 @@
#ifdef IOLOOP_NOTIFY_DNOTIFY
#include "ioloop-internal.h"
+#include "ioloop-notify-fd.h"
#include "fd-set-nonblock.h"
#include "fd-close-on-exec.h"
@@ -16,14 +17,18 @@
#include <fcntl.h>
struct ioloop_notify_handler_context {
- struct io *event_io;
- bool disabled;
+ struct ioloop_notify_fd_context fd_ctx;
+ struct io *event_io;
int event_pipe[2];
+
+ bool disabled;
};
static int sigrt_refcount = 0;
+static struct ioloop_notify_handler_context *io_loop_notify_handler_init(void);
+
static void sigrt_handler(int signo __attr_unused__, siginfo_t *si,
void *data __attr_unused__)
{
@@ -41,41 +46,44 @@
errno = saved_errno;
}
-static void event_callback(struct ioloop *ioloop)
+static void dnotify_input(struct ioloop *ioloop)
{
struct ioloop_notify_handler_context *ctx =
ioloop->notify_handler_context;
- struct io *io;
- int fd, ret;
+ struct io_notify *io;
+ int fd_buf[256], i, ret;
- ret = read(ctx->event_pipe[0], &fd, sizeof(fd));
+ ret = read(ctx->event_pipe[0], fd_buf, sizeof(fd_buf));
if (ret < 0)
i_fatal("read(event_pipe) failed: %m");
- if (ret != sizeof(fd)) {
- i_fatal("read(event_pipe) returned %d != %"PRIuSIZE_T,
- ret, sizeof(fd));
- }
+ if ((ret % sizeof(fd_buf[0])) != 0)
+ i_fatal("read(event_pipe) returned %d", ret);
+ ret /= sizeof(fd_buf[0]);
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;
- }
+ for (i = 0; i < ret; i++) {
+ io = io_notify_fd_find(&ctx->fd_ctx, fd_buf[i]);
+ if (io != NULL)
+ io->io.callback(io->io.context);
}
}
-struct io *io_loop_notify_add(struct ioloop *ioloop, const char *path,
- io_callback_t *callback, void *context)
+#undef io_add_notify
+struct io *io_add_notify(const char *path, io_callback_t *callback,
+ void *context)
{
struct ioloop_notify_handler_context *ctx =
- ioloop->notify_handler_context;
- struct io *io;
+ current_ioloop->notify_handler_context;
int fd;
+ if (ctx == NULL)
+ ctx = io_loop_notify_handler_init();
+ if (ctx->disabled)
+ return NULL;
+
fd = open(path, O_RDONLY);
if (fd == -1) {
i_error("open(%s) for dnotify failed: %m", path);
@@ -109,23 +117,18 @@
}
if (ctx->event_io == NULL) {
- ctx->event_io =
- io_add(ctx->event_pipe[0], IO_READ,
- event_callback, ioloop);
+ ctx->event_io = io_add(ctx->event_pipe[0], IO_READ,
+ dnotify_input, current_ioloop);
}
- io = p_new(ioloop->pool, struct io, 1);
- io->fd = fd;
-
- io->callback = callback;
- io->context = context;
- return io;
+ return io_notify_fd_add(&ctx->fd_ctx, fd, callback, context);
}
-void io_loop_notify_remove(struct ioloop *ioloop, struct io *io)
+void io_loop_notify_remove(struct ioloop *ioloop, struct io *_io)
{
struct ioloop_notify_handler_context *ctx =
ioloop->notify_handler_context;
+ struct io_notify *io = (struct io_notify *)_io;
if (fcntl(io->fd, F_NOTIFY, 0) < 0)
i_error("fcntl(F_NOTIFY, 0) failed: %m");
@@ -134,21 +137,24 @@
if (close(io->fd))
i_error("close(dnotify) failed: %m");
- if (ioloop->notifys == NULL)
+ io_notify_fd_free(&ctx->fd_ctx, io);
+
+ if (ctx->fd_ctx.notifies == NULL)
io_remove(&ctx->event_io);
}
-void io_loop_notify_handler_init(struct ioloop *ioloop)
+static struct ioloop_notify_handler_context *io_loop_notify_handler_init(void)
{
struct ioloop_notify_handler_context *ctx;
struct sigaction act;
- ctx = ioloop->notify_handler_context =
+ ctx = current_ioloop->notify_handler_context =
i_new(struct ioloop_notify_handler_context, 1);
if (pipe(ctx->event_pipe) < 0) {
- i_fatal("pipe() failed: %m");
- return;
+ ctx->disabled = TRUE;
+ i_error("dnotify: pipe() failed: %m");
+ return ctx;
}
fd_set_nonblock(ctx->event_pipe[0], TRUE);
@@ -175,9 +181,10 @@
}
}
}
+ return ctx;
}
-void io_loop_notify_handler_deinit(struct ioloop *ioloop __attr_unused__)
+void io_loop_notify_handler_deinit(struct ioloop *ioloop)
{
struct ioloop_notify_handler_context *ctx =
ioloop->notify_handler_context;
--- NEW FILE: ioloop-notify-fd.c ---
/* Copyright (c) 2007 Timo Sirainen */
#include "lib.h"
#include "ioloop-internal.h"
#include "ioloop-notify-fd.h"
#if defined(IOLOOP_NOTIFY_DNOTIFY) || defined(IOLOOP_NOTIFY_INOTIFY)
struct io *io_notify_fd_add(struct ioloop_notify_fd_context *ctx, int fd,
io_callback_t *callback, void *context)
{
struct io_notify *io;
io = i_new(struct io_notify, 1);
io->io.condition = IO_NOTIFY;
io->io.callback = callback;
io->io.context = context;
io->fd = fd;
if (ctx->notifies != NULL) {
ctx->notifies->prev = io;
io->next = ctx->notifies;
}
ctx->notifies = io;
return &io->io;
}
void io_notify_fd_free(struct ioloop_notify_fd_context *ctx,
struct io_notify *io)
{
if (io->prev != NULL)
io->prev->next = io->next;
else
ctx->notifies = io->next;
if (io->next != NULL)
io->next->prev = io->prev;
i_free(io);
}
struct io_notify *
io_notify_fd_find(struct ioloop_notify_fd_context *ctx, int fd)
{
struct io_notify *io;
for (io = ctx->notifies; io != NULL; io = io->next) {
if (io->fd == fd)
return io;
}
return NULL;
}
#endif
--- NEW FILE: ioloop-notify-fd.h ---
#ifndef __IOLOOP_NOTIFY_FD_H
#define __IOLOOP_NOTIFY_FD_H
/* common notify code for fd-based notifications (dnotify, inotify) */
struct io_notify {
struct io io;
/* use a doubly linked list so that io_remove() is quick */
struct io_notify *prev, *next;
int fd;
};
struct ioloop_notify_fd_context {
struct io_notify *notifies;
};
struct io *io_notify_fd_add(struct ioloop_notify_fd_context *ctx, int fd,
io_callback_t *callback, void *context);
void io_notify_fd_free(struct ioloop_notify_fd_context *ctx,
struct io_notify *io);
struct io_notify *
io_notify_fd_find(struct ioloop_notify_fd_context *ctx, int fd);
#endif
Index: ioloop-notify-inotify.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/ioloop-notify-inotify.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- ioloop-notify-inotify.c 18 Jan 2007 16:44:09 -0000 1.12
+++ ioloop-notify-inotify.c 8 Mar 2007 22:04:21 -0000 1.13
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Johannes Berg */
+/* Copyright (C) 2005-2007 Johannes Berg, Timo Sirainen */
#define _GNU_SOURCE
#include "lib.h"
@@ -7,6 +7,7 @@
#include "fd-close-on-exec.h"
#include "ioloop-internal.h"
+#include "ioloop-notify-fd.h"
#include "buffer.h"
#include "network.h"
@@ -16,136 +17,115 @@
#include <sys/ioctl.h>
#include <sys/inotify.h>
-#define INITIAL_INOTIFY_BUFLEN (FILENAME_MAX + sizeof(struct inotify_event))
-#define MAXIMAL_INOTIFY_BUFLEN (32*1024)
-
-struct inotify_io {
- struct io io;
- int wd;
-};
+#define INOTIFY_BUFLEN (32*1024)
struct ioloop_notify_handler_context {
- int inotify_fd;
+ struct ioloop_notify_fd_context fd_ctx;
+ int inotify_fd;
struct io *event_io;
- buffer_t *buf;
bool disabled;
};
-static bool event_read_next(struct ioloop *ioloop)
+static struct ioloop_notify_handler_context *io_loop_notify_handler_init(void);
+
+static bool inotify_input_more(struct ioloop *ioloop)
{
struct ioloop_notify_handler_context *ctx =
ioloop->notify_handler_context;
- struct io *io;
- struct inotify_event *event;
- ssize_t ret;
- size_t record_length;
- int required_bytes;
-
- if (ioctl(ctx->inotify_fd, FIONREAD, &required_bytes))
- i_fatal("ioctl(inotify_fd, FIONREAD) failed: %m");
-
- if (required_bytes <= 0)
- return FALSE;
-
- if (required_bytes > MAXIMAL_INOTIFY_BUFLEN)
- required_bytes = MAXIMAL_INOTIFY_BUFLEN;
-
- event = buffer_get_space_unsafe(ctx->buf, 0, required_bytes);
- ret = read(ctx->inotify_fd, (void *)event, required_bytes);
-
- if (ret == 0)
- return FALSE;
+ const struct inotify_event *event;
+ unsigned char event_buf[INOTIFY_BUFLEN];
+ struct io_notify *io;
+ ssize_t ret, pos;
- if (ret < 0)
- i_fatal("read(inotify_fd) failed: %m");
+ /* read as many events as there is available and fit into our buffer.
+ only full events are returned by the kernel. */
+ ret = read(ctx->inotify_fd, event_buf, sizeof(event_buf));
+ if (ret <= 0) {
+ if (ret == 0) {
+ /* nothing more to read */
+ return FALSE;
+ }
+ i_fatal("read(inotify) failed: %m");
+ }
if (gettimeofday(&ioloop_timeval, &ioloop_timezone) < 0)
i_fatal("gettimeofday(): %m");
ioloop_time = ioloop_timeval.tv_sec;
- while ((size_t)required_bytes > sizeof(*event)) {
- for (io = ioloop->notifys; io != NULL; io = io->next) {
- struct inotify_io *iio = (struct inotify_io *)io;
-
- if (iio->wd == event->wd) {
- io->callback(io->context);
- break;
- }
- }
-
- record_length = event->len + sizeof(struct inotify_event);
- if ((size_t)required_bytes < record_length)
+ for (pos = 0; pos < ret; ) {
+ if ((size_t)(ret - pos) < sizeof(*event))
break;
- required_bytes -= record_length;
- /* this might point outside the area if the loop
- won't run again */
- event = PTR_OFFSET(event, record_length);
- }
+ event = (struct inotify_event *)(event_buf + pos);
+ pos += sizeof(*event) + event->len;
+ io = io_notify_fd_find(&ctx->fd_ctx, event->wd);
+ if (io != NULL)
+ io->io.callback(io->io.context);
+ }
+ if (pos != ret)
+ i_error("read(inotify) returned partial event");
return TRUE;
}
-static void event_callback(struct ioloop *ioloop)
+static void inotify_input(struct ioloop *ioloop)
{
- while (event_read_next(ioloop)) ;
+ while (inotify_input_more(ioloop)) ;
}
-struct io *io_loop_notify_add(struct ioloop *ioloop, const char *path,
- io_callback_t *callback, void *context)
+#undef io_add_notify
+struct io *io_add_notify(const char *path, io_callback_t *callback,
+ void *context)
{
struct ioloop_notify_handler_context *ctx =
- ioloop->notify_handler_context;
- struct inotify_io *io;
- int watchdescriptor;
+ current_ioloop->notify_handler_context;
+ int fd;
+ if (ctx == NULL)
+ ctx = io_loop_notify_handler_init();
if (ctx->disabled)
return NULL;
- watchdescriptor = inotify_add_watch(ctx->inotify_fd, path,
- IN_CREATE | IN_DELETE | IN_MOVE |
- IN_CLOSE | IN_MODIFY);
-
- if (watchdescriptor < 0) {
- ctx->disabled = TRUE;
+ fd = inotify_add_watch(ctx->inotify_fd, path,
+ IN_CREATE | IN_DELETE | IN_MOVE |
+ IN_CLOSE | IN_MODIFY);
+ if (fd < 0) {
/* 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;
}
if (ctx->event_io == NULL) {
ctx->event_io = io_add(ctx->inotify_fd, IO_READ,
- event_callback, ioloop);
+ inotify_input, current_ioloop);
}
- io = p_new(ioloop->pool, struct inotify_io, 1);
- io->io.fd = -1;
-
- io->io.callback = callback;
- io->io.context = context;
- io->wd = watchdescriptor;
- return &io->io;
+ return io_notify_fd_add(&ctx->fd_ctx, fd, callback, context);
}
void io_loop_notify_remove(struct ioloop *ioloop, struct io *_io)
{
struct ioloop_notify_handler_context *ctx =
ioloop->notify_handler_context;
- struct inotify_io *io = (struct inotify_io *)_io;
+ struct io_notify *io = (struct io_notify *)_io;
- if (inotify_rm_watch(ctx->inotify_fd, io->wd) < 0)
+ if (inotify_rm_watch(ctx->inotify_fd, io->fd) < 0)
i_error("inotify_rm_watch() failed: %m");
- if (ioloop->notifys == NULL)
+ io_notify_fd_free(&ctx->fd_ctx, io);
+
+ if (ctx->fd_ctx.notifies == NULL)
io_remove(&ctx->event_io);
}
-void io_loop_notify_handler_init(struct ioloop *ioloop)
+static struct ioloop_notify_handler_context *io_loop_notify_handler_init(void)
{
+ struct ioloop *ioloop = current_ioloop;
struct ioloop_notify_handler_context *ctx;
ctx = ioloop->notify_handler_context =
@@ -155,11 +135,10 @@
if (ctx->inotify_fd == -1) {
i_error("inotify_init() failed: %m");
ctx->disabled = TRUE;
- return;
+ } else {
+ fd_close_on_exec(ctx->inotify_fd, TRUE);
}
- fd_close_on_exec(ctx->inotify_fd, TRUE);
-
- ctx->buf = buffer_create_dynamic(default_pool, INITIAL_INOTIFY_BUFLEN);
+ return ctx;
}
void io_loop_notify_handler_deinit(struct ioloop *ioloop)
@@ -167,12 +146,10 @@
struct ioloop_notify_handler_context *ctx =
ioloop->notify_handler_context;
- if (ctx->inotify_fd != -1)
+ if (ctx->inotify_fd != -1) {
if (close(ctx->inotify_fd) < 0)
- i_error("close(inotify descriptor) failed: %m");
-
- if (ctx->buf != NULL)
- buffer_free(ctx->buf);
+ i_error("close(inotify) failed: %m");
+ }
i_free(ctx);
}
Index: ioloop-notify-kqueue.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/ioloop-notify-kqueue.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- ioloop-notify-kqueue.c 15 Dec 2006 18:38:10 -0000 1.8
+++ ioloop-notify-kqueue.c 8 Mar 2007 22:04:21 -0000 1.9
@@ -33,6 +33,12 @@
EV_SET(a, b, c, d, e, f, g)
#endif
+struct io_notify {
+ struct io io;
+ int refcount;
+ int fd;
+};
+
struct ioloop_notify_handler_context {
int kq;
struct io *event_io;
@@ -40,39 +46,55 @@
static void event_callback(struct ioloop_notify_handler_context *ctx)
{
- struct io *io;
- struct kevent ev;
+ struct io_notify *io;
+ struct kevent events[64];
struct timespec ts;
- int ret;
-
- if (gettimeofday(&ioloop_timeval, &ioloop_timezone) < 0)
- i_fatal("gettimeofday() failed: %m");
- ioloop_time = ioloop_timeval.tv_sec;
+ int i, ret;
ts.tv_sec = 0;
ts.tv_nsec = 0;
- ret = kevent(ctx->kq, NULL, 0, &ev, 1, &ts);
+ ret = kevent(ctx->kq, NULL, 0, events,
+ sizeof(events)/sizeof(events[0]), &ts);
if (ret <= 0) {
if (ret == 0 || errno == EINTR)
return;
i_fatal("kevent(notify) failed: %m");
}
- io = (void *)ev.udata;
- io->callback(io->context);
+
+ if (gettimeofday(&ioloop_timeval, &ioloop_timezone) < 0)
+ i_fatal("gettimeofday() failed: %m");
+ ioloop_time = ioloop_timeval.tv_sec;
+
+ for (i = 0; i < ret; i++) {
+ io = (void *)events[i].udata;
+ i_assert(io->refcount == 1);
+ io->refcount++;
+ }
+ for (i = 0; i < ret; i++) {
+ io = (void *)events[i].udata;
+ /* there can be multiple events for a single io.
+ call the callback only once if that happens. */
+ if (io->refcount == 2 && io->io.callback != NULL)
+ io->io.callback(io->io.context);
+
+ if (--io->refcount == 0)
+ i_free(io);
+ }
}
-void io_loop_notify_handler_init(struct ioloop *ioloop)
+static struct ioloop_notify_handler_context *io_loop_notify_handler_init(void)
{
struct ioloop_notify_handler_context *ctx;
- ctx = ioloop->notify_handler_context =
- p_new(ioloop->pool, struct ioloop_notify_handler_context, 1);
+ ctx = current_ioloop->notify_handler_context =
+ i_new(struct ioloop_notify_handler_context, 1);
ctx->kq = kqueue();
if (ctx->kq < 0)
i_fatal("kqueue(notify) failed: %m");
fd_close_on_exec(ctx->kq, TRUE);
+ return ctx;
}
void io_loop_notify_handler_deinit(struct ioloop *ioloop)
@@ -84,19 +106,23 @@
io_remove(&ctx->event_io);
if (close(ctx->kq) < 0)
i_error("close(kqueue notify) failed: %m");
- p_free(ioloop->pool, ctx);
+ i_free(ctx);
}
-struct io *io_loop_notify_add(struct ioloop *ioloop, const char *path,
- io_callback_t *callback, void *context)
+#undef io_add_notify
+struct io *io_add_notify(const char *path, io_callback_t *callback,
+ void *context)
{
struct ioloop_notify_handler_context *ctx =
- ioloop->notify_handler_context;
+ current_ioloop->notify_handler_context;
struct kevent ev;
- struct io *io;
+ struct io_notify *io;
int fd;
struct stat sb;
+ if (ctx == NULL)
+ ctx = io_loop_notify_handler_init();
+
fd = open(path, O_RDONLY);
if (fd == -1) {
if (errno != ENOENT)
@@ -115,10 +141,11 @@
}
fd_close_on_exec(fd, TRUE);
- io = p_new(ioloop->pool, struct io, 1);
+ io = i_new(struct io_notify, 1);
+ io->io.callback = callback;
+ io->io.context = context;
+ io->refcount = 1;
io->fd = fd;
- io->callback = callback;
- io->context = context;
/* EV_CLEAR flag is needed because the EVFILT_VNODE filter reports
event state transitions and not the current state. With this flag,
@@ -128,31 +155,33 @@
if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0) {
i_error("kevent(%d, %s) for notify failed: %m", fd, path);
(void)close(fd);
- p_free(ioloop->pool, io);
+ i_free(io);
return NULL;
}
if (ctx->event_io == NULL) {
- ctx->event_io =
- io_add(ctx->kq, IO_READ, event_callback,
- ioloop->notify_handler_context);
+ ctx->event_io = io_add(ctx->kq, IO_READ, event_callback,
+ current_ioloop->notify_handler_context);
}
- return io;
+ return &io->io;
}
-void io_loop_notify_remove(struct ioloop *ioloop, struct io *io)
+void io_loop_notify_remove(struct ioloop *ioloop, struct io *_io)
{
struct ioloop_notify_handler_context *ctx =
ioloop->notify_handler_context;
+ struct io_notify *io = (struct io_notify *)_io;
struct kevent ev;
- i_assert((io->condition & IO_NOTIFY) != 0);
-
MY_EV_SET(&ev, io->fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL);
if (kevent(ctx->kq, &ev, 1, NULL, 0, 0) < 0)
i_error("kevent(%d) for notify remove failed: %m", io->fd);
if (close(io->fd) < 0)
i_error("close(%d) for notify remove failed: %m", io->fd);
+ io->fd = -1;
+
+ if (--io->refcount == 0)
+ i_free(io);
}
#endif
Index: ioloop-poll.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/ioloop-poll.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- ioloop-poll.c 28 Dec 2006 18:09:07 -0000 1.34
+++ ioloop-poll.c 8 Mar 2007 22:04:21 -0000 1.35
@@ -22,31 +22,30 @@
{
struct ioloop_handler_context *ctx;
- ioloop->handler_context = ctx =
- p_new(ioloop->pool, struct ioloop_handler_context, 1);
+ ioloop->handler_context = ctx = i_new(struct ioloop_handler_context, 1);
ctx->fds_count = IOLOOP_INITIAL_FD_COUNT;
- ctx->fds = p_new(ioloop->pool, struct pollfd, ctx->fds_count);
+ ctx->fds = i_new(struct pollfd, ctx->fds_count);
ctx->idx_count = IOLOOP_INITIAL_FD_COUNT;
- ctx->fd_index = p_new(ioloop->pool, int, ctx->idx_count);
+ ctx->fd_index = i_new(int, ctx->idx_count);
memset(ctx->fd_index, 0xff, sizeof(int) * ctx->idx_count);
}
void io_loop_handler_deinit(struct ioloop *ioloop)
{
- p_free(ioloop->pool, ioloop->handler_context->fds);
- p_free(ioloop->pool, ioloop->handler_context->fd_index);
- p_free(ioloop->pool, ioloop->handler_context);
+ i_free(ioloop->handler_context->fds);
+ i_free(ioloop->handler_context->fd_index);
+ i_free(ioloop->handler_context);
}
#define IO_POLL_ERROR (POLLERR | POLLHUP | POLLNVAL)
#define IO_POLL_INPUT (POLLIN | POLLPRI | IO_POLL_ERROR)
#define IO_POLL_OUTPUT (POLLOUT | IO_POLL_ERROR)
-void io_loop_handle_add(struct ioloop *ioloop, struct io *io)
+void io_loop_handle_add(struct ioloop *ioloop, struct io_file *io)
{
struct ioloop_handler_context *ctx = ioloop->handler_context;
- enum io_condition condition = io->condition;
+ enum io_condition condition = io->io.condition;
unsigned int old_count;
int index, fd = io->fd;
@@ -56,7 +55,7 @@
ctx->idx_count = nearest_power((unsigned int) fd+1);
- ctx->fd_index = p_realloc(ioloop->pool, ctx->fd_index,
+ ctx->fd_index = i_realloc(ctx->fd_index,
sizeof(int) * old_count,
sizeof(int) * ctx->idx_count);
memset(ctx->fd_index + old_count, 0xff,
@@ -69,7 +68,7 @@
ctx->fds_count = nearest_power(ctx->fds_count+1);
- ctx->fds = p_realloc(ioloop->pool, ctx->fds,
+ ctx->fds = i_realloc(ctx->fds,
sizeof(struct pollfd) * old_count,
sizeof(struct pollfd) * ctx->fds_count);
}
@@ -95,10 +94,10 @@
ctx->fds[index].events |= IO_POLL_ERROR;
}
-void io_loop_handle_remove(struct ioloop *ioloop, struct io *io)
+void io_loop_handle_remove(struct ioloop *ioloop, struct io_file *io)
{
struct ioloop_handler_context *ctx = ioloop->handler_context;
- enum io_condition condition = io->condition;
+ enum io_condition condition = io->io.condition;
int index, fd = io->fd;
index = ctx->fd_index[fd];
@@ -116,6 +115,7 @@
i_error("fcntl(%d, F_GETFD) failed: %m", io->fd);
}
#endif
+ i_free(io);
if (condition & IO_READ) {
ctx->fds[index].events &= ~(POLLIN|POLLPRI);
@@ -143,7 +143,7 @@
struct ioloop_handler_context *ctx = ioloop->handler_context;
struct pollfd *pollfd;
struct timeval tv;
- struct io *io;
+ struct io_file *io;
unsigned int t_id;
int msecs, ret;
bool call;
@@ -163,28 +163,29 @@
return;
}
- for (io = ioloop->ios; io != NULL && ret > 0; io = ioloop->next_io) {
- ioloop->next_io = io->next;
+ io = ioloop->io_files;
+ for (; io != NULL && ret > 0; io = ioloop->next_io_file) {
+ ioloop->next_io_file = io->next;
pollfd = &ctx->fds[ctx->fd_index[io->fd]];
if (pollfd->revents != 0) {
if (pollfd->revents & POLLNVAL) {
i_error("invalid I/O fd %d, callback %p",
- io->fd, (void *) io->callback);
+ io->fd, (void *) io->io.callback);
pollfd->events = 0;
pollfd->revents = 0;
call = TRUE;
- } else if ((io->condition &
+ } else if ((io->io.condition &
(IO_READ|IO_WRITE)) == (IO_READ|IO_WRITE)) {
call = TRUE;
pollfd->revents = 0;
- } else if (io->condition & IO_READ) {
+ } else if (io->io.condition & IO_READ) {
call = (pollfd->revents & IO_POLL_INPUT) != 0;
pollfd->revents &= ~IO_POLL_INPUT;
- } else if (io->condition & IO_WRITE) {
+ } else if (io->io.condition & IO_WRITE) {
call = (pollfd->revents & IO_POLL_OUTPUT) != 0;
pollfd->revents &= ~IO_POLL_OUTPUT;
- } else if (io->condition & IO_ERROR) {
+ } else if (io->io.condition & IO_ERROR) {
call = (pollfd->revents & IO_POLL_ERROR) != 0;
pollfd->revents &= ~IO_POLL_ERROR;
} else {
@@ -196,11 +197,11 @@
if (call) {
t_id = t_push();
- io->callback(io->context);
+ io->io.callback(io->io.context);
if (t_pop() != t_id) {
i_panic("Leaked a t_pop() call in "
"I/O handler %p",
- (void *)io->callback);
+ (void *)io->io.callback);
}
}
}
Index: ioloop-select.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/ioloop-select.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- ioloop-select.c 7 Mar 2007 15:57:41 -0000 1.24
+++ ioloop-select.c 8 Mar 2007 22:04:21 -0000 1.25
@@ -20,13 +20,13 @@
static void update_highest_fd(struct ioloop *ioloop)
{
struct ioloop_handler_context *ctx = ioloop->handler_context;
- struct io *io;
+ struct io_file *io;
int max_highest_fd;
max_highest_fd = ctx->highest_fd-1;
ctx->highest_fd = -1;
- for (io = ioloop->ios; io != NULL; io = io->next) {
+ for (io = ioloop->io_files; io != NULL; io = io->next) {
if (io->fd <= ctx->highest_fd)
continue;
@@ -41,8 +41,7 @@
{
struct ioloop_handler_context *ctx;
- ioloop->handler_context = ctx =
- p_new(ioloop->pool, struct ioloop_handler_context, 1);
+ ioloop->handler_context = ctx = i_new(struct ioloop_handler_context, 1);
ctx->highest_fd = -1;
FD_ZERO(&ctx->read_fds);
FD_ZERO(&ctx->write_fds);
@@ -51,13 +50,13 @@
void io_loop_handler_deinit(struct ioloop *ioloop)
{
- p_free(ioloop->pool, ioloop->handler_context);
+ i_free(ioloop->handler_context);
}
-void io_loop_handle_add(struct ioloop *ioloop, struct io *io)
+void io_loop_handle_add(struct ioloop *ioloop, struct io_file *io)
{
struct ioloop_handler_context *ctx = ioloop->handler_context;
- enum io_condition condition = io->condition;
+ enum io_condition condition = io->io.condition;
int fd = io->fd;
i_assert(fd >= 0);
@@ -75,10 +74,10 @@
ctx->highest_fd = io->fd;
}
-void io_loop_handle_remove(struct ioloop *ioloop, struct io *io)
+void io_loop_handle_remove(struct ioloop *ioloop, struct io_file *io)
{
struct ioloop_handler_context *ctx = ioloop->handler_context;
- enum io_condition condition = io->condition;
+ enum io_condition condition = io->io.condition;
int fd = io->fd;
i_assert(fd >= 0 && fd < FD_SETSIZE);
@@ -95,6 +94,7 @@
if (io->fd == ctx->highest_fd)
update_highest_fd(ioloop);
}
+ i_free(io);
}
#define io_check_condition(ctx, fd, cond) \
@@ -106,7 +106,7 @@
{
struct ioloop_handler_context *ctx = ioloop->handler_context;
struct timeval tv;
- struct io *io;
+ struct io_file *io;
unsigned int t_id;
int ret;
@@ -130,17 +130,19 @@
return;
}
- for (io = ioloop->ios; io != NULL && ret > 0; io = ioloop->next_io) {
- ioloop->next_io = io->next;
+ io = ioloop->io_files;
+ for (; io != NULL && ret > 0; io = ioloop->next_io_file) {
+ ioloop->next_io_file = io->next;
- if (io_check_condition(ctx, io->fd, io->condition)) {
+ if (io_check_condition(ctx, io->fd, io->io.condition)) {
ret--;
t_id = t_push();
- io->callback(io->context);
+ io->io.callback(io->io.context);
if (t_pop() != t_id) {
i_panic("Leaked a t_pop() call in "
- "I/O handler %p", (void *)io->callback);
+ "I/O handler %p",
+ (void *)io->io.callback);
}
}
}
Index: ioloop.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/ioloop.c,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -d -r1.43 -r1.44
--- ioloop.c 7 Mar 2007 16:08:02 -0000 1.43
+++ ioloop.c 8 Mar 2007 22:04:21 -0000 1.44
@@ -23,54 +23,43 @@
struct io *io_add(int fd, enum io_condition condition,
io_callback_t *callback, void *context)
{
- struct io *io;
+ struct io_file *io;
i_assert(fd >= 0);
i_assert(callback != NULL);
i_assert((condition & IO_NOTIFY) == 0);
- io = p_new(current_ioloop->pool, struct io, 1);
+ io = i_new(struct io_file, 1);
+ io->io.condition = condition;
+ io->io.callback = callback;
+ io->io.context = context;
io->refcount = 1;
io->fd = fd;
- io->condition = condition;
-
- io->callback = callback;
- io->context = context;
io_loop_handle_add(current_ioloop, io);
- io->next = current_ioloop->ios;
- current_ioloop->ios = io;
-
- if (io->next != NULL)
- io->next->prev = io;
- return io;
+ if (current_ioloop->io_files != NULL) {
+ current_ioloop->io_files->prev = io;
+ io->next = current_ioloop->io_files;
+ }
+ current_ioloop->io_files = io;
+ return &io->io;
}
-#undef io_add_notify
-struct io *io_add_notify(const char *path, io_callback_t *callback,
- void *context)
+static void io_file_unlink(struct io_file *io)
{
- struct io *io;
-
- i_assert(path != NULL);
- i_assert(callback != NULL);
-
- if (current_ioloop->notify_handler_context == NULL)
- io_loop_notify_handler_init(current_ioloop);
-
- io = io_loop_notify_add(current_ioloop, path, callback, context);
- if (io == NULL)
- return NULL;
-
- io->refcount = 1;
- io->condition |= IO_NOTIFY;
- io->next = current_ioloop->notifys;
- current_ioloop->notifys = io;
+ if (io->prev != NULL)
+ io->prev->next = io->next;
+ else
+ current_ioloop->io_files = io->next;
if (io->next != NULL)
- io->next->prev = io;
- return io;
+ io->next->prev = io->prev;
+
+ /* if we got here from an I/O handler callback, make sure we
+ don't try to handle this one next. */
+ if (current_ioloop->next_io_file == io)
+ current_ioloop->next_io_file = io->next;
}
void io_remove(struct io **_io)
@@ -79,35 +68,18 @@
*_io = NULL;
- i_assert(io->refcount > 0);
+ /* make sure the callback doesn't get called anymore.
+ kqueue code relies on this. */
+ io->callback = NULL;
- /* unlink from linked list */
- if (io->prev != NULL)
- io->prev->next = io->next;
+ if ((io->condition & IO_NOTIFY) != 0)
+ io_loop_notify_remove(current_ioloop, io);
else {
- if ((io->condition & IO_NOTIFY) == 0)
- current_ioloop->ios = io->next;
- else
- current_ioloop->notifys = io->next;
- }
- if (io->next != NULL)
- io->next->prev = io->prev;
-
- if ((io->condition & IO_NOTIFY) == 0) {
- /* if we got here from an I/O handler callback, make sure we
- don't try to handle this one next. */
- if (current_ioloop->next_io == io)
- current_ioloop->next_io = io->next;
+ struct io_file *io_file = (struct io_file *)io;
- io_loop_handle_remove(current_ioloop, io);
- } else {
- io_loop_notify_remove(current_ioloop, io);
+ io_file_unlink(io_file);
+ io_loop_handle_remove(current_ioloop, io_file);
}
-
- io->callback = NULL;
-
- if (--io->refcount == 0)
- p_free(current_ioloop->pool, io);
}
static void timeout_list_insert(struct ioloop *ioloop, struct timeout *timeout)
@@ -154,7 +126,7 @@
{
struct timeout *timeout;
- timeout = p_new(current_ioloop->pool, struct timeout, 1);
+ timeout = i_new(struct timeout, 1);
timeout->msecs = msecs;
timeout->callback = callback;
@@ -174,14 +146,6 @@
*timeout = NULL;
}
-void timeout_destroy(struct ioloop *ioloop, struct timeout **timeout_p)
-{
- struct timeout *timeout = *timeout_p;
-
- *timeout_p = timeout->next;
- p_free(ioloop->pool, timeout);
-}
-
int io_loop_get_wait_time(struct timeout *timeout, struct timeval *tv,
struct timeval *tv_now)
{
@@ -268,7 +232,8 @@
struct timeout *t = ioloop->timeouts;
if (t->destroyed) {
- timeout_destroy(ioloop, &ioloop->timeouts);
+ ioloop->timeouts = t->next;
+ i_free(t);
continue;
}
@@ -300,9 +265,10 @@
while (called_timeouts != NULL) {
struct timeout *t = called_timeouts;
- if (t->destroyed)
- timeout_destroy(ioloop, &called_timeouts);
- else {
+ if (t->destroyed) {
+ called_timeouts = t->next;
+ i_free(t);
+ } else {
called_timeouts = t->next;
timeout_list_insert(current_ioloop, t);
}
@@ -341,7 +307,7 @@
return ioloop->running;
}
-struct ioloop *io_loop_create(pool_t pool)
+struct ioloop *io_loop_create(void)
{
struct ioloop *ioloop;
@@ -350,10 +316,7 @@
i_fatal("gettimeofday(): %m");
ioloop_time = ioloop_timeval.tv_sec;
- ioloop = p_new(pool, struct ioloop, 1);
- pool_ref(pool);
- ioloop->pool = pool;
-
+ ioloop = i_new(struct ioloop, 1);
io_loop_handler_init(ioloop);
ioloop->prev = current_ioloop;
@@ -365,18 +328,18 @@
void io_loop_destroy(struct ioloop **_ioloop)
{
struct ioloop *ioloop = *_ioloop;
- pool_t pool;
*_ioloop = NULL;
if (ioloop->notify_handler_context != NULL)
io_loop_notify_handler_deinit(ioloop);
- while (ioloop->ios != NULL) {
- struct io *io = ioloop->ios;
+ while (ioloop->io_files != NULL) {
+ struct io_file *io = ioloop->io_files;
+ struct io *_io = &io->io;
- i_warning("I/O leak: %p (%d)", (void *)io->callback, io->fd);
- io_remove(&io);
+ i_warning("I/O leak: %p (%d)", (void *)io->io.callback, io->fd);
+ io_remove(&_io);
}
while (ioloop->timeouts != NULL) {
@@ -386,7 +349,8 @@
i_warning("Timeout leak: %p", (void *)to->callback);
timeout_remove(&to);
}
- timeout_destroy(ioloop, &ioloop->timeouts);
+ ioloop->timeouts = to->next;
+ i_free(to);
}
io_loop_handler_deinit(ioloop);
@@ -395,7 +359,5 @@
i_assert(ioloop == current_ioloop);
current_ioloop = current_ioloop->prev;
- pool = ioloop->pool;
- p_free(pool, ioloop);
- pool_unref(pool);
+ i_free(ioloop);
}
Index: ioloop.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/ioloop.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- ioloop.h 15 Dec 2006 16:55:32 -0000 1.20
+++ ioloop.h 8 Mar 2007 22:04:21 -0000 1.21
@@ -65,7 +65,7 @@
void io_loop_set_running(struct ioloop *ioloop);
void io_loop_handler_run(struct ioloop *ioloop);
-struct ioloop *io_loop_create(pool_t pool);
+struct ioloop *io_loop_create(void);
/* Destroy I/O loop and set ioloop pointer to NULL. */
void io_loop_destroy(struct ioloop **ioloop);
More information about the dovecot-cvs
mailing list