[dovecot-cvs] dovecot/src/lib-storage/index/mbox mbox-expunge.c,1.16,1.17 mbox-save.c,1.19,1.20 mbox-storage.c,1.14,1.15 mbox-storage.h,1.6,1.7

cras at procontrol.fi cras at procontrol.fi
Sat Oct 26 23:38:39 EEST 2002


Update of /home/cvs/dovecot/src/lib-storage/index/mbox
In directory danu:/tmp/cvs-serv5075/lib-storage/index/mbox

Modified Files:
	mbox-expunge.c mbox-save.c mbox-storage.c mbox-storage.h 
Log Message:
mbox locking fixes / changes. we now read-lock the mbox file before syncing
so we can be sure no-one corrupts our reads by expunging mailbox. mbox file
is kept open all the time, but re-opened when device/inode for file has
changed (ie. someone overwrote it). File is also kept mmap()ed until lock is
dropped.

we currently create .lock file even when reading the file (ie. being
effectively write-lock), but that'll be made configurable later.



Index: mbox-expunge.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-expunge.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- mbox-expunge.c	19 Oct 2002 23:09:56 -0000	1.16
+++ mbox-expunge.c	26 Oct 2002 19:38:37 -0000	1.17
@@ -114,14 +114,14 @@
 		return TRUE;
 	}
 
-	inbuf = mbox_file_open(ibox->index, 0, TRUE);
+	/* mbox must be already opened, synced and locked at this point.
+	   we just want the IBuffer. */
+	inbuf = mbox_get_inbuf(ibox->index, 0, MAIL_LOCK_EXCLUSIVE);
 	if (inbuf == NULL)
 		return FALSE;
 
-	if (!mbox_lock_write(ibox->index)) {
-		i_buffer_unref(inbuf);
-		return FALSE;
-	}
+	i_assert(ibox->index->mbox_sync_counter ==
+		 ibox->index->mbox_lock_counter);
 
 	t_push();
 	outbuf = o_buffer_create_file(ibox->index->mbox_fd, data_stack_pool,
@@ -142,9 +142,20 @@
 		failed = TRUE;
 	}
 
-	(void)mbox_unlock(ibox->index);
 	o_buffer_unref(outbuf);
 	t_pop();
 
 	return !failed;
+}
+
+int mbox_storage_expunge(Mailbox *box, int notify)
+{
+	IndexMailbox *ibox = (IndexMailbox *) box;
+	int ret;
+
+	ibox->index->mbox_lock_next_sync = MAIL_LOCK_EXCLUSIVE;
+	ret = index_storage_expunge(box, notify);
+	(void)mbox_unlock(ibox->index);
+
+	return ret;
 }

Index: mbox-save.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-save.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- mbox-save.c	24 Oct 2002 00:15:39 -0000	1.19
+++ mbox-save.c	26 Oct 2002 19:38:37 -0000	1.20
@@ -2,7 +2,6 @@
 
 #include "lib.h"
 #include "hostpid.h"
-#include "ibuffer.h"
 #include "obuffer.h"
 #include "write-full.h"
 #include "mbox-index.h"
@@ -12,53 +11,65 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <sys/stat.h>
 #include <netdb.h>
 
 static char my_hostdomain[256] = "";
 
-static int set_error(MailStorage *storage, const char *mbox_path)
+static int write_error(MailStorage *storage, const char *mbox_path)
 {
 	if (errno == ENOSPC)
 		mail_storage_set_error(storage, "Not enough disk space");
 	else {
-		mail_storage_set_critical(storage, "Error writing to "
-					  "mbox file %s: %m", mbox_path);
+		mail_storage_set_critical(storage,
+			"Error writing to mbox file %s: %m", mbox_path);
 	}
 
 	return FALSE;
 }
 
