dovecot: Code cleanups and some minor fixes.

dovecot at dovecot.org dovecot at dovecot.org
Sat Sep 22 11:43:02 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/53313d1e7e4f
changeset: 6443:53313d1e7e4f
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Sep 22 11:42:58 2007 +0300
description:
Code cleanups and some minor fixes.

diffstat:

2 files changed, 111 insertions(+), 77 deletions(-)
src/lib-index/mail-cache-fields.c      |   89 ++++++++++++++++------------
src/lib-index/mail-cache-transaction.c |   99 +++++++++++++++++++-------------

diffs (truncated from 307 to 300 lines):

diff -r 6f12401a149e -r 53313d1e7e4f src/lib-index/mail-cache-fields.c
--- a/src/lib-index/mail-cache-fields.c	Sat Sep 22 11:11:58 2007 +0300
+++ b/src/lib-index/mail-cache-fields.c	Sat Sep 22 11:42:58 2007 +0300
@@ -10,6 +10,10 @@
 #include <stddef.h>
 
 #define CACHE_HDR_PREFETCH 1024
+
+#define CACHE_FIELD_IS_NEWLY_WANTED(cache, field_idx) \
+	((cache)->field_file_map[field_idx] == (uint32_t)-1 && \
+	 (cache)->fields[field_idx].used)
 
 static bool field_has_fixed_size(enum mail_cache_field_type type)
 {
@@ -340,53 +344,61 @@ int mail_cache_header_fields_read(struct
 	return 0;
 }
 
-static void copy_to_buf(struct mail_cache *cache, buffer_t *dest,
+static void copy_to_buf(struct mail_cache *cache, buffer_t *dest, bool add_new,
 			size_t offset, size_t size)
 {
 	const void *data;
 	unsigned int i, field;
 
+	/* copy the existing fields */
 	for (i = 0; i < cache->file_fields_count; i++) {
 		field = cache->file_field_map[i];
                 data = CONST_PTR_OFFSET(&cache->fields[field], offset);
 		buffer_append(dest, data, size);
 	}
+	if (!add_new)
+		return;
+
+	/* copy newly wanted fields */
 	for (i = 0; i < cache->fields_count; i++) {
-		if (cache->field_file_map[i] != (uint32_t)-1 ||
-		    !cache->fields[i].used)
-			continue;
-		data = CONST_PTR_OFFSET(&cache->fields[i], offset);
-		buffer_append(dest, data, size);
+		if (CACHE_FIELD_IS_NEWLY_WANTED(cache, i)) {
+			data = CONST_PTR_OFFSET(&cache->fields[i], offset);
+			buffer_append(dest, data, size);
+		}
 	}
 }
 
 static void copy_to_buf_byte(struct mail_cache *cache, buffer_t *dest,
-			     size_t offset)
+			     bool add_new, size_t offset)
 {
 	const int *data;
 	unsigned int i, field;
 	uint8_t byte;
 
+	/* copy the existing fields */
 	for (i = 0; i < cache->file_fields_count; i++) {
 		field = cache->file_field_map[i];
                 data = CONST_PTR_OFFSET(&cache->fields[field], offset);
 		byte = (uint8_t)*data;
 		buffer_append(dest, &byte, 1);
 	}
+	if (!add_new)
+		return;
+
+	/* copy newly wanted fields */
 	for (i = 0; i < cache->fields_count; i++) {
-		if (cache->field_file_map[i] != (uint32_t)-1 ||
-		    !cache->fields[i].used)
-			continue;
-		data = CONST_PTR_OFFSET(&cache->fields[i], offset);
-		byte = (uint8_t)*data;
-		buffer_append(dest, &byte, 1);
+		if (CACHE_FIELD_IS_NEWLY_WANTED(cache, i)) {
+			data = CONST_PTR_OFFSET(&cache->fields[i], offset);
+			byte = (uint8_t)*data;
+			buffer_append(dest, &byte, 1);
+		}
 	}
 }
 
 static int mail_cache_header_fields_update_locked(struct mail_cache *cache)
 {
 	buffer_t *buffer;
-	uint32_t i, offset;
+	uint32_t i, offset, dec_offset;
 	int ret = 0;
 
 	if (mail_cache_header_fields_read(cache) < 0 ||
@@ -396,21 +408,20 @@ static int mail_cache_header_fields_upda
 	t_push();
 	buffer = buffer_create_dynamic(pool_datastack_create(), 256);
 
-	copy_to_buf(cache, buffer,
+	copy_to_buf(cache, buffer, FALSE,
 		    offsetof(struct mail_cache_field_private, last_used),
 		    sizeof(uint32_t));
-	ret = mail_cache_write(cache, buffer->data,
-			       sizeof(uint32_t) * cache->file_fields_count,
+	ret = mail_cache_write(cache, buffer->data, buffer->used,
 			       offset + MAIL_CACHE_FIELD_LAST_USED());
 	if (ret == 0) {
 		buffer_set_used_size(buffer, 0);
-		copy_to_buf_byte(cache, buffer,
+		copy_to_buf_byte(cache, buffer, FALSE,
 				 offsetof(struct mail_cache_field, decision));
 
-		ret = mail_cache_write(cache, buffer->data,
-			sizeof(uint8_t) * cache->file_fields_count, offset +
-			MAIL_CACHE_FIELD_DECISION(cache->file_fields_count));
-
+		dec_offset = offset +
+			MAIL_CACHE_FIELD_DECISION(cache->file_fields_count);
+		ret = mail_cache_write(cache, buffer->data, buffer->used,
+				       dec_offset);
 		if (ret == 0) {
 			for (i = 0; i < cache->file_fields_count; i++)
 				cache->fields[i].decision_dirty = FALSE;
@@ -450,41 +461,41 @@ void mail_cache_header_fields_get(struct
 	memset(&hdr, 0, sizeof(hdr));
 	hdr.fields_count = cache->file_fields_count;
 	for (i = 0; i < cache->fields_count; i++) {
-		if (cache->field_file_map[i] == (uint32_t)-1 &&
-		    cache->fields[i].used)
+		if (CACHE_FIELD_IS_NEWLY_WANTED(cache, i))
 			hdr.fields_count++;
 	}
 	buffer_append(dest, &hdr, sizeof(hdr));
 
 	/* we have to keep the field order for the existing fields. */
-	copy_to_buf(cache, dest,
+	copy_to_buf(cache, dest, TRUE,
 		    offsetof(struct mail_cache_field_private, last_used),
 		    sizeof(uint32_t));
-	copy_to_buf(cache, dest, offsetof(struct mail_cache_field, field_size),
+	copy_to_buf(cache, dest, TRUE,
+		    offsetof(struct mail_cache_field, field_size),
 		    sizeof(uint32_t));
-	copy_to_buf_byte(cache, dest, offsetof(struct mail_cache_field, type));
-	copy_to_buf_byte(cache, dest,
+	copy_to_buf_byte(cache, dest, TRUE,
+			 offsetof(struct mail_cache_field, type));
+	copy_to_buf_byte(cache, dest, TRUE,
 			 offsetof(struct mail_cache_field, decision));
 
-	i_assert(buffer_get_used_size(dest) == sizeof(hdr) +
+	i_assert(dest->used == sizeof(hdr) +
 		 (sizeof(uint32_t)*2 + 2) * hdr.fields_count);
 
-	/* add fields' names */
+	/* add existing fields' names */
 	for (i = 0; i < cache->file_fields_count; i++) {
 		field = cache->file_field_map[i];
 		name = cache->fields[field].field.name;
 		buffer_append(dest, name, strlen(name)+1);
 	}
+	/* add newly wanted fields' names */
 	for (i = 0; i < cache->fields_count; i++) {
-		if (cache->field_file_map[i] != (uint32_t)-1 ||
-		    !cache->fields[i].used)
-			continue;
-
-		name = cache->fields[i].field.name;
-		buffer_append(dest, name, strlen(name)+1);
-	}
-
-	hdr.size = buffer_get_used_size(dest);
+		if (CACHE_FIELD_IS_NEWLY_WANTED(cache, i)) {
+			name = cache->fields[i].field.name;
+			buffer_append(dest, name, strlen(name)+1);
+		}
+	}
+
+	hdr.size = dest->used;
 	buffer_write(dest, 0, &hdr, sizeof(hdr));
 
 	if ((hdr.size & 3) != 0)
diff -r 6f12401a149e -r 53313d1e7e4f src/lib-index/mail-cache-transaction.c
--- a/src/lib-index/mail-cache-transaction.c	Sat Sep 22 11:11:58 2007 +0300
+++ b/src/lib-index/mail-cache-transaction.c	Sat Sep 22 11:42:58 2007 +0300
@@ -663,18 +663,58 @@ void mail_cache_transaction_rollback(str
 	mail_cache_transaction_free(ctx);
 }
 
+static int
+mail_cache_header_fields_write(struct mail_cache_transaction_ctx *ctx,
+			       const buffer_t *buffer)
+{
+	struct mail_cache *cache = ctx->cache;
+	size_t size = buffer->used;
+	uint32_t offset, hdr_offset;
+
+	if (mail_cache_transaction_get_space(ctx, size, size,
+					     &offset, NULL, TRUE) <= 0)
+		return -1;
+
+	if (mail_cache_write(cache, buffer->data, size, offset) < 0)
+		return -1;
+
+	if (!cache->index->fsync_disable) {
+		if (fdatasync(cache->fd) < 0) {
+			mail_cache_set_syscall_error(cache, "fdatasync()");
+			return -1;
+		}
+	}
+	if (mail_cache_header_fields_get_next_offset(cache, &hdr_offset) < 0)
+		return -1;
+
+	/* if we rollback the transaction, we must not overwrite this
+	   area because it's already committed after updating the
+	   header offset */
+	mail_cache_transaction_partial_commit(ctx, offset, size);
+
+	/* after it's guaranteed to be in disk, update header offset */
+	offset = mail_index_uint32_to_offset(offset);
+	if (mail_cache_write(cache, &offset, sizeof(offset), hdr_offset) < 0)
+		return -1;
+
+	if (hdr_offset == offsetof(struct mail_cache_header,
+				   field_header_offset)) {
+		/* we're adding the first field. hdr_copy needs to be kept
+		   in sync so unlocking won't overwrite it. */
+		cache->hdr_copy.field_header_offset = hdr_offset;
+	}
+	return 0;
+}
+
 static int mail_cache_header_add_field(struct mail_cache_transaction_ctx *ctx,
 				       unsigned int field_idx)
 {
 	struct mail_cache *cache = ctx->cache;
 	buffer_t *buffer;
-	const void *data;
-	size_t size;
-	uint32_t offset, hdr_offset;
-	int ret = 0;
-
-	ctx->cache->fields[field_idx].last_used = ioloop_time;
-	ctx->cache->fields[field_idx].used = TRUE;
+	int ret;
+
+	cache->fields[field_idx].last_used = ioloop_time;
+	cache->fields[field_idx].used = TRUE;
 
 	if ((ret = mail_cache_transaction_lock(ctx)) <= 0) {
 		/* create the cache file if it doesn't exist yet */
@@ -694,7 +734,7 @@ static int mail_cache_header_add_field(s
 		return -1;
 	}
 
-	if (ctx->cache->field_file_map[field_idx] != (uint32_t)-1) {
+	if (cache->field_file_map[field_idx] != (uint32_t)-1) {
 		/* it was already added */
 		if (mail_cache_unlock(cache) < 0)
 			return -1;
@@ -704,37 +744,20 @@ static int mail_cache_header_add_field(s
 	t_push();
 	buffer = buffer_create_dynamic(pool_datastack_create(), 256);
 	mail_cache_header_fields_get(cache, buffer);
-	data = buffer_get_data(buffer, &size);
-
-	if (mail_cache_transaction_get_space(ctx, size, size,
-					     &offset, NULL, TRUE) <= 0)
+	ret = mail_cache_header_fields_write(ctx, buffer);
+	t_pop();
+
+	if (ret == 0) {
+		/* we wrote all the headers, so there are no pending changes */
+		cache->field_header_write_pending = FALSE;
+		ret = mail_cache_header_fields_read(cache);
+	}
+	if (ret == 0 && cache->field_file_map[field_idx] == (uint32_t)-1) {
+		mail_index_set_error(cache->index,
+				     "Cache file %s: Newly added field got "
+				     "lost unexpectedly", cache->filepath);
 		ret = -1;
-	else if (mail_cache_write(cache, data, size, offset) < 0)
-		ret = -1;
-	else if (!cache->index->fsync_disable && fdatasync(cache->fd) < 0) {
-		mail_cache_set_syscall_error(cache, "fdatasync()");
-		ret = -1;
-	} else if (mail_cache_header_fields_get_next_offset(cache,
-							    &hdr_offset) < 0)
-		ret = -1;
-	else {
-		/* if we rollback the transaction, we must not overwrite this
-		   area because it's already committed after updating the
-		   header offset */
-		mail_cache_transaction_partial_commit(ctx, offset, size);
-
-		/* after it's guaranteed to be in disk, update header offset */
-		offset = mail_index_uint32_to_offset(offset);
-		if (mail_cache_write(cache, &offset, sizeof(offset),
-				     hdr_offset) < 0)
-			ret = -1;
-		else {
-			/* we'll need to fix mappings. */
-			if (mail_cache_header_fields_read(cache) < 0)
-				ret = -1;


More information about the dovecot-cvs mailing list