dovecot: Squat fixes

dovecot at dovecot.org dovecot at dovecot.org
Sat Feb 9 14:34:34 EET 2008


details:   http://hg.dovecot.org/dovecot/rev/43d2f70fb279
changeset: 7218:43d2f70fb279
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Feb 09 13:53:54 2008 +0200
description:
Squat fixes

diffstat:

2 files changed, 87 insertions(+), 37 deletions(-)
src/plugins/fts-squat/squat-trie.c    |   22 +++++--
src/plugins/fts-squat/squat-uidlist.c |  102 ++++++++++++++++++++++-----------

diffs (truncated from 352 to 300 lines):

diff -r 4674cdad3672 -r 43d2f70fb279 src/plugins/fts-squat/squat-trie.c
--- a/src/plugins/fts-squat/squat-trie.c	Fri Feb 08 08:46:08 2008 +0200
+++ b/src/plugins/fts-squat/squat-trie.c	Sat Feb 09 13:53:54 2008 +0200
@@ -201,6 +201,8 @@ static int squat_trie_open_fd(struct squ
 		i_error("open(%s) failed: %m", trie->path);
 		return -1;
 	}
+	if (trie->file_cache != NULL)
+		file_cache_set_fd(trie->file_cache, trie->fd);
 	return 0;
 }
 
@@ -1387,6 +1389,7 @@ static int squat_trie_map(struct squat_t
 	changed = trie->root.children.offset != trie->hdr.root_offset;
 
 	if (changed || trie->hdr.root_offset == 0) {
+		node_free(trie, &trie->root);
 		memset(&trie->root, 0, sizeof(trie->root));
 		trie->root.want_sequential = TRUE;
 		trie->root.unused_uids = trie->hdr.root_unused_uids;
@@ -1429,6 +1432,8 @@ int squat_trie_build_init(struct squat_t
 			i_error("creat(%s) failed: %m", trie->path);
 			return -1;
 		}
+		if (trie->file_cache != NULL)
+			file_cache_set_fd(trie->file_cache, trie->fd);
 	}
 
 	/* uidlist locks building */
@@ -1557,6 +1562,8 @@ static int squat_trie_write(struct squat
 				i_error("close(%s) failed: %m", trie->path);
 		}
 		trie->fd = fd;
+		if (trie->file_cache != NULL)
+			file_cache_set_fd(trie->file_cache, trie->fd);
 	}
 	return ret;
 }
