changeset 1730:8480f945e270 HEAD

IDLE uses now IO_*_NOTIFY to get instant notifying of mails.
author Timo Sirainen <tss@iki.fi>
date Sun, 24 Aug 2003 15:45:32 +0300
parents 5bf22d6bb65e
children 687a06278ef5
files src/imap/cmd-idle.c src/imap/cmd-select.c src/imap/commands-util.c src/lib-storage/index/index-mailbox-check.c src/lib-storage/index/index-storage.h src/lib-storage/index/index-sync.c src/lib-storage/index/maildir/maildir-storage.c src/lib-storage/index/mbox/mbox-storage.c src/lib-storage/mail-storage.h src/lib-storage/proxy-mailbox.c
diffstat 10 files changed, 117 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap/cmd-idle.c	Sun Aug 24 15:43:53 2003 +0300
+++ b/src/imap/cmd-idle.c	Sun Aug 24 15:45:32 2003 +0300
@@ -10,6 +10,7 @@
 
 #define DEFAULT_IDLE_CHECK_INTERVAL 30
 
+#include "imap-fetch.h"
 static void idle_finish(struct client *client, int done_ok)
 {
 	if (client->idle_to != NULL) {
@@ -31,7 +32,7 @@
 	if (client->mailbox != NULL) {
 		client->mailbox->auto_sync(client->mailbox,
 					   mailbox_check_interval != 0 ?
-					   MAILBOX_SYNC_NO_EXPUNGES :
+					   MAILBOX_SYNC_FLAG_NO_EXPUNGES :
 					   MAILBOX_SYNC_NONE,
 					   mailbox_check_interval);
 	}
@@ -118,7 +119,7 @@
 
 	if (client->mailbox != NULL) {
 		client->mailbox->auto_sync(client->mailbox,
-					   MAILBOX_SYNC_ALL, interval);
+					   MAILBOX_SYNC_FULL, interval);
 	}
 
 	client_send_line(client, "+ idling");
--- a/src/imap/cmd-select.c	Sun Aug 24 15:43:53 2003 +0300
+++ b/src/imap/cmd-select.c	Sun Aug 24 15:45:32 2003 +0300
@@ -85,7 +85,7 @@
 			    "OK [READ-WRITE] Select completed.");
 
 	if (mailbox_check_interval != 0) {
-		box->auto_sync(box, MAILBOX_SYNC_NO_EXPUNGES,
+		box->auto_sync(box, MAILBOX_SYNC_FLAG_NO_EXPUNGES,
 			       mailbox_check_interval);
 	}
 
--- a/src/imap/commands-util.c	Sun Aug 24 15:43:53 2003 +0300
+++ b/src/imap/commands-util.c	Sun Aug 24 15:45:32 2003 +0300
@@ -126,7 +126,7 @@
 	if (client->mailbox == NULL)
 		return;
 
-	if (!client->mailbox->sync(client->mailbox, MAIL_SYNC_FLAG_FAST)) {
+	if (!client->mailbox->sync(client->mailbox, MAILBOX_SYNC_FAST)) {
 		client_send_untagged_storage_error(client,
 						   client->mailbox->storage);
 	}
@@ -137,8 +137,8 @@
 	if (client->mailbox == NULL)
 		return;
 
-	if (!client->mailbox->sync(client->mailbox, MAIL_SYNC_FLAG_NO_EXPUNGES |
-				   MAIL_SYNC_FLAG_FAST)) {
+	if (!client->mailbox->sync(client->mailbox, MAILBOX_SYNC_FAST |
+				   MAILBOX_SYNC_FLAG_NO_EXPUNGES)) {
 		client_send_untagged_storage_error(client,
 						   client->mailbox->storage);
 	}
--- a/src/lib-storage/index/index-mailbox-check.c	Sun Aug 24 15:43:53 2003 +0300
+++ b/src/lib-storage/index/index-mailbox-check.c	Sun Aug 24 15:45:32 2003 +0300
@@ -12,7 +12,7 @@
 	struct index_mailbox *ibox = context;
 	struct index_autosync_file *file;
 	struct stat st;
-	int synced, sync_expunges;
+	int sync;
 
 	/* check changes only when we can also notify of new mail */
 	if ((unsigned int) (ioloop_time - ibox->sync_last_check) <
@@ -21,29 +21,61 @@
 
 	ibox->sync_last_check = ioloop_time;
 
-	synced = FALSE;
-	sync_expunges = ibox->autosync_type != MAILBOX_SYNC_NO_EXPUNGES;
-
+	sync = ibox->autosync_pending;
 	for (file = ibox->autosync_files; file != NULL; file = file->next) {
 		if (stat(file->path, &st) == 0 &&
-		    file->last_stamp != st.st_mtime) {
+		    file->last_stamp != st.st_mtime)
 			file->last_stamp = st.st_mtime;
-			if (!synced) {
-				ibox->box.sync(&ibox->box, sync_expunges);
-				synced = TRUE;
-			}
-		}
+	}
+
+	if (sync) {
+		ibox->box.sync(&ibox->box, ibox->autosync_flags);
+                ibox->autosync_pending = FALSE;
+	}
+}
+
+static void notify_callback(void *context)
+{
+	struct index_mailbox *ibox = context;
+
+	if ((unsigned int) (ioloop_time - ibox->sync_last_check) >=
+	    ibox->min_newmail_notify_interval) {
+		ibox->sync_last_check = ioloop_time;
+		ibox->box.sync(&ibox->box, ibox->autosync_flags);
+                ibox->autosync_pending = FALSE;
+	} else {
+		ibox->autosync_pending = TRUE;
 	}
 }
 
-void index_mailbox_check_add(struct index_mailbox *ibox, const char *path)
+void index_mailbox_check_add(struct index_mailbox *ibox,
+			     const char *path, int dir)
 {
 	struct index_autosync_file *file;
 	struct stat st;
+	struct io *io;
+	struct index_autosync_io *aio;
+	int fd;
+
+	fd = open(path, O_RDONLY);
+	if (fd >= 0) {
+		io = io_add(fd, dir ? IO_DIR_NOTIFY : IO_FILE_NOTIFY,
+			    notify_callback, ibox);
+		if (io != NULL) {
+			aio = i_new(struct index_autosync_io, 1);
+			aio->io = io;
+			aio->fd = fd;
+			aio->next = ibox->autosync_ios;
+			ibox->autosync_ios = aio;
+		}
+	}
 
 	file = i_new(struct index_autosync_file, 1);
 	file->path = i_strdup(path);
-	file->last_stamp = stat(path, &st) < 0 ? 0 : st.st_mtime;
+	if (fd < 0)
+		file->last_stamp = stat(path, &st) < 0 ? 0 : st.st_mtime;
+	else
+		file->last_stamp = fstat(fd, &st) < 0 ? 0 : st.st_mtime;
 
 	file->next = ibox->autosync_files;
         ibox->autosync_files = file;
@@ -55,6 +87,7 @@
 void index_mailbox_check_remove_all(struct index_mailbox *ibox)
 {
 	struct index_autosync_file *file;
+	struct index_autosync_io *aio;
 
 	while (ibox->autosync_files != NULL) {
 		file = ibox->autosync_files;
@@ -64,6 +97,16 @@
 		i_free(file);
 	}
 
+	while (ibox->autosync_ios != NULL) {
+		aio = ibox->autosync_ios;
+		ibox->autosync_ios = aio->next;
+
+		io_remove(aio->io);
+		if (close(aio->fd) < 0)
+			i_error("close(autosync_io) failed: %m");
+		i_free(aio);
+	}
+
 	if (ibox->autosync_to != NULL) {
 		timeout_remove(ibox->autosync_to);
 		ibox->autosync_to = NULL;
--- a/src/lib-storage/index/index-storage.h	Sun Aug 24 15:43:53 2003 +0300
+++ b/src/lib-storage/index/index-storage.h	Sun Aug 24 15:45:32 2003 +0300
@@ -12,6 +12,12 @@
 	time_t last_stamp;
 };
 
+struct index_autosync_io {
+	struct index_autosync_io *next;
+	struct io *io;
+	int fd;
+};
+
 struct index_mailbox {
 	struct mailbox box;
 
@@ -24,8 +30,9 @@
 	struct mail_cache_transaction_ctx *trans_ctx;
 
 	struct timeout *autosync_to;
-        struct index_autosync_file *autosync_files;
-	enum mailbox_sync_type autosync_type;
+	struct index_autosync_file *autosync_files;
+        struct index_autosync_io *autosync_ios;
+	enum mailbox_sync_flags autosync_flags;
 	time_t sync_last_check;
 	unsigned int min_newmail_notify_interval;
 
@@ -39,6 +46,7 @@
 	unsigned int inconsistent:1;
 	unsigned int sent_diskspace_warning:1;
 	unsigned int sent_readonly_flags_warning:1;
+	unsigned int autosync_pending:1;
 };
 
 int mail_storage_set_index_error(struct index_mailbox *ibox);
@@ -76,7 +84,8 @@
 
 unsigned int index_storage_get_recent_count(struct mail_index *index);
 
-void index_mailbox_check_add(struct index_mailbox *ibox, const char *path);
+void index_mailbox_check_add(struct index_mailbox *ibox,
+			     const char *path, int dir);
 void index_mailbox_check_remove_all(struct index_mailbox *ibox);
 
 /* mailbox methods: */
@@ -86,7 +95,7 @@
 int index_storage_get_status(struct mailbox *box,
 			     enum mailbox_status_items items,
 			     struct mailbox_status *status);
-int index_storage_sync(struct mailbox *box, enum mail_sync_flags flags);
+int index_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags);
 
 struct mail_fetch_context *
 index_storage_fetch_init(struct mailbox *box,
--- a/src/lib-storage/index/index-sync.c	Sun Aug 24 15:43:53 2003 +0300
+++ b/src/lib-storage/index/index-sync.c	Sun Aug 24 15:45:32 2003 +0300
@@ -213,12 +213,12 @@
 	return TRUE;
 }
 
-int index_storage_sync(struct mailbox *box, enum mail_sync_flags flags)
+int index_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags)
 {
 	struct index_mailbox *ibox = (struct index_mailbox *) box;
 	int ret;
 
-	if ((flags & MAIL_SYNC_FLAG_FAST) == 0 ||
+	if ((flags & MAILBOX_SYNC_FAST) == 0 ||
 	    ibox->sync_last_check + MAILBOX_FULL_SYNC_INTERVAL <= ioloop_time) {
 		ibox->sync_last_check = ioloop_time;
 
@@ -235,7 +235,7 @@
 
 	/* FIXME: we could sync flags always, but expunges in the middle
 	   could make it a bit more difficult and slower */
-	if ((flags & MAIL_SYNC_FLAG_NO_EXPUNGES) == 0 ||
+	if ((flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) == 0 ||
 	    mail_modifylog_get_expunge_count(ibox->index->modifylog) == 0)
 		ret = index_storage_sync_modifylog(ibox, FALSE);
 	else
--- a/src/lib-storage/index/maildir/maildir-storage.c	Sun Aug 24 15:43:53 2003 +0300
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Sun Aug 24 15:45:32 2003 +0300
@@ -753,21 +753,29 @@
 }
 
 static void maildir_storage_auto_sync(struct mailbox *box,
-				      enum mailbox_sync_type sync_type,
+				      enum mailbox_sync_flags flags,
 				      unsigned int min_newmail_notify_interval)
 {
 	struct index_mailbox *ibox = (struct index_mailbox *) box;
 
-	ibox->autosync_type = sync_type;
 	ibox->min_newmail_notify_interval = min_newmail_notify_interval;
 
-        index_mailbox_check_remove_all(ibox);
-	if (sync_type != MAILBOX_SYNC_NONE) {
-		index_mailbox_check_add(ibox,
-			t_strconcat(ibox->index->mailbox_path, "/new", NULL));
-		index_mailbox_check_add(ibox,
-			t_strconcat(ibox->index->mailbox_path, "/cur", NULL));
+	if ((ibox->autosync_flags == 0 && flags == 0) ||
+	    (ibox->autosync_flags != 0 && flags != 0)) {
+		/* flags or interval just changed. or nothing. */
+		ibox->autosync_flags = flags;
 	}
+	ibox->autosync_flags = flags;
+
+	if (flags == 0) {
+		index_mailbox_check_remove_all(ibox);
+		return;
+	}
+
+	index_mailbox_check_add(ibox,
+		t_strconcat(ibox->index->mailbox_path, "/new", NULL), TRUE);
+	index_mailbox_check_add(ibox,
+		t_strconcat(ibox->index->mailbox_path, "/cur", NULL), TRUE);
 }
 
 static int maildir_storage_lock(struct mailbox *box,
--- a/src/lib-storage/index/mbox/mbox-storage.c	Sun Aug 24 15:43:53 2003 +0300
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Sun Aug 24 15:45:32 2003 +0300
@@ -757,17 +757,24 @@
 }
 
 static void mbox_storage_auto_sync(struct mailbox *box,
-				   enum mailbox_sync_type sync_type,
+				   enum mailbox_sync_flags flags,
 				   unsigned int min_newmail_notify_interval)
 {
 	struct index_mailbox *ibox = (struct index_mailbox *) box;
 
-	ibox->autosync_type = sync_type;
 	ibox->min_newmail_notify_interval = min_newmail_notify_interval;
 
-	index_mailbox_check_remove_all(ibox);
-	if (sync_type != MAILBOX_SYNC_NONE)
-		index_mailbox_check_add(ibox, ibox->index->mailbox_path);
+	if ((ibox->autosync_flags == 0 && flags == 0) ||
+	    (ibox->autosync_flags != 0 && flags != 0)) {
+		/* flags or interval just changed. or nothing. */
+		ibox->autosync_flags = flags;
+	}
+	ibox->autosync_flags = flags;
+
+	if (flags == 0)
+		index_mailbox_check_remove_all(ibox);
+	else
+		index_mailbox_check_add(ibox, ibox->index->mailbox_path, FALSE);
 }
 
 static int mbox_storage_lock(struct mailbox *box,
--- a/src/lib-storage/mail-storage.h	Sun Aug 24 15:43:53 2003 +0300
+++ b/src/lib-storage/mail-storage.h	Sun Aug 24 15:45:32 2003 +0300
@@ -47,12 +47,6 @@
 	MAILBOX_NAME_NOINFERIORS
 };
 
-enum mailbox_sync_type {
-	MAILBOX_SYNC_NONE,
-	MAILBOX_SYNC_ALL,
-	MAILBOX_SYNC_NO_EXPUNGES
-};
-
 enum mailbox_lock_type {
 	MAILBOX_LOCK_UNLOCK	= 0x00,
 	MAILBOX_LOCK_READ	= 0x01,
@@ -101,9 +95,11 @@
 	MAIL_FETCH_IMAP_ENVELOPE	= 0x4000
 };
 
-enum mail_sync_flags {
-	MAIL_SYNC_FLAG_NO_EXPUNGES	= 0x01,
-	MAIL_SYNC_FLAG_FAST		= 0x02
+enum mailbox_sync_flags {
+	MAILBOX_SYNC_NONE		= 0x00,
+	MAILBOX_SYNC_FULL		= 0x01,
+	MAILBOX_SYNC_FAST		= 0x02,
+	MAILBOX_SYNC_FLAG_NO_EXPUNGES	= 0x04
 };
 
 enum client_workarounds {
@@ -249,11 +245,11 @@
 			  struct mailbox_status *status);
 
 	/* Synchronize the mailbox. */
-	int (*sync)(struct mailbox *box, enum mail_sync_flags flags);
+	int (*sync)(struct mailbox *box, enum mailbox_sync_flags flags);
 
 	/* Synchronize mailbox in background. It's done until this function is
-	   called with sync_type = MAILBOX_SYNC_NONE */
-	void (*auto_sync)(struct mailbox *box, enum mailbox_sync_type sync_type,
+	   called with flags = MAILBOX_SYNC_NONE. */
+	void (*auto_sync)(struct mailbox *box, enum mailbox_sync_flags flags,
 			  unsigned int min_newmail_notify_interval);
 
 	/* Initialize new fetch request. wanted_fields isn't required, but it
--- a/src/lib-storage/proxy-mailbox.c	Sun Aug 24 15:43:53 2003 +0300
+++ b/src/lib-storage/proxy-mailbox.c	Sun Aug 24 15:45:32 2003 +0300
@@ -39,19 +39,19 @@
 	return p->box->get_status(p->box, items, status);
 }
 
-static int _sync(struct mailbox *box, enum mail_sync_flags flags)
+static int _sync(struct mailbox *box, enum mailbox_sync_flags flags)
 {
 	struct proxy_mailbox *p = (struct proxy_mailbox *) box;
 
 	return p->box->sync(p->box, flags);
 }
 
-static void _auto_sync(struct mailbox *box, enum mailbox_sync_type sync_type,
+static void _auto_sync(struct mailbox *box, enum mailbox_sync_flags flags,
 		       unsigned int min_newmail_notify_interval)
 {
 	struct proxy_mailbox *p = (struct proxy_mailbox *) box;
 
-	p->box->auto_sync(p->box, sync_type, min_newmail_notify_interval);
+	p->box->auto_sync(p->box, flags, min_newmail_notify_interval);
 }
 
 static struct mail_fetch_context *