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