dovecot: Moved fdatasync_path() to a global function.

dovecot at dovecot.org dovecot at dovecot.org
Tue Mar 4 06:28:17 EET 2008


details:   http://hg.dovecot.org/dovecot/rev/aaeae4a920f7
changeset: 7324:aaeae4a920f7
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Mar 04 03:47:57 2008 +0200
description:
Moved fdatasync_path() to a global function.

diffstat:

24 files changed, 510 insertions(+), 201 deletions(-)
src/lib-index/mail-index-view-sync.c         |    2 
src/lib-index/mail-index.h                   |   11 +
src/lib-storage/index/dbox/dbox-file.c       |  118 +++++++++++++++++
src/lib-storage/index/dbox/dbox-file.h       |    4 
src/lib-storage/index/dbox/dbox-mail.c       |    5 
src/lib-storage/index/dbox/dbox-storage.c    |   13 +
src/lib-storage/index/dbox/dbox-storage.h    |    3 
src/lib-storage/index/dbox/dbox-sync-file.c  |   33 ++++
src/lib-storage/index/dbox/dbox-sync.c       |   27 +++-
src/lib-storage/index/index-mail.c           |    6 
src/lib-storage/index/maildir/maildir-save.c |   28 +---
src/lib/Makefile.am                          |    2 
src/lib/fdatasync-path.c                     |   22 +++
src/lib/fdatasync-path.h                     |    7 +
src/master/child-process.c                   |    9 +
src/master/child-process.h                   |    1 
src/master/mail-process.c                    |   14 +-
src/master/mail-process.h                    |    4 
src/master/main.c                            |   12 -
src/plugins/expire/Makefile.am               |    1 
src/plugins/expire/expire-env.c              |   83 ++++++++++--
src/plugins/expire/expire-env.h              |   14 --
src/plugins/expire/expire-plugin.c           |  120 +++++++-----------
src/plugins/expire/expire-tool.c             |  172 ++++++++++++++++++--------

diffs (truncated from 1389 to 300 lines):