@@ -1565,7 +1572,7 @@ int squat_trie_build_deinit(struct squat
 			    const ARRAY_TYPE(seq_range) *expunged_uids)
 {
 	struct squat_trie_build_context *ctx = *_ctx;
-	bool compress;
+	bool compress, unlock = TRUE;
 	int ret;
 
 	*_ctx = NULL;
@@ -1577,13 +1584,20 @@ int squat_trie_build_deinit(struct squat
 	   change under. */
 	squat_uidlist_build_flush(ctx->uidlist_build_ctx);
 	ret = squat_trie_renumber_uidlists(ctx, expunged_uids, compress);
-	if (ret == 0)
+	if (ret == 0) {
 		ret = squat_trie_write(ctx);
+		if (ret < 0)
+			unlock = FALSE;
+	}
 
 	if (ret == 0)
 		ret = squat_uidlist_build_finish(ctx->uidlist_build_ctx);
-	if (ctx->file_lock != NULL)
-		file_unlock(&ctx->file_lock);
+	if (ctx->file_lock != NULL) {
+		if (unlock)
+			file_unlock(&ctx->file_lock);
+		else
+			file_lock_free(&ctx->file_lock);
+	}
 	squat_uidlist_build_deinit(&ctx->uidlist_build_ctx);
 
 	i_free(ctx);
diff -r 4674cdad3672 -r 43d2f70fb279 src/plugins/fts-squat/squat-uidlist.c
--- a/src/plugins/fts-squat/squat-uidlist.c	Fri Feb 08 08:46:08 2008 +0200
+++ b/src/plugins/fts-squat/squat-uidlist.c	Sat Feb 09 13:53:54 2008 +0200
@@ -149,6 +149,7 @@ uidlist_write_array(struct ostream *outp
 		base_uid++;
 
 		for (; i < uid_count; i++) {
+			i_assert((uid & ~UID_LIST_MASK_RANGE) >= base_uid);
 			if ((uid & UID_LIST_MASK_RANGE) == 0) {
 				uid -= base_uid;
 				uid2 = uid;
@@ -312,6 +313,12 @@ static int squat_uidlist_map_blocks(stru
 	const void *base;
 	uint32_t block_count, blocks_offset, blocks_size, i, verify_count;
 
+	if (hdr->block_list_offset == 0) {
+		/* empty file */
+		uidlist->cur_block_count = 0;
+		return 1;
+	}
+
 	/* get number of blocks */
 	if (uidlist_file_cache_read(uidlist, hdr->block_list_offset,
 				    sizeof(block_count)) < 0)
@@ -319,7 +326,7 @@ static int squat_uidlist_map_blocks(stru
 	blocks_offset = hdr->block_list_offset + sizeof(block_count);
 	if (blocks_offset > uidlist->data_size) {
 		squat_uidlist_set_corrupted(uidlist, "block list outside file");
-		return -1;
+		return 0;
 	}
 
 	base = CONST_PTR_OFFSET(uidlist->data, hdr->block_list_offset);
@@ -331,7 +338,7 @@ static int squat_uidlist_map_blocks(stru
 		return -1;
 	if (blocks_offset + blocks_size > uidlist->data_size) {
 		squat_uidlist_set_corrupted(uidlist, "block list outside file");
-		return -1;
+		return 0;
 	}
 
 	uidlist->cur_block_count = block_count;
@@ -345,17 +352,17 @@ static int squat_uidlist_map_blocks(stru
 			     uidlist->cur_block_end_indexes[i])) {
 			squat_uidlist_set_corrupted(uidlist,
 				"block list corrupted");
-			return -1;
-		}
-	}
-	return 0;
+			return 0;
+		}
+	}
+	return 1;
 }
 
 static int squat_uidlist_map_header(struct squat_uidlist *uidlist)
 {
 	if (uidlist->hdr.indexid == 0) {
 		/* still being built */
-		return 0;
+		return 1;
 	}
 	if (uidlist->hdr.indexid != uidlist->trie->hdr.indexid) {
 		/* see if trie was recreated */
@@ -363,13 +370,13 @@ static int squat_uidlist_map_header(stru
 	}
 	if (uidlist->hdr.indexid != uidlist->trie->hdr.indexid) {
 		squat_uidlist_set_corrupted(uidlist, "wrong indexid");
-		return -1;
+		return 0;
 	}
 	if (uidlist->hdr.used_file_size < sizeof(uidlist->hdr) ||
 	    (uidlist->hdr.used_file_size > uidlist->mmap_size &&
 	     uidlist->mmap_base != NULL)) {
 		squat_uidlist_set_corrupted(uidlist, "broken used_file_size");
-		return -1;
+		return 0;
 	}
 	return squat_uidlist_map_blocks(uidlist);
 }
@@ -426,7 +433,7 @@ static int squat_uidlist_map(struct squa
 	if (mmap_hdr != NULL && !uidlist->building &&
 	    uidlist->hdr.block_list_offset == mmap_hdr->block_list_offset) {
 		/* file hasn't changed */
-		return 0;
+		return 1;
 	}
 
 	if (!uidlist->trie->mmap_disable) {
@@ -495,7 +502,7 @@ static int squat_uidlist_open(struct squ
 		i_error("open(%s) failed: %m", uidlist->path);
 		return -1;
 	}
-	return squat_uidlist_map(uidlist);
+	return squat_uidlist_map(uidlist) <= 0 ? -1 : 0;
 }
 
 static void squat_uidlist_close(struct squat_uidlist *uidlist)
@@ -524,7 +531,7 @@ int squat_uidlist_refresh(struct squat_u
 		if (squat_uidlist_open(uidlist) < 0)
 			return -1;
 	} else {
-		if (squat_uidlist_map(uidlist) < 0)
+		if (squat_uidlist_map(uidlist) <= 0)
 			return -1;
 	}
 	return 0;
@@ -592,6 +599,8 @@ static int squat_uidlist_lock(struct squ
 
 static int squat_uidlist_open_or_create(struct squat_uidlist *uidlist)
 {
+	int ret;
+
 	if (uidlist->fd == -1) {
 		uidlist->fd = open(uidlist->path, O_RDWR | O_CREAT, 0600);
 		if (uidlist->fd == -1) {
@@ -603,7 +612,9 @@ static int squat_uidlist_open_or_create(
 		return -1;
 
 	if (uidlist->locked_file_size != 0) {
-		if (squat_uidlist_map(uidlist) < 0) {
+		if ((ret = squat_uidlist_map(uidlist)) < 0)
+			return -1;
+		if (ret == 0) {
 			/* broken file, truncate */
 			if (ftruncate(uidlist->fd, 0) < 0) {
 				i_error("ftruncate(%s) failed: %m",
@@ -676,6 +687,15 @@ uidlist_write_block_list_and_header(stru
 	unsigned int align, old_block_count, new_block_count;
 	uint32_t block_offset_count;
 	uoff_t block_list_offset;
+
+	i_assert(uidlist->trie->hdr.indexid != 0);
+	ctx->build_hdr.indexid = uidlist->trie->hdr.indexid;
+
+	if (array_count(block_end_indexes) == 0) {
+		ctx->build_hdr.used_file_size = output->offset;
+		uidlist->hdr = ctx->build_hdr;
+		return;
+	}
 
 	align = output->offset % sizeof(uint32_t);
 	if (align != 0) {
@@ -703,8 +723,6 @@ uidlist_write_block_list_and_header(stru
 	o_stream_flush(output);
 
 	/* update header - it's written later when trie is locked */
-	i_assert(uidlist->trie->hdr.indexid != 0);
-	ctx->build_hdr.indexid = uidlist->trie->hdr.indexid;
 	ctx->build_hdr.block_list_offset = block_list_offset;
 	ctx->build_hdr.used_file_size = output->offset;
 	uidlist->hdr = ctx->build_hdr;
@@ -961,8 +979,7 @@ int squat_uidlist_rebuild_finish(struct 
 
 	if (ctx->list_idx != 0)
 		uidlist_rebuild_flush_block(ctx);
-	if (array_count(&ctx->new_block_end_indexes) == 0 ||
-	    cancel || ctx->uidlist->corrupted)
+	if (cancel || ctx->uidlist->corrupted)
 		ret = 0;
 
 	temp_path = t_strconcat(ctx->uidlist->path, ".tmp", NULL);
@@ -1205,10 +1222,11 @@ squat_uidlist_get_at_offset(struct squat
 squat_uidlist_get_at_offset(struct squat_uidlist *uidlist, uoff_t offset,
 			    uint32_t num, ARRAY_TYPE(uint32_t) *uids)
 {
+	const uint32_t *uid_list;
 	const uint8_t *p, *end;
-	uint32_t size, base_uid;
+	uint32_t size, base_uid, next_uid, flags, prev;
 	uoff_t uidlist_data_offset;
-	unsigned int i, j, extra = 0;
+	unsigned int i, j, count;
 
 	if (num != 0)
 		uidlist_data_offset = offset;
@@ -1236,9 +1254,10 @@ squat_uidlist_get_at_offset(struct squat
 	p = CONST_PTR_OFFSET(uidlist->data, uidlist_data_offset);
 	end = p + size;
 
-	if ((num & UIDLIST_PACKED_FLAG_BEGINS_WITH_POINTER) != 0) {
+	flags = num;
+	if ((flags & UIDLIST_PACKED_FLAG_BEGINS_WITH_POINTER) != 0) {
 		/* link to the file */
-		uint32_t prev = squat_unpack_num(&p, end);
+		prev = squat_unpack_num(&p, end);
 
 		if ((prev & 1) != 0) {
 			/* pointer to uidlist */
@@ -1251,11 +1270,23 @@ squat_uidlist_get_at_offset(struct squat
 							0, uids) < 0)
 				return -1;
 		}
-	}
-
-	if ((num & UIDLIST_PACKED_FLAG_BITMASK) != 0) {
+		uid_list = array_get(uids, &count);
+		next_uid = count == 0 ? 0 : uid_list[count-1] + 1;
+	} else {
+		next_uid = 0;
+	}
+
+	num = base_uid = squat_unpack_num(&p, end);
+	if ((flags & UIDLIST_PACKED_FLAG_BITMASK) == 0)
+		base_uid >>= 1;
+	if (base_uid < next_uid) {
+		squat_uidlist_set_corrupted(uidlist,
+					    "broken continued uidlist");
+		return -1;
+	}
+
+	if ((flags & UIDLIST_PACKED_FLAG_BITMASK) != 0) {
 		/* bitmask */
-		base_uid = squat_unpack_num(&p, end);
 		size = end - p;
 
 		uidlist_array_append(uids, base_uid++);
@@ -1267,10 +1298,7 @@ squat_uidlist_get_at_offset(struct squat
 		}
 	} else {
 		/* range */
-		base_uid = 0;
-		while (p < end) {
-			num = squat_unpack_num(&p, end);
-			base_uid += (num >> 1) + extra;
+		for (;;) {
 			if ((num & 1) == 0) {
 				uidlist_array_append(uids, base_uid);


More information about the dovecot-cvs mailing list