[dovecot-cvs] dovecot: Merge branch: When compressing cache file, update the c...

dovecot at dovecot.org dovecot at dovecot.org
Tue May 22 22:50:11 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/29764126e1a6
changeset: 5654:29764126e1a6
user:      Timo Sirainen <tss at iki.fi>
date:      Tue May 22 22:50:06 2007 +0300
description:
Merge branch: When compressing cache file, update the cache file offsets
using the existing sync transaction.

diffstat:

3 files changed, 73 insertions(+), 46 deletions(-)
src/lib-index/mail-cache-compress.c |   95 +++++++++++++++++++++++------------
src/lib-index/mail-cache.h          |    5 +
src/lib-index/mail-index-sync.c     |   19 ++-----

diffs (264 lines):

diff -r 965e401fcb7b -r 29764126e1a6 src/lib-index/mail-cache-compress.c
--- a/src/lib-index/mail-cache-compress.c	Tue May 22 22:44:50 2007 +0300
+++ b/src/lib-index/mail-cache-compress.c	Tue May 22 22:50:06 2007 +0300
@@ -1,7 +1,7 @@
 /* Copyright (C) 2003-2004 Timo Sirainen */
 
 #include "lib.h"
-#include "buffer.h"
+#include "array.h"
 #include "ostream.h"
 #include "nfs-workarounds.h"
 #include "read-full.h"
@@ -13,6 +13,8 @@
 
 #include <sys/stat.h>
 
