changeset 472:2fa0bfb65268 HEAD

Added setting mail_save_crlf. Few other settings cleanups.
author Timo Sirainen <tss@iki.fi>
date Mon, 21 Oct 2002 03:09:29 +0300
parents 3448c77bb3d2
children cb7f34709d2d
files doc/configuration.txt dovecot-example.conf src/lib-index/maildir/maildir-sync.c src/lib-index/mbox/mbox-index.c src/lib-storage/index/index-save.c src/lib-storage/index/index-storage.h src/lib-storage/index/maildir/maildir-copy.c src/lib-storage/index/maildir/maildir-save.c src/lib-storage/index/mbox/mbox-save.c src/master/imap-process.c src/master/settings.c src/master/settings.h
diffstat 12 files changed, 137 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/doc/configuration.txt	Mon Oct 21 03:08:03 2002 +0300
+++ b/doc/configuration.txt	Mon Oct 21 03:09:29 2002 +0300
@@ -82,7 +82,7 @@
 sending mails. With Linux and FreeBSD Dovecot can use sendfile() syscall to
 send such mails. However extra CRs do increase the mail size, meaning more
 I/O and potentially losing the gained performance. You can enable this for
-mails saved by Dovecot by setting mail_save_crs = yes. For mails saved by
+mails saved by Dovecot by setting mail_save_crlf = yes. For mails saved by
 your mailer you'll need to do something else, not yet covered by this
 documentation.
 
--- a/dovecot-example.conf	Mon Oct 21 03:08:03 2002 +0300
+++ b/dovecot-example.conf	Mon Oct 21 03:09:29 2002 +0300
@@ -121,6 +121,11 @@
 # needed.
 #mail_never_cache_fields = 
 
+# Save mails with CR+LF instead of plain LF. This makes sending those mails
+# take less CPU, especially with sendfile() syscall with Linux and FreeBSD.
+# But it also creates a bit more disk I/O which may just make it slower.
+#mail_save_crlf = no
+
 # Copy mail to another folders using hard links. This is much faster than
 # actually copying the file. Only problem with it is that if either of the
 # mails are modified directly both will change. This isn't a problem with
--- a/src/lib-index/maildir/maildir-sync.c	Mon Oct 21 03:08:03 2002 +0300
+++ b/src/lib-index/maildir/maildir-sync.c	Mon Oct 21 03:09:29 2002 +0300
@@ -230,7 +230,7 @@
 
 	/* Do we want to check changes in file contents? This slows down
 	   things as we need to do extra stat() for all files. */
