dovecot: Handle indexid changes better.

dovecot at dovecot.org dovecot at dovecot.org
Thu Jun 28 01:52:05 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/4ea31bf18a56
changeset: 5819:4ea31bf18a56
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Jun 28 01:03:18 2007 +0300
description:
Handle indexid changes better.

diffstat:

9 files changed, 79 insertions(+), 17 deletions(-)
src/lib-index/mail-cache-compress.c          |    2 -
src/lib-index/mail-index-map.c               |   26 +++++++++++++++++++-----
src/lib-index/mail-index-sync-update.c       |    1 
src/lib-index/mail-index-write.c             |    1 
src/lib-index/mail-index.c                   |   12 ++++++++++-
src/lib-index/mail-transaction-log-file.c    |   28 ++++++++++++++++----------
src/lib-index/mail-transaction-log-private.h |    1 
src/lib-index/mail-transaction-log.c         |   22 ++++++++++++++++++++
src/lib-index/mail-transaction-log.h         |    3 ++

diffs (262 lines):

diff -r 86282604e2f5 -r 4ea31bf18a56 src/lib-index/mail-cache-compress.c
--- a/src/lib-index/mail-cache-compress.c	Thu Jun 28 00:04:31 2007 +0300
+++ b/src/lib-index/mail-cache-compress.c	Thu Jun 28 01:03:18 2007 +0300
@@ -139,7 +139,7 @@ mail_cache_copy(struct mail_cache *cache
 	memset(&hdr, 0, sizeof(hdr));
 	hdr.version = MAIL_CACHE_VERSION;
 	hdr.compat_sizeof_uoff_t = sizeof(uoff_t);
-	hdr.indexid = idx_hdr->indexid;
+	hdr.indexid = cache->index->indexid;
 	hdr.file_seq = get_next_file_seq(cache, view);
 	o_stream_send(output, &hdr, sizeof(hdr));
 
diff -r 86282604e2f5 -r 4ea31bf18a56 src/lib-index/mail-index-map.c
--- a/src/lib-index/mail-index-map.c	Thu Jun 28 00:04:31 2007 +0300
+++ b/src/lib-index/mail-index-map.c	Thu Jun 28 01:03:18 2007 +0300
@@ -7,6 +7,7 @@
 #include "read-full.h"
 #include "mail-index-private.h"
 #include "mail-index-sync-private.h"
+#include "mail-transaction-log-private.h"
 
 static void mail_index_map_init_extbufs(struct mail_index_map *map,
 					unsigned int initial_count)
@@ -252,7 +253,18 @@ static bool mail_index_check_header_comp
 				     "Corrupted header size (%u > %"PRIuUOFF_T")",
 				     index->filepath, hdr->header_size,
 				     file_size);
-		return 0;
+		return FALSE;
+	}
+
+	if (hdr->indexid != index->indexid) {
+		if (index->indexid != 0) {
+			mail_index_set_error(index, "Index file %s: "
+					     "indexid changed: %u -> %u",
+					     index->filepath, index->indexid,
+					     hdr->indexid);
+		}
+		index->indexid = hdr->indexid;
+		mail_transaction_log_indexid_changed(index->log);
 	}
 
 	return TRUE;
