dovecot-2.0: sdbox: Copying is now done with hard links.

dovecot at dovecot.org dovecot at dovecot.org
Sun Mar 21 18:12:28 EET 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/1bb98ad1af8b
changeset: 10965:1bb98ad1af8b
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Mar 21 18:12:24 2010 +0200
description:
sdbox: Copying is now done with hard links.

diffstat:

 src/lib-storage/index/dbox-common/dbox-save.h     |   2 +
 src/lib-storage/index/dbox-single/Makefile.am     |   1 +
 src/lib-storage/index/dbox-single/sdbox-copy.c    |  89 ++++++++++++++++++++++
 src/lib-storage/index/dbox-single/sdbox-file.c    |  16 ++-
 src/lib-storage/index/dbox-single/sdbox-file.h    |   1 +
 src/lib-storage/index/dbox-single/sdbox-save.c    |  21 ++---
 src/lib-storage/index/dbox-single/sdbox-storage.h |   1 +
 7 files changed, 113 insertions(+), 18 deletions(-)

diffs (213 lines):

diff -r cc42255736ad -r 1bb98ad1af8b src/lib-storage/index/dbox-common/dbox-save.h
--- a/src/lib-storage/index/dbox-common/dbox-save.h	Sun Mar 21 17:08:36 2010 +0200
+++ b/src/lib-storage/index/dbox-common/dbox-save.h	Sun Mar 21 18:12:24 2010 +0200
@@ -1,6 +1,8 @@
 #ifndef DBOX_SAVE_H
 #define DBOX_SAVE_H
 
+#include "dbox-storage.h"
+
 struct dbox_save_context {
 	struct mail_save_context ctx;
 	struct mail_index_transaction *trans;
diff -r cc42255736ad -r 1bb98ad1af8b src/lib-storage/index/dbox-single/Makefile.am
--- a/src/lib-storage/index/dbox-single/Makefile.am	Sun Mar 21 17:08:36 2010 +0200
+++ b/src/lib-storage/index/dbox-single/Makefile.am	Sun Mar 21 18:12:24 2010 +0200
@@ -11,6 +11,7 @@
 	-I$(top_srcdir)/src/lib-storage/index/dbox-common
 
 libstorage_dbox_single_la_SOURCES = \
+	sdbox-copy.c \
 	sdbox-file.c \
 	sdbox-mail.c \
 	sdbox-save.c \
diff -r cc42255736ad -r 1bb98ad1af8b src/lib-storage/index/dbox-single/sdbox-copy.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-storage/index/dbox-single/sdbox-copy.c	Sun Mar 21 18:12:24 2010 +0200
@@ -0,0 +1,89 @@
+/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "nfs-workarounds.h"
+#include "dbox-save.h"
+#include "sdbox-storage.h"
+#include "sdbox-file.h"
+#include "mail-copy.h"
+
+static int
+sdbox_copy_hardlink(struct mail_save_context *_ctx, struct mail *mail)
+{
+	struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx;
+	struct sdbox_mailbox *dest_mbox =
+		(struct sdbox_mailbox *)_ctx->transaction->box;
+	struct sdbox_mailbox *src_mbox;
+	struct dbox_file *src_file, *dest_file;
+	const char *src_path;
+	int ret;
+
+	if (strcmp(mail->box->storage->name, SDBOX_STORAGE_NAME) == 0)
+		src_mbox = (struct sdbox_mailbox *)mail->box;
+	else {
+		/* Source storage isn't sdbox, can't hard link */
+		return 0;
+	}
+
+	src_file = sdbox_file_init(src_mbox, mail->uid);
+	dest_file = sdbox_file_init(dest_mbox, 0);
+
+	src_path = src_file->primary_path;
+	ret = nfs_safe_link(src_path, dest_file->cur_path, FALSE);
+	if (ret < 0 && errno == ENOENT && src_file->alt_path != NULL) {
+		src_path = src_file->alt_path;
+		ret = nfs_safe_link(src_path, dest_file->cur_path, FALSE);
+	}
+	if (ret < 0) {
+		if (ECANTLINK(errno))
+			return 0;
+
+		if (errno == ENOENT)
+			mail_set_expunged(mail);
+		else {
+			mail_storage_set_critical(
+				_ctx->transaction->box->storage,
+				"link(%s, %s) failed: %m",
+				src_path, dest_file->cur_path);
+		}
+		return -1;
+	}
+
+	dbox_save_add_to_index(ctx);
+	sdbox_save_add_file(_ctx, dest_file);
+	if (_ctx->dest_mail != NULL)
+		mail_set_seq(_ctx->dest_mail, ctx->seq);
+	return 1;
+}
+
+static bool
+sdbox_compatible_file_modes(struct mailbox *box1, struct mailbox *box2)
+{
+	return box1->file_create_mode == box2->file_create_mode &&
+		box1->file_create_gid == box2->file_create_gid;
+}
+
+int sdbox_copy(struct mail_save_context *_ctx, struct mail *mail)
+{
+	struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx;
+	struct mailbox_transaction_context *_t = _ctx->transaction;
+	struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)_t->box;
+	int ret;
+
+	i_assert((_t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
+
+	ctx->finished = TRUE;
+	if (sdbox_compatible_file_modes(&mbox->box, mail->box)) {
+		T_BEGIN {
+			ret = sdbox_copy_hardlink(_ctx, mail);
+		} T_END;
+
+		if (ret != 0) {
+			index_save_context_free(_ctx);
+			return ret > 0 ? 0 : -1;
+		}
+
+		/* non-fatal hardlinking failure, try the slow way */
+	}
+	return mail_storage_copy(_ctx, mail);
+}
diff -r cc42255736ad -r 1bb98ad1af8b src/lib-storage/index/dbox-single/sdbox-file.c
--- a/src/lib-storage/index/dbox-single/sdbox-file.c	Sun Mar 21 17:08:36 2010 +0200
+++ b/src/lib-storage/index/dbox-single/sdbox-file.c	Sun Mar 21 18:12:24 2010 +0200
@@ -45,13 +45,17 @@
 		}
 	} T_END;
 	dbox_file_init(&file->file);
