dovecot: More squat fixes.

dovecot at dovecot.org dovecot at dovecot.org
Sun Feb 10 21:55:06 EET 2008


details:   http://hg.dovecot.org/dovecot/rev/e042b6385c7b
changeset: 7221:e042b6385c7b
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Feb 10 21:54:57 2008 +0200
description:
More squat fixes.

diffstat:

2 files changed, 68 insertions(+), 27 deletions(-)
src/plugins/fts-squat/squat-trie-private.h |    3 
src/plugins/fts-squat/squat-trie.c         |   92 ++++++++++++++++++++--------

diffs (197 lines):

diff -r 21d1d0ced13e -r e042b6385c7b src/plugins/fts-squat/squat-trie-private.h
--- a/src/plugins/fts-squat/squat-trie-private.h	Sat Feb 09 15:11:24 2008 +0200
+++ b/src/plugins/fts-squat/squat-trie-private.h	Sun Feb 10 21:54:57 2008 +0200
@@ -61,7 +61,8 @@ struct squat_node {
 	   first SEQUENTIAL_COUNT children have chars[n] = n. */
 	unsigned int have_sequential:1;
 
-	/* Number of UIDs that exists in parent node but not in this one.
+	/* Number of UIDs that exists in parent node but not in this one
+	   (i.e. number of UIDs [0..next_uid-1] not in this node's uidlist).
 	   This is mainly used when adding new UIDs to our children to set
 	   the UID to be relative to this node's UID list. */
 	uint32_t unused_uids;
diff -r 21d1d0ced13e -r e042b6385c7b src/plugins/fts-squat/squat-trie.c
--- a/src/plugins/fts-squat/squat-trie.c	Sat Feb 09 15:11:24 2008 +0200
+++ b/src/plugins/fts-squat/squat-trie.c	Sun Feb 10 21:54:57 2008 +0200
@@ -140,6 +140,22 @@ squat_trie_init(const char *path, uint32
 	return trie;
 }
 
+static void squat_trie_close_fd(struct squat_trie *trie)
+{
+	trie->data = NULL;
+	trie->data_size = 0;
+
+	if (trie->mmap_size != 0) {
+		if (munmap(trie->mmap_base, trie->mmap_size) < 0)
+			i_error("munmap(%s) failed: %m", trie->path);
+	}
+	if (trie->fd != -1) {
+		if (close(trie->fd) < 0)
+			i_error("close(%s) failed: %m", trie->path);
+		trie->fd = -1;
+	}
+}
+
 static void squat_trie_close(struct squat_trie *trie)
 {
 	trie->corrupted = FALSE;
@@ -147,20 +163,9 @@ static void squat_trie_close(struct squa
 	memset(&trie->root, 0, sizeof(trie->root));
 	memset(&trie->hdr, 0, sizeof(trie->hdr));
 
-	trie->data = NULL;
-	trie->data_size = 0;
-
+	squat_trie_close_fd(trie);
 	if (trie->file_cache != NULL)
 		file_cache_free(&trie->file_cache);
-	if (trie->mmap_size != 0) {
-		if (munmap(trie->mmap_base, trie->mmap_size) < 0)
-			i_error("munmap(%s) failed: %m", trie->path);
-	}
-	if (trie->fd != -1) {
-		if (close(trie->fd) < 0)
-			i_error("close(%s) failed: %m", trie->path);
-		trie->fd = -1;
-	}
 	trie->locked_file_size = 0;
 }
 
@@ -232,8 +237,11 @@ static int squat_trie_is_file_stale(stru
 	}
 	trie->locked_file_size = st2.st_size;
 
-	return st.st_ino == st2.st_ino &&
-		CMP_DEV_T(st.st_dev, st2.st_dev) ? 0 : 1;
+	if (st.st_ino == st2.st_ino && CMP_DEV_T(st.st_dev, st2.st_dev)) {
+		i_assert(trie->locked_file_size >= trie->data_size);
+		return 0;
+	}
+	return 1;
 }
 
 void squat_trie_refresh(struct squat_trie *trie)
@@ -704,6 +712,7 @@ static int squat_build_add(struct squat_
 		level++;
 
 		if (node->have_sequential) {
+			i_assert(node->child_count >= SEQUENTIAL_COUNT);
 			if (*data < SEQUENTIAL_COUNT) {
 				idx = *data;
 				goto found;
@@ -1089,7 +1098,8 @@ squat_uidlist_update_expunged_uids(const
 squat_uidlist_update_expunged_uids(const ARRAY_TYPE(seq_range) *shifts_arr,
 				   ARRAY_TYPE(seq_range) *child_shifts,
 				   ARRAY_TYPE(seq_range) *uids_arr,
-				   bool do_shifts)
+				   struct squat_trie *trie,
+				   struct squat_node *node, bool do_shifts)
 {
 	const struct seq_range *shifts;
 	struct seq_range *uids, shift;
@@ -1097,8 +1107,13 @@ squat_uidlist_update_expunged_uids(const
 	uint32_t child_shift_seq1, child_shift_count, seq_high;
 	unsigned int shift_sum = 0, child_sum = 0;
 
-	if (!array_is_created(shifts_arr))
+	if (!array_is_created(shifts_arr)) {
+		i_assert(node->uid_list_idx != 0 || node->child_count == 0);
 		return;
+	}
+
+	/* we'll recalculate this */
+	node->unused_uids = 0;
 
 	uids = array_get_modifiable(uids_arr, &uid_count);
 	shifts = array_get(shifts_arr, &shift_count);
@@ -1115,13 +1130,22 @@ squat_uidlist_update_expunged_uids(const
 				uids[uid_idx].seq1 + 1;
 
 			if (uid_idx > 0 &&
-			    uids[uid_idx-1].seq2 == uids[uid_idx].seq1 - 1) {
+			    uids[uid_idx-1].seq2 >= uids[uid_idx].seq1 - 1) {
 				/* we can merge this and the previous range */
+				i_assert(uids[uid_idx-1].seq2 ==
+					 uids[uid_idx].seq1 - 1);
 				uids[uid_idx-1].seq2 = uids[uid_idx].seq2;
 				array_delete(uids_arr, uid_idx, 1);
 				uids = array_get_modifiable(uids_arr,
 							    &uid_count);
 			} else {
+				if (uid_idx == 0)
+					node->unused_uids += uids[0].seq1;
+				else {
+					node->unused_uids +=
+						uids[uid_idx].seq1 -
+						uids[uid_idx-1].seq2 - 1;
+				}
 				uid_idx++;
 			}
 		}
@@ -1186,6 +1210,24 @@ squat_uidlist_update_expunged_uids(const
 			shift_sum = 0;
 		}
 	}
+
+	if (uid_count == 0) {
+		/* no UIDs left, delete the node's children and mark it
+		   unused */
+		i_assert(!NODE_IS_DYNAMIC_LEAF(node));
+		node_free(trie, node);
+
+		node->child_count = 0;
+		node->have_sequential = FALSE;
+		node->next_uid = 0;
+	} else {
+		if (do_shifts)
+			node->next_uid = uids[uid_count-1].seq2 + 1;
+		else {
+			node->unused_uids += (node->next_uid - 1) -
+				uids[uid_count-1].seq2;
+		}
+	}
 }
 
 static int
@@ -1217,13 +1259,12 @@ squat_trie_expunge_uidlists(struct squat
 			break;
 		}
 		squat_uidlist_update_expunged_uids(&shifts, &iter->cur.shifts,
-						   &uid_range, shift);
+						   &uid_range, ctx->trie, node,
+						   shift);
 		node->uid_list_idx =
 			squat_uidlist_rebuild_nextu(rebuild_ctx, &uid_range);
-		if (node->uid_list_idx == 0) {
-			node->child_count = 0;
-			node->next_uid = 0;
-		}
+		i_assert(node->uid_list_idx != 0 || node->next_uid == 0);
+
 		node = squat_trie_iterate_next(iter, &shifts);
 		shift = TRUE;
 	} while (node != NULL);
@@ -1434,6 +1475,7 @@ int squat_trie_build_init(struct squat_t
 		}
 		if (trie->file_cache != NULL)
 			file_cache_set_fd(trie->file_cache, trie->fd);
+		i_assert(trie->locked_file_size == 0);
 	}
 
 	/* uidlist locks building */
@@ -1557,11 +1599,9 @@ static int squat_trie_write(struct squat
 		if (unlink(path) < 0 && errno != ENOENT)
 			i_error("unlink(%s) failed: %m", path);
 	} else {
-		if (trie->fd != -1) {
-			if (close(trie->fd) < 0)
-				i_error("close(%s) failed: %m", trie->path);
-		}
+		squat_trie_close_fd(trie);
 		trie->fd = fd;
+		trie->locked_file_size = trie->hdr.used_file_size;
 		if (trie->file_cache != NULL)
 			file_cache_set_fd(trie->file_cache, trie->fd);
 	}


More information about the dovecot-cvs mailing list