changeset 5819:4ea31bf18a56 HEAD

Handle indexid changes better.
author Timo Sirainen <tss@iki.fi>
date Thu, 28 Jun 2007 01:03:18 +0300
parents 86282604e2f5
children e59892590a02
files src/lib-index/mail-cache-compress.c src/lib-index/mail-index-map.c src/lib-index/mail-index-sync-update.c src/lib-index/mail-index-write.c src/lib-index/mail-index.c src/lib-index/mail-transaction-log-file.c src/lib-index/mail-transaction-log-private.h src/lib-index/mail-transaction-log.c src/lib-index/mail-transaction-log.h
diffstat 9 files changed, 79 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- 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 @@
 	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));
 
--- 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 @@
 				     "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(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 @@
 		   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))
--- 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 @@
 #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
--- 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 @@
 	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)
--- 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 @@
 		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);
--- 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 @@
 {
 	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 @@
 	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 @@
 
 	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;
@@ -314,6 +318,9 @@
 
 	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) {
                 if (errno != ESTALE || !ignore_estale) {
@@ -347,18 +354,19 @@
 
 	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 @@
 		} 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;
--- 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 file_lock *file_lock;
 
 	unsigned int locked:1;
+	unsigned int corrupted:1;
 };
 
 struct mail_transaction_log {
--- 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 @@
 		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;
--- 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
@@ -124,6 +124,9 @@
 /* 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
    points always to the latest file. This function doesn't actually find the