-static int mbox_check_ending_lf(MailStorage *storage, int fd, off_t pos,
-				const char *mbox_path)
+static int mbox_seek_to_end(MailStorage *storage, int fd,
+			    const char *mbox_path, off_t *pos)
 {
+	struct stat st;
 	char ch;
 
-	if (pos == 0)
-		return TRUE;
+	if (fstat(fd, &st) < 0) {
+		mail_storage_set_critical(storage,
+			"fstat() failed for mbox file %s: %m", mbox_path);
+		return FALSE;
+	}
 
-	do {
-		if (lseek(fd, pos-1, SEEK_SET) < 0)
-			break;
+	*pos = st.st_size;
+	if (st.st_size == 0)
+		return TRUE;
 
-		if (read(fd, &ch, 1) != 1)
-			break;
+	if (lseek(fd, st.st_size-1, SEEK_SET) < 0) {
+		mail_storage_set_critical(storage,
+			"lseek() failed for mbox file %s: %m", mbox_path);
+		return FALSE;
+	}
 
-		if (ch != '\n') {
-			if (write_full(fd, "\n", 1) < 0)
-				break;
-		}
+	if (read(fd, &ch, 1) != 1) {
+		mail_storage_set_critical(storage,
+			"read() failed for mbox file %s: %m", mbox_path);
+		return FALSE;
+	}
 
-		return TRUE;
-	} while (0);
+	if (ch != '\n') {
+		if (write_full(fd, "\n", 1) < 0)
+			return write_error(storage, mbox_path);
+		*pos += 1;
+	}
 
-	return set_error(storage, mbox_path);
+	return TRUE;
 }
 
 static int mbox_append_lf(MailStorage *storage, OBuffer *outbuf,
 			  const char *mbox_path)
 {
 	if (o_buffer_send(outbuf, "\n", 1) < 0)
-		return set_error(storage, mbox_path);
+		return write_error(storage, mbox_path);
 
 	return TRUE;
 }
@@ -92,7 +103,7 @@
 	len = strlen(line);
 
 	if (o_buffer_send(outbuf, line, len) < 0)
-		return set_error(storage, mbox_path);
+		return write_error(storage, mbox_path);
 
 	return TRUE;
 }
@@ -110,7 +121,7 @@
 
 	if (flags & MAIL_SEEN) {
 		if (o_buffer_send(outbuf, "Status: R\n", 10) < 0)
-			return set_error(storage, mbox_path);
+			return write_error(storage, mbox_path);
 	}
 
 	if (flags & (MAIL_ANSWERED|MAIL_DRAFT|MAIL_FLAGGED|MAIL_DELETED)) {
@@ -122,27 +133,27 @@
 				  "\n", NULL);
 
 		if (o_buffer_send(outbuf, str, strlen(str)) < 0)
-			return set_error(storage, mbox_path);
+			return write_error(storage, mbox_path);
 	}
 
 	if (flags & MAIL_CUSTOM_FLAGS_MASK) {
 		if (o_buffer_send(outbuf, "X-Keywords:", 11) < 0)
-			return set_error(storage, mbox_path);
+			return write_error(storage, mbox_path);
 
 		field = 1 << MAIL_CUSTOM_FLAG_1_BIT;
 		for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++, field <<= 1) {
 			if ((flags & field) && custom_flags[i] != NULL) {
 				if (o_buffer_send(outbuf, " ", 1) < 0)
-					return set_error(storage, mbox_path);
+					return write_error(storage, mbox_path);
 
 				if (o_buffer_send(outbuf, custom_flags[i],
 						  strlen(custom_flags[i])) < 0)
-					return set_error(storage, mbox_path);
+					return write_error(storage, mbox_path);
 			}
 		}
 
 		if (o_buffer_send(outbuf, "\n", 1) < 0)
-			return set_error(storage, mbox_path);
+			return write_error(storage, mbox_path);
 	}
 
 	return TRUE;