diff -r 028939047ffb -r aaeae4a920f7 src/lib-index/mail-index-view-sync.c
--- a/src/lib-index/mail-index-view-sync.c	Mon Mar 03 08:59:10 2008 +0200
+++ b/src/lib-index/mail-index-view-sync.c	Tue Mar 04 03:47:57 2008 +0200
@@ -502,7 +502,7 @@ mail_index_view_sync_get_next_transactio
 
 #define FLAG_UPDATE_IS_INTERNAL(u) \
 	((((u)->add_flags | (u)->remove_flags) & \
-	  ~MAIL_INDEX_MAIL_FLAG_DIRTY) == 0)
+	  MAIL_INDEX_FLAGS_MASK) == 0)
 
 static bool
 mail_index_view_sync_get_rec(struct mail_index_view_sync_ctx *ctx,
diff -r 028939047ffb -r aaeae4a920f7 src/lib-index/mail-index.h
--- a/src/lib-index/mail-index.h	Mon Mar 03 08:59:10 2008 +0200
+++ b/src/lib-index/mail-index.h	Tue Mar 04 03:47:57 2008 +0200
@@ -36,7 +36,10 @@ enum mail_index_header_flag {
 };
 
 enum mail_index_mail_flags {
-	MAIL_INDEX_MAIL_FLAG_DIRTY = 0x80
+	/* For private use by backend. Replacing flags doesn't change this. */
+	MAIL_INDEX_MAIL_FLAG_BACKEND	= 0x40,
+	/* Message flags haven't been written to backend */
+	MAIL_INDEX_MAIL_FLAG_DIRTY	= 0x80
 };
 
 #define MAIL_INDEX_FLAGS_MASK \
@@ -245,9 +248,9 @@ mail_index_transaction_open_updated_view
    Changes done to the returned transaction are expected to describe the
    mailbox's current state.
 
-   The returned view already contains all the changes, so if e.g. a record's
-   flags are different in view than in the mailbox you can assume that they
-   were changed externally, and you need to update the index.
+   The returned view already contains all the changes (except expunge
+   requests). After applying sync records on top of backend flags they should
+   match flags in the view. If they don't, there have been external changes.
 
    Returned expunges are treated as expunge requests. They're not really
    removed from the index until you mark them expunged to the returned
diff -r 028939047ffb -r aaeae4a920f7 src/lib-storage/index/dbox/dbox-file.c
--- a/src/lib-storage/index/dbox/dbox-file.c	Mon Mar 03 08:59:10 2008 +0200
+++ b/src/lib-storage/index/dbox/dbox-file.c	Tue Mar 04 03:47:57 2008 +0200
@@ -7,6 +7,8 @@
 #include "hostpid.h"
 #include "istream.h"
 #include "ostream.h"
+#include "mkdir-parents.h"
+#include "fdatasync-path.h"
 #include "write-full.h"
 #include "str.h"
 #include "dbox-storage.h"
@@ -375,6 +377,7 @@ static int dbox_file_open_fd(struct dbox
 static int dbox_file_open_fd(struct dbox_file *file)
 {
 	const char *path;
+	bool alt = FALSE;
 	int i;
 
 	/* try the primary path first */
@@ -398,7 +401,11 @@ static int dbox_file_open_fd(struct dbox
 		/* try the alternative path */
 		path = t_strdup_printf("%s/%s", file->mbox->alt_path,
 				       file->fname);
-	}
+		alt = TRUE;
+	}
+	i_free(file->current_path);
+	file->current_path = i_strdup(path);
+	file->alt_path = alt;
 	return 1;
 }
 
@@ -1015,7 +1022,7 @@ static int dbox_file_grow_metadata(struc
 	} else {
 		i_error("%s: Metadata changed unexpectedly",
 			dbox_file_get_path(file));
-		ret = 0;
+		ret = -1;
 	}
 
 	dbox_index_unlock_file(file->mbox->dbox_index, file->file_id);
@@ -1199,6 +1206,113 @@ bool dbox_file_lookup(struct dbox_mailbo
 	return TRUE;
 }
 
+int dbox_file_move(struct dbox_file *file, bool alt_path)
+{
+	struct ostream *output;
+	const char *dest_dir, *temp_path, *dest_path;
+	struct stat st;
+	bool deleted;
+	int out_fd, ret = 0;
+
+	i_assert(file->input != NULL);
+
+	if (file->alt_path == alt_path)
+		return 0;
+
+	if (stat(file->current_path, &st) < 0 && errno == ENOENT) {
+		/* already expunged by another session */
+		return 0;
+	}
+
+	dest_dir = alt_path ? file->mbox->alt_path : file->mbox->path;
+	temp_path = t_strdup_printf("%s/%s", dest_dir,
+				    dbox_generate_tmp_filename());
+
+	/* first copy the file. make sure to catch every possible error
+	   since we really don't want to break the file. */
+	out_fd = open(temp_path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+	if (out_fd == -1 && errno == ENOENT) {
+		if (mkdir_parents(dest_dir, 0700) < 0) {
+			i_error("mkdir_parents(%s) failed: %m", dest_dir);
+			return -1;
+		}
+		out_fd = open(temp_path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+	}
+	if (out_fd == -1) {
+		i_error("open(%s, O_CREAT) failed: %m", temp_path);
+		return -1;
+	}
+	output = o_stream_create_fd_file(out_fd, 0, FALSE);
+	i_stream_seek(file->input, 0);
+	while ((ret = o_stream_send_istream(output, file->input)) > 0) ;
+	if (ret == 0)
+		ret = o_stream_flush(output);
+	if (output->stream_errno != 0) {
+		errno = output->stream_errno;
+		i_error("write(%s) failed: %m", temp_path);
+		ret = -1;
+	} else if (file->input->stream_errno != 0) {
+		errno = file->input->stream_errno;
+		i_error("read(%s) failed: %m", file->current_path);
+		ret = -1;
+	} else if (ret < 0) {
+		i_error("o_stream_send_istream(%s, %s) "
+			"failed with unknown error",
+			temp_path, file->current_path);
+	}
+	o_stream_unref(&output);
+
+	if (!file->mbox->ibox.fsync_disable && ret == 0) {
+		if (fsync(out_fd) < 0) {
+			i_error("fsync(%s) failed: %m", temp_path);
+			ret = -1;
+		}
+	}
+	if (close(out_fd) < 0) {
+		i_error("close(%s) failed: %m", temp_path);
+		ret = -1;
+	}
+	if (ret < 0) {
+		(void)unlink(temp_path);
+		return -1;
+	}
+
+	/* the temp file was successfully written. rename it now to the
+	   destination file. the destination shouldn't exist, but if it does
+	   its contents should be the same (except for maybe older metadata) */
+	dest_path = t_strdup_printf("%s/%s", dest_dir, file->fname);
+	if (rename(temp_path, dest_path) < 0) {
+		i_error("rename(%s, %s) failed: %m", temp_path, dest_path);
+		(void)unlink(temp_path);
+		return -1;
+	}
+	if (!file->mbox->ibox.fsync_disable) {
+		if (fdatasync_path(dest_dir) < 0) {
+			i_error("fdatasync(%s) failed: %m", dest_dir);
+			(void)unlink(dest_path);
+			return -1;
+		}
+	}
+	if (unlink(file->current_path) < 0) {
+		i_error("unlink(%s) failed: %m", file->current_path);
+		if (errno == EACCES) {
+			/* configuration problem? revert the write */
+			(void)unlink(dest_path);
+		}
+		/* who knows what happened to the file. keep both just to be
+		   sure both won't get deleted. */
+		return -1;
+	}
+
+	/* file was successfully moved - reopen it */
+	dbox_file_close(file);
+	if (dbox_file_open(file, TRUE, &deleted) <= 0) {
+		i_error("dbox_file_move(%s): reopening file failed", dest_path);
+		return -1;
+	}
+	return 0;
+}
+
 void dbox_mail_metadata_flags_append(string_t *str, enum mail_flags flags)
 {
 	unsigned int i;
diff -r 028939047ffb -r aaeae4a920f7 src/lib-storage/index/dbox/dbox-file.h
--- a/src/lib-storage/index/dbox/dbox-file.h	Mon Mar 03 08:59:10 2008 +0200
+++ b/src/lib-storage/index/dbox/dbox-file.h	Tue Mar 04 03:47:57 2008 +0200
@@ -128,6 +128,7 @@ struct dbox_file {
 	/* Includes the trailing LF that shouldn't be used */
 	unsigned int metadata_len;
 
+	unsigned int alt_path:1;
 	unsigned int maildir_file:1;
 	unsigned int nonappendable:1;
 	unsigned int deleted:1;
@@ -217,6 +218,9 @@ bool dbox_file_lookup(struct dbox_mailbo
 bool dbox_file_lookup(struct dbox_mailbox *mbox, struct mail_index_view *view,
 		      uint32_t seq, uint32_t *file_id_r, uoff_t *offset_r);
 
+/* Move the file to alt path or back. */
+int dbox_file_move(struct dbox_file *file, bool alt_path);
+
 /* Append flags as metadata value to given string */
 void dbox_mail_metadata_flags_append(string_t *str, enum mail_flags flags);
 /* Append keywords as metadata value to given string */
diff -r 028939047ffb -r aaeae4a920f7 src/lib-storage/index/dbox/dbox-mail.c
--- a/src/lib-storage/index/dbox/dbox-mail.c	Mon Mar 03 08:59:10 2008 +0200
+++ b/src/lib-storage/index/dbox/dbox-mail.c	Tue Mar 04 03:47:57 2008 +0200
@@ -1,6 +1,7 @@
 /* Copyright (c) 2007-2008 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
+#include "ioloop.h"
 #include "istream.h"
 #include "index-mail.h"
 #include "dbox-storage.h"
@@ -119,7 +120,9 @@ static int dbox_mail_get_save_date(struc
 
 	value = dbox_file_metadata_get(file, DBOX_METADATA_SAVE_TIME);
 	data->save_date = value == NULL ? 0 : strtoul(value, NULL, 16);
-	*date_r = data->save_date;
+	/* if the time is missing or corrupted, use the current time and
+	   cache it */
+	*date_r = data->save_date == 0 ? ioloop_time : data->save_date;
 	return 0;
 }
 
diff -r 028939047ffb -r aaeae4a920f7 src/lib-storage/index/dbox/dbox-storage.c
--- a/src/lib-storage/index/dbox/dbox-storage.c	Mon Mar 03 08:59:10 2008 +0200
+++ b/src/lib-storage/index/dbox/dbox-storage.c	Tue Mar 04 03:47:57 2008 +0200
@@ -151,16 +151,21 @@ static const char *
 static const char *
 dbox_get_alt_path(struct dbox_storage *storage, const char *path)
 {
+	const char *root;
 	unsigned int len;
 
 	if (storage->alt_dir == NULL)
 		return NULL;
 
-	len = strlen(storage->alt_dir);
-	if (strncmp(path, storage->alt_dir, len) != 0)
-		return t_strconcat(storage->alt_dir, path + len, NULL);
-	else
+	root = mailbox_list_get_path(storage->storage.list, NULL,
+				     MAILBOX_LIST_PATH_TYPE_DIR);
+
+	len = strlen(root);
+	if (strncmp(path, root, len) != 0 && path[len] == '/') {
+		/* can't determine the alt path - shouldn't happen */
 		return NULL;
+	}
+	return t_strconcat(storage->alt_dir, path + len, NULL);
 }
 
 static struct mailbox *
diff -r 028939047ffb -r aaeae4a920f7 src/lib-storage/index/dbox/dbox-storage.h
--- a/src/lib-storage/index/dbox/dbox-storage.h	Mon Mar 03 08:59:10 2008 +0200
+++ b/src/lib-storage/index/dbox/dbox-storage.h	Tue Mar 04 03:47:57 2008 +0200
@@ -25,6 +25,9 @@
 #define DBOX_DEFAULT_ROTATE_MIN_SIZE (1024*16)
 #define DBOX_DEFAULT_ROTATE_DAYS 0
 #define DBOX_DEFAULT_MAX_OPEN_FILES 64
+
+/* Flag specifies if the message should be in primary or alternative storage */
+#define DBOX_INDEX_FLAG_ALT MAIL_INDEX_MAIL_FLAG_BACKEND
 
 struct dbox_index_header {
 	uint32_t last_dirty_flush_stamp;
diff -r 028939047ffb -r aaeae4a920f7 src/lib-storage/index/dbox/dbox-sync-file.c
--- a/src/lib-storage/index/dbox/dbox-sync-file.c	Mon Mar 03 08:59:10 2008 +0200
+++ b/src/lib-storage/index/dbox/dbox-sync-file.c	Tue Mar 04 03:47:57 2008 +0200
@@ -324,9 +324,9 @@ dbox_sync_file_int(struct dbox_sync_cont
 		first_expunge_seq = (uint32_t)-1;
 	}
 
-	if (array_is_created(&entry->changes))
+	if (array_is_created(&entry->changes)) {
 		seqs = array_get(&entry->changes, &count);
-	else {
+	} else {
 		seqs = NULL;
 		count = 0;
 	}
@@ -344,6 +344,31 @@ dbox_sync_file_int(struct dbox_sync_cont
 	if (first_expunge_seq != (uint32_t)-1)
 		return dbox_sync_file_expunge(ctx, file, entry);
 	return 1;


More information about the dovecot-cvs mailing list