@@ -609,7 +621,6 @@ static void mail_index_header_init(struc
 static void mail_index_header_init(struct mail_index *index,
 				   struct mail_index_header *hdr)
 {
-	i_assert(index->indexid != 0);
 	i_assert((sizeof(*hdr) % sizeof(uint64_t)) == 0);
 
 	memset(hdr, 0, sizeof(*hdr));
@@ -741,9 +752,14 @@ int mail_index_map(struct mail_index *in
 		   reopening succeeds) */
 		(void)mail_index_map_latest_file(index, &index->map, &lock_id);
 
-		/* and update the map with the latest changes from
-		   transaction log */
-		ret = mail_index_sync_map(index, &index->map, type, TRUE);
+		/* if we're creating the index file, we don't have any
+		   logs yet */
+		if (index->log->head != NULL) {
+			/* and update the map with the latest changes from
+			   transaction log */
+			ret = mail_index_sync_map(index, &index->map,
+						  type, TRUE);
+		}
 
 		/* we need the lock only if we didn't move the map to memory */
 		if (!MAIL_INDEX_MAP_IS_IN_MEMORY(index->map))
diff -r 86282604e2f5 -r 4ea31bf18a56 src/lib-index/mail-index-sync-update.c
--- a/src/lib-index/mail-index-sync-update.c	Thu Jun 28 00:04:31 2007 +0300
+++ b/src/lib-index/mail-index-sync-update.c	Thu Jun 28 01:03:18 2007 +0300
@@ -799,6 +799,7 @@ int mail_index_sync_map(struct mail_inde
 #ifdef DEBUG
 	mail_index_map_check(map);
 #endif
+	i_assert(map->hdr.indexid == index->indexid);
 
 	/* transaction log tracks internally the current tail offset.
 	   besides using header updates, it also updates the offset to skip
diff -r 86282604e2f5 -r 4ea31bf18a56 src/lib-index/mail-index-write.c
--- a/src/lib-index/mail-index-write.c	Thu Jun 28 00:04:31 2007 +0300
+++ b/src/lib-index/mail-index-write.c	Thu Jun 28 01:03:18 2007 +0300
@@ -20,6 +20,7 @@ static int mail_index_recreate(struct ma
 	int ret, fd;
 
 	i_assert(!MAIL_INDEX_IS_IN_MEMORY(index));
+	i_assert(map->hdr.indexid == index->indexid);
 
 	fd = mail_index_create_tmp_file(index, &path);
 	if (fd == -1)
diff -r 86282604e2f5 -r 4ea31bf18a56 src/lib-index/mail-index.c
--- a/src/lib-index/mail-index.c	Thu Jun 28 00:04:31 2007 +0300
+++ b/src/lib-index/mail-index.c	Thu Jun 28 01:03:18 2007 +0300
@@ -1,6 +1,7 @@
 /* Copyright (C) 2003-2004 Timo Sirainen */
 
 #include "lib.h"
+#include "ioloop.h"
 #include "array.h"
 #include "buffer.h"
 #include "hash.h"
@@ -404,11 +405,20 @@ static bool mail_index_open_files(struct
 		if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
 			return FALSE;
 
+		/* if dovecot.index exists, read it first so that we can get
+		   the correct indexid and log sequence */
+		(void)mail_index_try_open(index);
+
+		if (index->indexid == 0) {
+			/* create a new indexid for us */
+			index->indexid = ioloop_time;
+		}
+
 		ret = mail_transaction_log_create(index->log);
 		created = TRUE;
 	}
 	if (ret >= 0) {
-		ret = created ? 0 : mail_index_try_open(index);
+		ret = index->map != NULL ? 0 : mail_index_try_open(index);
 		if (ret == 0) {
 			/* doesn't exist / corrupted */
 			index->map = mail_index_map_alloc(index);
diff -r 86282604e2f5 -r 4ea31bf18a56 src/lib-index/mail-transaction-log-file.c
--- a/src/lib-index/mail-transaction-log-file.c	Thu Jun 28 00:04:31 2007 +0300
+++ b/src/lib-index/mail-transaction-log-file.c	Thu Jun 28 01:03:18 2007 +0300
@@ -20,6 +20,7 @@ mail_transaction_log_file_set_corrupted(
 {
 	va_list va;
 
+	file->corrupted = TRUE;
 	file->hdr.indexid = 0;
 	if (!MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
 		/* indexid=0 marks the log file as corrupted */
@@ -142,9 +143,6 @@ mail_transaction_log_init_hdr(struct mai
 	struct mail_index *index = log->index;
 	unsigned int lock_id = 0;
 
-	if (log->index->indexid == 0)
-		log->index->indexid = ioloop_time;
-
 	memset(hdr, 0, sizeof(*hdr));
 	hdr->major_version = MAIL_TRANSACTION_LOG_MAJOR_VERSION;
 	hdr->minor_version = MAIL_TRANSACTION_LOG_MINOR_VERSION;
@@ -154,9 +152,15 @@ mail_transaction_log_init_hdr(struct mai
 
 	if (index->fd != -1) {
 		/* not creating index - make sure we have latest header */
-		if (mail_index_map(index, MAIL_INDEX_SYNC_HANDLER_HEAD,
-				   &lock_id) <= 0)
-			return -1;
+		if (!index->mapping) {
+			if (mail_index_map(index, MAIL_INDEX_SYNC_HANDLER_HEAD,
+					   &lock_id) <= 0)
+				return -1;
+		} else {
+			/* if we got here from mapping, the .log file is
+			   corrupted. use whatever values we got from index
+			   file */
+		}
 	}
 	if (index->map != NULL) {
 		hdr->prev_file_seq = index->map->hdr.log_file_seq;
@@ -313,6 +317,9 @@ mail_transaction_log_file_read_hdr(struc
 	int ret;
 
 	i_assert(!MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file));
+
+	if (file->corrupted)
+		return 0;
 
 	ret = pread_full(file->fd, &file->hdr, sizeof(file->hdr), 0);
 	if (ret < 0) {
@@ -347,18 +354,19 @@ mail_transaction_log_file_read_hdr(struc
 
 	if (file->hdr.indexid == 0) {
 		/* corrupted */
+		file->corrupted = TRUE;
 		mail_index_set_error(file->log->index,
 			"Transaction log file %s: marked corrupted",
 			file->filepath);
 		return 0;
 	}
 	if (file->hdr.indexid != file->log->index->indexid) {
-		if (file->log->index->fd != -1) {
+		if (file->log->index->indexid != 0) {
 			/* index file was probably just rebuilt and we don't
 			   know about it yet */
 			mail_transaction_log_file_set_corrupted(file,
-				"invalid indexid (%u != %u)",
-				file->hdr.indexid, file->log->index->indexid);
+				"indexid changed %u -> %u",
+				file->log->index->indexid, file->hdr.indexid);
 			return 0;
 		}
 
@@ -462,7 +470,7 @@ mail_transaction_log_file_create2(struct
 		} else {
 			file->fd = fd;
 			if (mail_transaction_log_file_read_hdr(file,
-							       FALSE) == 0) {
+							       FALSE) > 0) {
 				/* yes, it was ok */
 				(void)file_dotlock_delete(dotlock);
 				return 0;
diff -r 86282604e2f5 -r 4ea31bf18a56 src/lib-index/mail-transaction-log-private.h
--- a/src/lib-index/mail-transaction-log-private.h	Thu Jun 28 00:04:31 2007 +0300
+++ b/src/lib-index/mail-transaction-log-private.h	Thu Jun 28 01:03:18 2007 +0300
@@ -46,6 +46,7 @@ struct mail_transaction_log_file {
 	struct file_lock *file_lock;
 
 	unsigned int locked:1;
+	unsigned int corrupted:1;
 };
 
 struct mail_transaction_log {
diff -r 86282604e2f5 -r 4ea31bf18a56 src/lib-index/mail-transaction-log.c
--- a/src/lib-index/mail-transaction-log.c	Thu Jun 28 00:04:31 2007 +0300
+++ b/src/lib-index/mail-transaction-log.c	Thu Jun 28 01:03:18 2007 +0300
@@ -137,6 +137,28 @@ void mail_transaction_log_move_to_memory
 		mail_transaction_log_file_move_to_memory(log->head);
 }
 
+void mail_transaction_log_indexid_changed(struct mail_transaction_log *log)
+{
+	struct mail_transaction_log_file *file;
+
+	mail_transaction_logs_clean(log);
+
+	for (file = log->files; file != NULL; file = file->next) {
+		if (file->hdr.indexid != log->index->indexid) {
+			mail_transaction_log_file_set_corrupted(file,
+				"indexid changed: %u -> %u",
+				file->hdr.indexid, log->index->indexid);
+		}
+	}
+
+	if (log->head != NULL &&
+	    log->head->hdr.indexid != log->index->indexid) {
+		if (--log->head->refcount == 0)
+			mail_transaction_log_file_free(&log->head);
+		(void)mail_transaction_log_create(log);
+	}
+}
+
 void mail_transaction_logs_clean(struct mail_transaction_log *log)
 {
 	struct mail_transaction_log_file *file, *next;
diff -r 86282604e2f5 -r 4ea31bf18a56 src/lib-index/mail-transaction-log.h
--- a/src/lib-index/mail-transaction-log.h	Thu Jun 28 00:04:31 2007 +0300
+++ b/src/lib-index/mail-transaction-log.h	Thu Jun 28 01:03:18 2007 +0300
@@ -123,6 +123,9 @@ int mail_transaction_log_create(struct m
 int mail_transaction_log_create(struct mail_transaction_log *log);
 /* Close all the open transactions log files. */
 void mail_transaction_log_close(struct mail_transaction_log *log);
+
+/* Notify of indexid change */
+void mail_transaction_log_indexid_changed(struct mail_transaction_log *log);
 
 /* Returns the file seq/offset where the mailbox is currently synced at.
    Since the log is rotated only when mailbox is fully synced, the sequence


More information about the dovecot-cvs mailing list