@@ -153,11 +164,11 @@
 		      IBuffer *data, uoff_t data_size)
 {
 	IndexMailbox *ibox = (IndexMailbox *) box;
+	MailIndex *index;
 	MailFlags real_flags;
 	const char *mbox_path;
-	IBuffer *inbuf;
 	OBuffer *outbuf;
-	int fd, failed;
+	int failed;
 	off_t pos;
 
 	if (box->readonly) {
@@ -171,31 +182,19 @@
 	if (!index_mailbox_fix_custom_flags(ibox, &real_flags, custom_flags))
 		return FALSE;
 
-	/* just make sure the mbox is opened, we don't need the ibuffer */
-	inbuf = mbox_file_open(ibox->index, 0, TRUE);
-	if (inbuf == NULL)
+	index = ibox->index;
+	if (!mbox_lock(index, MAIL_LOCK_EXCLUSIVE))
 		return FALSE;
 
-	i_buffer_unref(inbuf);
-	fd = ibox->index->mbox_fd;
-
-	if (!mbox_lock_write(ibox->index)) {
-		(void)close(fd);
-		return mail_storage_set_index_error(ibox);
-	}
-
-	failed = FALSE;
-
-	mbox_path = ibox->index->mbox_path;
-	pos = lseek(fd, 0, SEEK_END);
-	if (pos < 0) {
-		mail_storage_set_critical(box->storage,
-					  "lseek() failed for mbox file %s: %m",
-					  mbox_path);
+	mbox_path = index->mbox_path;
+	if (!mbox_seek_to_end(box->storage, index->mbox_fd, mbox_path, &pos))
 		failed = TRUE;
-	} else if (mbox_check_ending_lf(box->storage, fd, pos, mbox_path)) {
+	else {
+		failed = FALSE;
+
 		t_push();
-		outbuf = o_buffer_create_file(fd, data_stack_pool, 4096,
+		outbuf = o_buffer_create_file(index->mbox_fd,
+					      data_stack_pool, 4096,
 					      IO_PRIORITY_DEFAULT, FALSE);
 
 		if (!write_from_line(box->storage, outbuf, mbox_path,
@@ -206,13 +205,13 @@
 					data, outbuf, data_size) ||
 		    !mbox_append_lf(box->storage, outbuf, mbox_path)) {
 			/* failed, truncate file back to original size */
-			(void)ftruncate(fd, pos);
+			(void)ftruncate(index->mbox_fd, pos);
 			failed = TRUE;
 		}
 		o_buffer_unref(outbuf);
 		t_pop();
 	}
 
-	(void)mbox_unlock(ibox->index);
+	(void)mbox_unlock(index);
 	return !failed;
 }

Index: mbox-storage.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-storage.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- mbox-storage.c	19 Oct 2002 14:51:59 -0000	1.14
+++ mbox-storage.c	26 Oct 2002 19:38:37 -0000	1.15
@@ -5,6 +5,7 @@
 #include "subscription-file/subscription-file.h"
 #include "mail-custom-flags.h"
 #include "mbox-index.h"
+#include "mbox-lock.h"
 #include "mbox-storage.h"
 
 #include <stdio.h>
@@ -386,6 +387,32 @@
 	index_storage_close(box);
 }
 
+static int mbox_storage_fetch(Mailbox *box, MailFetchData *fetch_data,
+			      OBuffer *outbuf, int *all_found)
+{
+	IndexMailbox *ibox = (IndexMailbox *) box;
+	int ret;
+
+	ibox->index->mbox_lock_next_sync = MAIL_LOCK_SHARED;
+	ret = index_storage_fetch(box, fetch_data, outbuf, all_found);
+	(void)mbox_unlock(ibox->index);
+
+ 	return ret;
+}
+
+static int mbox_storage_search(Mailbox *box, MailSearchArg *args,
+			       OBuffer *outbuf, int uid_result)
+{
+	IndexMailbox *ibox = (IndexMailbox *) box;
+	int ret;
+
+	ibox->index->mbox_lock_next_sync = MAIL_LOCK_SHARED;
+	ret = index_storage_search(box, args, outbuf, uid_result);
+	(void)mbox_unlock(ibox->index);
+
+ 	return ret;
+}
+
 MailStorage mbox_storage = {
 	"mbox", /* name */
 
@@ -417,11 +444,11 @@
 	index_storage_set_sync_callbacks,
 	index_storage_get_status,
 	index_storage_sync,
-	index_storage_expunge,
+	mbox_storage_expunge,
 	index_storage_update_flags,
 	index_storage_copy,
-	index_storage_fetch,
-	index_storage_search,
+	mbox_storage_fetch,
+	mbox_storage_search,
 	mbox_storage_save,
 	mail_storage_is_inconsistency_error,
 

Index: mbox-storage.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-storage.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- mbox-storage.h	24 Oct 2002 00:15:39 -0000	1.6
+++ mbox-storage.h	26 Oct 2002 19:38:37 -0000	1.7
@@ -14,6 +14,7 @@
 int mbox_find_subscribed(MailStorage *storage, const char *mask,
 			 MailboxFunc func, void *context);
 
+int mbox_storage_expunge(Mailbox *box, int notify);
 int mbox_expunge_locked(IndexMailbox *ibox, int notify);
 
 #endif




More information about the dovecot-cvs mailing list