+ARRAY_DEFINE_TYPE(ext_offset, uint32_t);
+
 struct mail_cache_copy_context {
 	bool new_msg;
 	buffer_t *buffer, *field_seen;
@@ -113,18 +115,21 @@ get_next_file_seq(struct mail_cache *cac
 }
 
 static int
-mail_cache_copy(struct mail_cache *cache, struct mail_index_view *view, int fd)
+mail_cache_copy(struct mail_cache *cache, struct mail_index_transaction *trans,
+		int fd, uint32_t *file_seq_r,
+		ARRAY_TYPE(ext_offset) *ext_offsets)
 {
         struct mail_cache_copy_context ctx;
+	struct mail_index_view *view;
 	struct mail_cache_view *cache_view;
-	struct mail_index_transaction *t;
 	const struct mail_index_header *idx_hdr;
 	struct mail_cache_header hdr;
 	struct mail_cache_record cache_rec;
 	struct ostream *output;
 	buffer_t *buffer;
-	uint32_t i, message_count, seq, first_new_seq, old_offset;
-	uoff_t offset;
+	uint32_t i, message_count, seq, first_new_seq, ext_offset;
+
+	view = mail_index_transaction_get_view(trans);
 
 	/* get sequence of first message which doesn't need its temp fields
 	   removed. */
@@ -142,7 +147,6 @@ mail_cache_copy(struct mail_cache *cache
 	}
 
 	cache_view = mail_cache_view_open(cache, view);
-	t = mail_index_transaction_begin(view, FALSE, TRUE);
 	output = o_stream_create_file(fd, default_pool, 0, FALSE);
 
 	memset(&hdr, 0, sizeof(hdr));
@@ -157,9 +161,13 @@ mail_cache_copy(struct mail_cache *cache
 	ctx.field_seen = buffer_create_dynamic(default_pool, 64);
 	ctx.field_seen_value = 0;
 
-	mail_index_ext_reset(t, cache->ext_id, hdr.file_seq);
-
+	t_array_init(ext_offsets, message_count);
 	for (seq = 1; seq <= message_count; seq++) {
+		if (mail_index_transaction_is_expunged(trans, seq)) {
+			(void)array_append_space(ext_offsets);
+			continue;
+		}
+
 		ctx.new_msg = seq >= first_new_seq;
 		buffer_set_used_size(ctx.buffer, 0);
 
@@ -176,15 +184,19 @@ mail_cache_copy(struct mail_cache *cache
 					 mail_cache_compress_callback, &ctx);
 
 		cache_rec.size = buffer_get_used_size(ctx.buffer);
-		if (cache_rec.size == sizeof(cache_rec))
-			continue;
-
-		mail_index_update_ext(t, seq, cache->ext_id, &output->offset,
-				      &old_offset);
-
-		buffer_write(ctx.buffer, 0, &cache_rec, sizeof(cache_rec));
-		o_stream_send(output, ctx.buffer->data, cache_rec.size);
-	}
+		if (cache_rec.size == sizeof(cache_rec)) {
+			/* nothing cached */
+			ext_offset = 0;
+		} else {
+			ext_offset = output->offset;
+			buffer_write(ctx.buffer, 0, &cache_rec,
+				     sizeof(cache_rec));
+			o_stream_send(output, ctx.buffer->data, cache_rec.size);
+		}
+
+		array_append(ext_offsets, &ext_offset, 1);
+	}
+	i_assert(array_count(ext_offsets) == message_count);
 
 	if (cache->fields_count != 0) {
 		hdr.field_header_offset =
@@ -217,7 +229,6 @@ mail_cache_copy(struct mail_cache *cache
 	if (o_stream_flush(output) < 0) {
 		errno = output->stream_errno;
 		mail_cache_set_syscall_error(cache, "o_stream_flush()");
-		(void)mail_index_transaction_rollback(&t);
 		o_stream_destroy(&output);
 		return -1;
 	}
@@ -232,12 +243,12 @@ mail_cache_copy(struct mail_cache *cache
 	if (!cache->index->fsync_disable) {
 		if (fdatasync(fd) < 0) {
 			mail_cache_set_syscall_error(cache, "fdatasync()");
-			(void)mail_index_transaction_rollback(&t);
-			return -1;
-		}
-	}
-
-	return mail_index_transaction_commit(&t, &seq, &offset);
+			return -1;
+		}
+	}
+
+	*file_seq_r = hdr.file_seq;
+	return 0;
 }
 
 static int mail_cache_compress_has_file_changed(struct mail_cache *cache)
@@ -275,11 +286,15 @@ static int mail_cache_compress_has_file_
 }
 
 static int mail_cache_compress_locked(struct mail_cache *cache,
-				      struct mail_index_view *view,
+				      struct mail_index_transaction *trans,
 				      bool *unlock)
 {
 	struct dotlock *dotlock;
         mode_t old_mask;
+	uint32_t file_seq, old_offset;
+	ARRAY_TYPE(ext_offset) ext_offsets;
+	const uint32_t *offsets;
+	unsigned int i, count;
 	int fd, ret;
 
 	/* get the latest info on fields */
@@ -319,8 +334,10 @@ static int mail_cache_compress_locked(st
 		return -1;
 	}
 
-	if (mail_cache_copy(cache, view, fd) < 0) {
+	t_push();
+	if (mail_cache_copy(cache, trans, fd, &file_seq, &ext_offsets) < 0) {
 		(void)file_dotlock_delete(&dotlock);
+		t_pop();
 		return -1;
 	}
 
@@ -329,8 +346,21 @@ static int mail_cache_compress_locked(st
 		mail_cache_set_syscall_error(cache,
 					     "file_dotlock_replace()");
 		(void)close(fd);
-		return -1;
-	}
+		t_pop();
+		return -1;
+	}
+
+	/* once we're sure that the compression was successful,
+	   update the offsets */
+	mail_index_ext_reset(trans, cache->ext_id, file_seq);
+	offsets = array_get(&ext_offsets, &count);
+	for (i = 0; i < count; i++) {
+		if (offsets[i] != 0) {
+			mail_index_update_ext(trans, i + 1, cache->ext_id,
+					      &offsets[i], &old_offset);
+		}
+	}
+	t_pop();
 
 	if (*unlock) {
 		(void)mail_cache_unlock(cache);
@@ -352,7 +382,8 @@ static int mail_cache_compress_locked(st
 	return 0;
 }
 
-int mail_cache_compress(struct mail_cache *cache, struct mail_index_view *view)
+int mail_cache_compress(struct mail_cache *cache,
+			struct mail_index_transaction *trans)
 {
 	bool unlock = FALSE;
 	int ret;
@@ -363,7 +394,7 @@ int mail_cache_compress(struct mail_cach
 	if (cache->index->lock_method == FILE_LOCK_METHOD_DOTLOCK) {
 		/* we're using dotlocking, cache file creation itself creates
 		   the dotlock file we need. */
-		return mail_cache_compress_locked(cache, view, &unlock);
+		return mail_cache_compress_locked(cache, trans, &unlock);
 	}
 
 	switch (mail_cache_lock(cache)) {
@@ -372,11 +403,11 @@ int mail_cache_compress(struct mail_cach
 	case 0:
 		/* couldn't lock, either it's broken or doesn't exist.
 		   just start creating it. */
-		return mail_cache_compress_locked(cache, view, &unlock);
+		return mail_cache_compress_locked(cache, trans, &unlock);
 	default:
 		/* locking succeeded. */
 		unlock = TRUE;
-		ret = mail_cache_compress_locked(cache, view, &unlock);
+		ret = mail_cache_compress_locked(cache, trans, &unlock);
 		if (unlock) {
 			if (mail_cache_unlock(cache) < 0)
 				ret = -1;
diff -r 965e401fcb7b -r 29764126e1a6 src/lib-index/mail-cache.h
--- a/src/lib-index/mail-cache.h	Tue May 22 22:44:50 2007 +0300
+++ b/src/lib-index/mail-cache.h	Tue May 22 22:50:06 2007 +0300
@@ -58,8 +58,9 @@ mail_cache_register_get_list(struct mail
 
 /* Returns TRUE if cache should be compressed. */
 bool mail_cache_need_compress(struct mail_cache *cache);
-/* Compress cache file. */
-int mail_cache_compress(struct mail_cache *cache, struct mail_index_view *view);
+/* Compress cache file. Offsets are updated to given transaction. */
+int mail_cache_compress(struct mail_cache *cache,
+			struct mail_index_transaction *trans);
 
 struct mail_cache_view *
 mail_cache_view_open(struct mail_cache *cache, struct mail_index_view *iview);
diff -r 965e401fcb7b -r 29764126e1a6 src/lib-index/mail-index-sync.c
--- a/src/lib-index/mail-index-sync.c	Tue May 22 22:44:50 2007 +0300
+++ b/src/lib-index/mail-index-sync.c	Tue May 22 22:50:06 2007 +0300
@@ -654,6 +654,13 @@ int mail_index_sync_commit(struct mail_i
 	uoff_t offset;
 	int ret = 0;
 
+	if (mail_cache_need_compress(index->cache)) {
+		/* if cache compression fails, we don't really care.
+		   the cache offsets are updated only if the compression was
+		   successful. */
+		(void)mail_cache_compress(index->cache, ctx->ext_trans);
+	}
+
 	if (mail_index_transaction_commit(&ctx->ext_trans, &seq, &offset) < 0)
 		ret = -1;
 
@@ -679,18 +686,6 @@ int mail_index_sync_commit(struct mail_i
 			ret = -1;
 	}
 
-	if (ret == 0 && mail_cache_need_compress(index->cache)) {
-		/* if cache compression fails, we don't really care */
-		if (mail_cache_compress(index->cache, ctx->view) == 0) {
-			/* cache_offsets have changed, sync them */
-			if (mail_index_sync_set_log_view(ctx->view,
-							 seq, offset) < 0)
-				ret = -1;
-			else if (mail_index_sync_update_index(ctx, FALSE) < 0)
-				ret = -1;
-		}
-	}
-
 	if (ret == 0) {
 		index->sync_log_file_seq = index->map->hdr.log_file_seq;
 		index->sync_log_file_offset =


More information about the dovecot-cvs mailing list