+	return &file->file;
+}
 
-	if (uid == 0) {
-		file->file.fd = file->file.storage->v.
-			file_create_fd(&file->file, file->file.primary_path,
-				       FALSE);
-	}
-	return &file->file;
+struct dbox_file *sdbox_file_create(struct sdbox_mailbox *mbox)
+{
+	struct dbox_file *file;
+
+	file = sdbox_file_init(mbox, 0);
+	file->fd = file->storage->v.
+		file_create_fd(file, file->primary_path, FALSE);
+	return file;
 }
 
 int sdbox_file_assign_uid(struct sdbox_file *file, uint32_t uid)
diff -r cc42255736ad -r 1bb98ad1af8b src/lib-storage/index/dbox-single/sdbox-file.h
--- a/src/lib-storage/index/dbox-single/sdbox-file.h	Sun Mar 21 17:08:36 2010 +0200
+++ b/src/lib-storage/index/dbox-single/sdbox-file.h	Sun Mar 21 18:12:24 2010 +0200
@@ -12,6 +12,7 @@
 };
 
 struct dbox_file *sdbox_file_init(struct sdbox_mailbox *mbox, uint32_t uid);
+struct dbox_file *sdbox_file_create(struct sdbox_mailbox *mbox);
 
 /* Assign UID for a newly created file (by renaming it) */
 int sdbox_file_assign_uid(struct sdbox_file *file, uint32_t uid);
diff -r cc42255736ad -r 1bb98ad1af8b src/lib-storage/index/dbox-single/sdbox-save.c
--- a/src/lib-storage/index/dbox-single/sdbox-save.c	Sun Mar 21 17:08:36 2010 +0200
+++ b/src/lib-storage/index/dbox-single/sdbox-save.c	Sun Mar 21 18:12:24 2010 +0200
@@ -70,13 +70,20 @@
 	return t->save_ctx;
 }
 
+void sdbox_save_add_file(struct mail_save_context *_ctx, struct dbox_file *file)
+{
+	struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
+
+	array_append(&ctx->files, &file, 1);
+}
+
 int sdbox_save_begin(struct mail_save_context *_ctx, struct istream *input)
 {
 	struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
 	struct dbox_file *file;
 	int ret;
 
-	file = sdbox_file_init(ctx->mbox, 0);
+	file = sdbox_file_create(ctx->mbox);
 	ctx->append_ctx = dbox_file_append_init(file);
 	ret = dbox_file_get_append_stream(ctx->append_ctx,
 					  &ctx->ctx.dbox_output);
@@ -93,7 +100,7 @@
 	if (ctx->first_saved_seq == 0)
 		ctx->first_saved_seq = ctx->ctx.seq;
 
-	array_append(&ctx->files, &file, 1);
+	sdbox_save_add_file(_ctx, file);
 	return ctx->ctx.failed ? -1 : 0;
 }
 
@@ -295,13 +302,3 @@
 		mail_free(&ctx->ctx.mail);
 	i_free(ctx);
 }
-
-int sdbox_copy(struct mail_save_context *_ctx, struct mail *mail)
-{
-	struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx;
-
-	/* FIXME: use hard linking */
-
-	ctx->finished = TRUE;
-	return mail_storage_copy(_ctx, mail);
-}
diff -r cc42255736ad -r 1bb98ad1af8b src/lib-storage/index/dbox-single/sdbox-storage.h
--- a/src/lib-storage/index/dbox-single/sdbox-storage.h	Sun Mar 21 17:08:36 2010 +0200
+++ b/src/lib-storage/index/dbox-single/sdbox-storage.h	Sun Mar 21 18:12:24 2010 +0200
@@ -53,6 +53,7 @@
 
 struct dbox_file *
 sdbox_save_file_get_file(struct mailbox_transaction_context *t, uint32_t seq);
+void sdbox_save_add_file(struct mail_save_context *ctx, struct dbox_file *file);
 
 int sdbox_transaction_save_commit_pre(struct mail_save_context *ctx);
 void sdbox_transaction_save_commit_post(struct mail_save_context *ctx,


More information about the dovecot-cvs mailing list