changeset 6703:75c48f171ad3 HEAD

Keep a separate copy of mail_cache_header when mmap_disable=yes, otherwise it could get cleared unexpectedly.
author Timo Sirainen <tss@iki.fi>
date Tue, 06 Nov 2007 20:28:01 +0200
parents 34a5cf8675fc
children b0e8403b4bb1
files src/lib-index/mail-cache-private.h src/lib-index/mail-cache-transaction.c src/lib-index/mail-cache.c
diffstat 3 files changed, 24 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-cache-private.h	Tue Nov 06 19:13:33 2007 +0200
+++ b/src/lib-index/mail-cache-private.h	Tue Nov 06 20:28:01 2007 +0200
@@ -142,7 +142,13 @@
 	struct dotlock *dotlock;
 	struct file_lock *file_lock;
 
+	/* mmap_disable=no: hdr points to data / NULL when cache is invalid.
+	   mmap_disable=yes: hdr points to hdr_ro_copy. this is needed because
+	   cache invalidation can zero the data any time */
 	const struct mail_cache_header *hdr;
+	struct mail_cache_header hdr_ro_copy;
+	/* hdr_copy gets updated when cache is locked and written when
+	   unlocking and hdr_modified=TRUE */
 	struct mail_cache_header hdr_copy;
 
 	pool_t field_pool;
--- a/src/lib-index/mail-cache-transaction.c	Tue Nov 06 19:13:33 2007 +0200
+++ b/src/lib-index/mail-cache-transaction.c	Tue Nov 06 20:28:01 2007 +0200
@@ -705,6 +705,7 @@
 		/* 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;
+		cache->hdr_ro_copy.field_header_offset = hdr_offset;
 	}
 	return 0;
 }
--- a/src/lib-index/mail-cache.c	Tue Nov 06 19:13:33 2007 +0200
+++ b/src/lib-index/mail-cache.c	Tue Nov 06 20:28:01 2007 +0200
@@ -181,7 +181,7 @@
 		return FALSE;
 	}
 
-	if (cache->hdr->version != MAIL_CACHE_VERSION) {
+	if (hdr->version != MAIL_CACHE_VERSION) {
 		/* version changed - upgrade silently */
 		return FALSE;
 	}
@@ -190,11 +190,11 @@
 		return FALSE;
 	}
 
-	if (cache->hdr->indexid != cache->index->indexid) {
+	if (hdr->indexid != cache->index->indexid) {
 		/* index id changed - handle silently */
 		return FALSE;
 	}
-	if (cache->hdr->file_seq == 0) {
+	if (hdr->file_seq == 0) {
 		mail_cache_set_corrupted(cache, "file_seq is 0");
 		return FALSE;
 	}
@@ -249,16 +249,19 @@
 
 		cache->data = file_cache_get_map(cache->file_cache,
 						 &cache->mmap_length);
-		cache->hdr = cache->data;
 
-		if (offset == 0 && !mail_cache_verify_header(cache)) {
-			cache->need_compress_file_seq =
-				!MAIL_CACHE_IS_UNUSABLE(cache) &&
-				cache->hdr->file_seq != 0 ?
-				cache->hdr->file_seq : 0;
-			cache->hdr = NULL;
-			return -1;
+		if (offset == 0) {
+			if (!mail_cache_verify_header(cache)) {
+				cache->need_compress_file_seq =
+					!MAIL_CACHE_IS_UNUSABLE(cache) &&
+					cache->hdr->file_seq != 0 ?
+					cache->hdr->file_seq : 0;
+				return -1;
+			}
+			memcpy(&cache->hdr_ro_copy, cache->data,
+			       sizeof(cache->hdr_ro_copy));
 		}
+		cache->hdr = &cache->hdr_ro_copy;
 		return 0;
 	}
 
@@ -293,17 +296,16 @@
 		return -1;
 	}
 	cache->data = cache->mmap_base;
-	cache->hdr = cache->mmap_base;
 
 	if (!mail_cache_verify_header(cache)) {
 		cache->need_compress_file_seq =
 			!MAIL_CACHE_IS_UNUSABLE(cache) &&
 			cache->hdr->file_seq != 0 ?
 			cache->hdr->file_seq : 0;
-		cache->hdr = NULL;
 		return -1;
 	}
 
+	cache->hdr = cache->data;
 	return 0;
 }
 
@@ -601,6 +603,7 @@
 		if (mail_cache_write(cache, &cache->hdr_copy,
 				     sizeof(cache->hdr_copy), 0) < 0)
 			ret = -1;
+		cache->hdr_ro_copy = cache->hdr_copy;
 		mail_cache_update_need_compress(cache);
 	}
 
@@ -624,10 +627,9 @@
 	if (cache->file_cache != NULL) {
 		file_cache_write(cache->file_cache, data, size, offset);
 
-		/* data/hdr pointers may change if file cache was grown */
+		/* data pointer may change if file cache was grown */
 		cache->data = file_cache_get_map(cache->file_cache,
 						 &cache->mmap_length);
-		cache->hdr = cache->data;
 	}
 	return 0;
 }