changeset 627:49893535ce92 HEAD

Avoid rebuilding tree twice if two processes notice it's broken at the same time.
author Timo Sirainen <tss@iki.fi>
date Wed, 20 Nov 2002 18:15:57 +0200
parents 5ce5aafe28d9
children e4aba04143ad
files src/lib-index/mail-tree.c
diffstat 1 files changed, 40 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-tree.c	Wed Nov 20 18:06:24 2002 +0200
+++ b/src/lib-index/mail-tree.c	Wed Nov 20 18:15:57 2002 +0200
@@ -201,6 +201,32 @@
 	return TRUE;
 }
 
+static int mail_tree_open_init(MailTree *tree)
+{
+	if (!mmap_update(tree))
+		return FALSE;
+
+	if (tree->mmap_full_length == 0) {
+		/* just created it */
+		return FALSE;
+	}
+
+	if (!mmap_verify(tree)) {
+		/* broken header */
+		return FALSE;
+	}
+
+	if (tree->header->indexid != tree->index->indexid) {
+		index_set_error(tree->index,
+				"IndexID mismatch for binary tree file %s",
+				tree->filepath);
+
+		return FALSE;
+	} 
+
+	return TRUE;
+}
+
 int mail_tree_open_or_create(MailIndex *index)
 {
 	MailTree *tree;
@@ -209,32 +235,23 @@
 	if (tree == NULL)
 		return FALSE;
 
-	do {
-		if (!mmap_update(tree))
-			break;
-
-		if (tree->mmap_full_length == 0) {
-			/* just created it */
-			if (!mail_tree_rebuild(tree))
-				break;
-		} else if (!mmap_verify(tree)) {
-			/* broken header */
-			if (!mail_tree_rebuild(tree))
-				break;
-		} else if (tree->header->indexid != index->indexid) {
-			index_set_error(tree->index,
-				"IndexID mismatch for binary tree file %s",
-				tree->filepath);
-
-			if (!mail_tree_rebuild(tree))
-				break;
+	if (!mail_tree_open_init(tree)) {
+		/* lock and check again, just to avoid rebuilding it twice
+		   if two processes notice the error at the same time */
+		if (!tree->index->set_lock(tree->index, MAIL_LOCK_EXCLUSIVE)) {
+			mail_tree_free(tree);
+			return FALSE;
 		}
 
-		return TRUE;
-	} while (0);
+		if (!mail_tree_open_init(tree)) {
+			if (!mail_tree_rebuild(tree)) {
+				mail_tree_free(tree);
+				return FALSE;
+			}
+		}
+	}
 
-	mail_tree_free(tree);
-	return FALSE;
+	return TRUE;
 }
 
 static void mail_tree_close(MailTree *tree)