-	check_content_changes = getenv("CHECK_CONTENT_CHANGES") != NULL;
+	check_content_changes = getenv("MAILDIR_CHECK_CONTENT_CHANGES") != NULL;
 
 	/* now walk through the index syncing and expunging existing mails */
 	failed = !maildir_index_sync_files(index, dir, files,
--- a/src/lib-index/mbox/mbox-index.c	Mon Oct 21 03:08:03 2002 +0300
+++ b/src/lib-index/mbox/mbox-index.c	Mon Oct 21 03:09:29 2002 +0300
@@ -484,6 +484,11 @@
 	const unsigned char *data;
 	size_t size;
 
+	if (end_offset > inbuf->v_size) {
+		/* missing data */
+		return FALSE;
+	}
+
 	/* don't bother parsing the whole body, just make
 	   sure it ends properly */
 	i_buffer_seek(inbuf, end_offset);
--- a/src/lib-storage/index/index-save.c	Mon Oct 21 03:08:03 2002 +0300
+++ b/src/lib-storage/index/index-save.c	Mon Oct 21 03:09:29 2002 +0300
@@ -2,78 +2,117 @@
 
 #include "lib.h"
 #include "ibuffer.h"
+#include "obuffer.h"
 #include "write-full.h"
 #include "index-storage.h"
 
 #include <stdlib.h>
 #include <unistd.h>
 
-static int write_with_crlf(int fd, const unsigned char *data,
-			   size_t size, int *last_cr)
+static int write_with_crlf(OBuffer *outbuf, const unsigned char *data,
+			   size_t size)
 {
-	ssize_t i, cr;
+	size_t i, start;
 
-	i_assert(size <= SSIZE_T_MAX);
+	i_assert(size > 0 && size <= SSIZE_T_MAX);
 
-	cr = *last_cr ? -1 : -2;
-	for (i = 0; i < (ssize_t)size; i++) {
-		if (data[i] == '\r')
-			cr = i;
-		else if (data[i] == '\n' && cr != i-1) {
+	start = 0;
+	for (i = 0; i < size; i++) {
+		if (data[i] == '\n' && (i == 0 || data[i-1] != '\r')) {
 			/* missing CR */
-			if (write_full(fd, data, (size_t)i) < 0)
-				return FALSE;
-			if (write_full(fd, "\r", 1) < 0)
-				return FALSE;
+			if (o_buffer_send(outbuf, data + start, i - start) < 0)
+				return -1;
+			if (o_buffer_send(outbuf, "\r", 1) < 0)
+				return -1;
 
-			/* skip the data so far. \n is left into buffer and
-			   we'll continue from the next character. */
-			data += i;
-			size -= i;
-			i = 0; cr = -2;
+			/* \n is written next time */
+			start = i;
 		}
 	}
 
-	return write_full(fd, data, size) >= 0;
+	/* if last char is \r, leave it to buffer */
+	if (data[size-1] == '\r')
+		size--;
+
+	if (o_buffer_send(outbuf, data + start, size - start) < 0)
+		return -1;
+
+	return size;
 }
 
-int index_storage_save_into_fd(MailStorage *storage, int fd, const char *path,
-			       IBuffer *buf, uoff_t data_size)
+static int write_with_lf(OBuffer *outbuf, const unsigned char *data,
+			 size_t size)
 {
+	size_t i, start;
+
+	i_assert(size > 0 && size <= SSIZE_T_MAX);
+
+	start = 0;
+	for (i = 0; i < size; i++) {
+		if (data[i] == '\n' && i > 0 && data[i-1] == '\r') {
+			/* \r\n - skip \r */
+			if (o_buffer_send(outbuf, data + start,
+					   i - start - 1) < 0)
+				return -1;
+
+			/* \n is written next time */
+			start = i;
+		}
+	}
+
+	/* if last char is \r, leave it to buffer */
+	if (data[size-1] == '\r')
+		size--;
+
+	if (o_buffer_send(outbuf, data + start, size - start) < 0)
+		return -1;
+
+	return size;
+}
+
+int index_storage_save(MailStorage *storage, const char *path,
+		       IBuffer *inbuf, OBuffer *outbuf, uoff_t data_size)
+{
+	int (*write_func)(OBuffer *, const unsigned char *, size_t);
 	const unsigned char *data;
 	size_t size;
 	ssize_t ret;
-	int last_cr, failed;
+	int failed;
 
-	last_cr = FALSE;
+	write_func = getenv("MAIL_SAVE_CRLF") ? write_with_crlf : write_with_lf;
 
 	failed = FALSE;
 	while (data_size > 0) {
-		ret = i_buffer_read(buf);
+		ret = i_buffer_read(inbuf);
 		if (ret < 0) {
 			mail_storage_set_critical(storage,
 						  "Error reading mail: %m");
 			return FALSE;
 		}
 
-		data = i_buffer_get_data(buf, &size);
+		data = i_buffer_get_data(inbuf, &size);
 		if (size > data_size)
 			size = (size_t)data_size;
-		data_size -= size;
 
-		if (!failed && !write_with_crlf(fd, data, size, &last_cr)) {
-			if (errno == ENOSPC) {
-				mail_storage_set_error(storage,
-						       "Not enough disk space");
+		if (!failed) {
+			ret = write_func(outbuf, data, size);
+			if (ret < 0) {
+				if (errno == ENOSPC) {
+					mail_storage_set_error(storage,
+						"Not enough disk space");
+				} else {
+					mail_storage_set_critical(storage,
+						"write_full() failed for file "
+						"%s: %m", path);
+				}
+				failed = TRUE;
 			} else {
-				mail_storage_set_critical(storage,
-							  "write() failed for "
-							  "file %s: %m", path);
+				size = ret;
 			}
-			failed = TRUE;
 		}
 
-		i_buffer_skip(buf, size);
+		data_size -= size;
+		i_buffer_skip(inbuf, size);
 	}
 
 	return !failed;
--- a/src/lib-storage/index/index-storage.h	Mon Oct 21 03:08:03 2002 +0300
+++ b/src/lib-storage/index/index-storage.h	Mon Oct 21 03:09:29 2002 +0300
@@ -50,8 +50,8 @@
 int index_expunge_mail(IndexMailbox *ibox, MailIndexRecord *rec,
 		       unsigned int seq, int notify);
 
-int index_storage_save_into_fd(MailStorage *storage, int fd, const char *path,
-			       IBuffer *buf, uoff_t data_size);
+int index_storage_save(MailStorage *storage, const char *path,
+		       IBuffer *inbuf, OBuffer *outbuf, uoff_t data_size);
 
 void *index_msgcache_get_context(MailIndex *index, MailIndexRecord *rec);
 
--- a/src/lib-storage/index/maildir/maildir-copy.c	Mon Oct 21 03:08:03 2002 +0300
+++ b/src/lib-storage/index/maildir/maildir-copy.c	Mon Oct 21 03:09:29 2002 +0300
@@ -95,7 +95,7 @@
 		return FALSE;
 	}
 
-	if (getenv("COPY_WITH_HARDLINKS") != NULL &&
+	if (getenv("MAILDIR_COPY_WITH_HARDLINKS") != NULL &&
 	    destbox->storage == box->storage) {
 		/* both source and destination mailbox are in maildirs and
 		   copy_with_hardlinks option is on, do it */
--- a/src/lib-storage/index/maildir/maildir-save.c	Mon Oct 21 03:08:03 2002 +0300
+++ b/src/lib-storage/index/maildir/maildir-save.c	Mon Oct 21 03:09:29 2002 +0300
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "ioloop.h"
 #include "hostpid.h"
+#include "obuffer.h"
 #include "maildir-index.h"
 #include "maildir-storage.h"
 
@@ -44,20 +45,28 @@
 					 IBuffer *buf, uoff_t data_size)
 {
 	const char *fname, *path;
+	OBuffer *outbuf;
 	int fd;
 
 	fd = maildir_create_tmp(storage, dir, &fname);
 	if (fd == -1)
 		return NULL;
 
+	t_push();
+	outbuf = o_buffer_create_file(fd, data_stack_pool, 4096,
+				      IO_PRIORITY_DEFAULT, FALSE);
+
 	path = t_strconcat(dir, "/", fname, NULL);
-	if (!index_storage_save_into_fd(storage, fd, path, buf, data_size))
+	if (!index_storage_save(storage, path, buf, outbuf, data_size))
 		fname = NULL;
 
-	(void)close(fd);
+	o_buffer_unref(outbuf);
+	if (close(fd) < 0)
+		fname = NULL;
 
 	if (fname == NULL)
 		(void)unlink(path);
+	t_pop();
 	return fname;
 }
 
--- a/src/lib-storage/index/mbox/mbox-save.c	Mon Oct 21 03:08:03 2002 +0300
+++ b/src/lib-storage/index/mbox/mbox-save.c	Mon Oct 21 03:09:29 2002 +0300
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "hostpid.h"
 #include "ibuffer.h"
+#include "obuffer.h"
 #include "write-full.h"
 #include "mbox-index.h"
 #include "mbox-lock.h"
@@ -53,16 +54,17 @@
 	return set_error(storage, mbox_path);
 }
 
-static int mbox_append_lf(MailStorage *storage, int fd, const char *mbox_path)
+static int mbox_append_lf(MailStorage *storage, OBuffer *outbuf,
+			  const char *mbox_path)
 {
-	if (write_full(fd, "\n", 1) < 0)
+	if (o_buffer_send(outbuf, "\n", 1) < 0)
 		return set_error(storage, mbox_path);
 
 	return TRUE;
 }
 
-static int write_from_line(MailStorage *storage, int fd, const char *mbox_path,
-			   time_t internal_date)
+static int write_from_line(MailStorage *storage, OBuffer *outbuf,
+			   const char *mbox_path, time_t internal_date)
 {
 	const char *sender, *line, *name;
 	size_t len;
@@ -88,13 +90,14 @@
 	line = mbox_from_create(sender, internal_date);
 	len = strlen(line);
 
-	if (write_full(fd, line, len) < 0)
+	if (o_buffer_send(outbuf, line, len) < 0)
 		return set_error(storage, mbox_path);
 
 	return TRUE;
 }
 
-static int write_flags(MailStorage *storage, int fd, const char *mbox_path,
+static int write_flags(MailStorage *storage, OBuffer *outbuf,
+		       const char *mbox_path,
 		       MailFlags flags, const char *custom_flags[])
 {
 	const char *str;
@@ -105,7 +108,7 @@
 		return TRUE;
 
 	if (flags & MAIL_SEEN) {
-		if (write_full(fd, "Status: R\n", 10) < 0)
+		if (o_buffer_send(outbuf, "Status: R\n", 10) < 0)
 			return set_error(storage, mbox_path);
 	}
 
@@ -117,27 +120,27 @@
 				  (flags & MAIL_DELETED) ? "T" : "",
 				  "\n", NULL);
 
-		if (write_full(fd, str, strlen(str)) < 0)
+		if (o_buffer_send(outbuf, str, strlen(str)) < 0)
 			return set_error(storage, mbox_path);
 	}
 
 	if (flags & MAIL_CUSTOM_FLAGS_MASK) {
-		if (write_full(fd, "X-Keywords:", 11) < 0)
+		if (o_buffer_send(outbuf, "X-Keywords:", 11) < 0)
 			return set_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 (write_full(fd, " ", 1) < 0)
+				if (o_buffer_send(outbuf, " ", 1) < 0)
 					return set_error(storage, mbox_path);
 
-				if (write_full(fd, custom_flags[i],
-					       strlen(custom_flags[i])) < 0)
+				if (o_buffer_send(outbuf, custom_flags[i],
+						  strlen(custom_flags[i])) < 0)
 					return set_error(storage, mbox_path);
 			}
 		}
 
-		if (write_full(fd, "\n", 1) < 0)
+		if (o_buffer_send(outbuf, "\n", 1) < 0)
 			return set_error(storage, mbox_path);
 	}
 
@@ -151,6 +154,7 @@
 	MailFlags real_flags;
 	const char *mbox_path;
 	IBuffer *inbuf;
+	OBuffer *outbuf;
 	int fd, failed;
 	off_t pos;
 
@@ -180,27 +184,31 @@
 
 	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",
-					  ibox->index->mbox_path);
+					  mbox_path);
 		failed = TRUE;
-	} else {
-		mbox_path = ibox->index->mbox_path;
+	} else if (mbox_check_ending_lf(box->storage, fd, pos, mbox_path)) {
+		t_push();
+		outbuf = o_buffer_create_file(fd, data_stack_pool, 4096,
+					      IO_PRIORITY_DEFAULT, FALSE);
 
-		if (!mbox_check_ending_lf(box->storage, fd, pos, mbox_path) ||
-		    !write_from_line(box->storage, fd, mbox_path,
+		if (!write_from_line(box->storage, outbuf, mbox_path,
 				     internal_date) ||
-		    !write_flags(box->storage, fd, mbox_path, flags,
+		    !write_flags(box->storage, outbuf, mbox_path, flags,
 				 custom_flags) ||
-		    !index_storage_save_into_fd(box->storage, fd, mbox_path,
-						data, data_size) ||
-		    !mbox_append_lf(box->storage, fd, mbox_path)) {
+		    !index_storage_save(box->storage, mbox_path,
+					data, outbuf, data_size) ||
+		    !mbox_append_lf(box->storage, outbuf, mbox_path)) {
 			/* failed, truncate file back to original size */
 			(void)ftruncate(fd, pos);
 			failed = TRUE;
 		}
+		o_buffer_unref(outbuf);
+		t_pop();
 	}
 
 	(void)mbox_unlock(ibox->index);
--- a/src/master/imap-process.c	Mon Oct 21 03:08:03 2002 +0300
+++ b/src/master/imap-process.c	Mon Oct 21 03:09:29 2002 +0300
@@ -119,10 +119,12 @@
 	putenv((char *) t_strconcat("MAIL_NEVER_CACHE_FIELDS=",
 				    set_mail_never_cache_fields, NULL));
 
+	if (set_mail_save_crlf)
+		putenv("MAIL_SAVE_CRLF=1");
 	if (set_maildir_copy_with_hardlinks)
-		putenv("COPY_WITH_HARDLINKS=1");
+		putenv("MAILDIR_COPY_WITH_HARDLINKS=1");
 	if (set_maildir_check_content_changes)
-		putenv("CHECK_CONTENT_CHANGES=1");
+		putenv("MAILDIR_CHECK_CONTENT_CHANGES=1");
 	if (set_overwrite_incompatible_index)
 		putenv("OVERWRITE_INCOMPATIBLE_INDEX=1");
 	if (umask(set_umask) != set_umask)
--- a/src/master/settings.c	Mon Oct 21 03:08:03 2002 +0300
+++ b/src/master/settings.c	Mon Oct 21 03:09:29 2002 +0300
@@ -52,6 +52,7 @@
 	{ "mail_cache_fields",	SET_STR, &set_mail_cache_fields },
 	{ "mail_never_cache_fields",
 				SET_STR, &set_mail_never_cache_fields },
+	{ "mail_save_crlf",	SET_BOOL,&set_mail_save_crlf },
 	{ "maildir_copy_with_hardlinks",
 				SET_BOOL,&set_maildir_copy_with_hardlinks },
 	{ "maildir_check_content_changes",
@@ -99,6 +100,7 @@
 
 char *set_mail_cache_fields = "MessagePart";
 char *set_mail_never_cache_fields = NULL;
+int set_mail_save_crlf = FALSE;
 int set_maildir_copy_with_hardlinks = FALSE;
 int set_maildir_check_content_changes = FALSE;
 int set_overwrite_incompatible_index = FALSE;
--- a/src/master/settings.h	Mon Oct 21 03:08:03 2002 +0300
+++ b/src/master/settings.h	Mon Oct 21 03:09:29 2002 +0300
@@ -36,6 +36,7 @@
 
 extern char *set_mail_cache_fields;
 extern char *set_mail_never_cache_fields;
+extern int set_mail_save_crlf;
 extern int set_maildir_copy_with_hardlinks;
 extern int set_maildir_check_content_changes;
 extern int set_overwrite_incompatible_index;