# HG changeset patch # User Timo Sirainen # Date 1220167330 -10800 # Node ID b97c3be33b04ba53f9cdabb086695f612a0e6ce8 # Parent 612eb505775fd75094faa9f00db13bf92de03cd5 Replaced "no extension resizing" flag with "no extension shrinking". It fixes some bugs while still handling the original reason it was added. diff -r 612eb505775f -r b97c3be33b04 src/lib-index/mail-index-sync-ext.c --- a/src/lib-index/mail-index-sync-ext.c Sun Aug 31 09:31:27 2008 +0300 +++ b/src/lib-index/mail-index-sync-ext.c Sun Aug 31 10:22:10 2008 +0300 @@ -260,13 +260,14 @@ static void sync_ext_resize(const struct mail_transaction_ext_intro *u, - uint32_t ext_map_idx, struct mail_index_sync_map_ctx *ctx) + uint32_t ext_map_idx, struct mail_index_sync_map_ctx *ctx, + bool no_shrink) { struct mail_index_map *map = ctx->view->map; struct mail_index_ext *ext; struct mail_index_ext_header *ext_hdr; uint32_t old_size, new_size, old_record_size; - bool modified = FALSE; + bool modified = FALSE, reorder = FALSE; ext = array_idx_modifiable(&map->extensions, ext_map_idx); @@ -275,25 +276,38 @@ if (new_size < old_size) { /* header shrank */ - buffer_delete(map->hdr_copy_buf, ext->hdr_offset + new_size, - old_size - new_size); - modified = TRUE; + if (!no_shrink) { + new_size = old_size; + buffer_delete(map->hdr_copy_buf, + ext->hdr_offset + new_size, + old_size - new_size); + ext->hdr_size = u->hdr_size; + modified = TRUE; + } } else if (new_size > old_size) { /* header grown */ buffer_insert_zero(map->hdr_copy_buf, ext->hdr_offset + old_size, new_size - old_size); + ext->hdr_size = u->hdr_size; modified = TRUE; } map->hdr_base = map->hdr_copy_buf->data; + if (ext->record_align < u->record_align || + (ext->record_align > u->record_align && !no_shrink)) { + ext->record_align = u->record_align; + modified = TRUE; + reorder = TRUE; + } + old_record_size = ext->record_size; - ext->hdr_size = u->hdr_size; - ext->record_size = u->record_size; - ext->record_align = u->record_align; - - if (old_record_size != u->record_size) + if (ext->record_size < u->record_size || + (ext->record_size > u->record_size && !no_shrink)) { + ext->record_size = u->record_size; modified = TRUE; + reorder = TRUE; + } if (modified) { i_assert((map->hdr_copy_buf->used % sizeof(uint64_t)) == 0); @@ -321,7 +335,7 @@ } } - if (old_record_size != u->record_size) { + if (reorder) { map = mail_index_sync_get_atomic_map(ctx); sync_ext_reorder(map, ext_map_idx, old_record_size); } else if (modified) { @@ -426,7 +440,7 @@ u.hdr_size = rext->hdr_size; u.record_size = rext->record_size; u.record_align = rext->record_align; - sync_ext_resize(&u, *ext_map_idx_r, ctx); + sync_ext_resize(&u, *ext_map_idx_r, ctx, FALSE); } else { memset(&ext_hdr, 0, sizeof(ext_hdr)); ext_hdr.name_size = strlen(name); @@ -446,7 +460,7 @@ const struct mail_index_ext *ext; const char *name, *error; uint32_t ext_map_idx; - bool no_resize; + bool no_shrink; /* default to ignoring the following extension updates in case this intro is corrupted */ @@ -497,7 +511,7 @@ ext_hdr.hdr_size = u->hdr_size; ext_hdr.record_size = u->record_size; ext_hdr.record_align = u->record_align; - no_resize = (u->flags & MAIL_TRANSACTION_EXT_INTRO_FLAG_NO_RESIZE) != 0; + no_shrink = (u->flags & MAIL_TRANSACTION_EXT_INTRO_FLAG_NO_SHRINK) != 0; /* make sure the header looks valid before doing anything with it */ if (mail_index_map_ext_hdr_check(&map->hdr, &ext_hdr, @@ -511,8 +525,7 @@ /* exists already */ if (u->reset_id == ext->reset_id) { /* check if we need to resize anything */ - if (!no_resize) - sync_ext_resize(u, ext_map_idx, ctx); + sync_ext_resize(u, ext_map_idx, ctx, no_shrink); ctx->cur_ext_ignore = FALSE; } else { /* extension was reset and this transaction hadn't @@ -598,6 +611,8 @@ return 1; ext = array_idx(&map->extensions, ctx->cur_ext_map_idx); + i_assert(ext->hdr_offset + u->offset + u->size <= map->hdr.header_size); + buffer_write(map->hdr_copy_buf, ext->hdr_offset + u->offset, u + 1, u->size); map->hdr_base = map->hdr_copy_buf->data; @@ -634,6 +649,8 @@ return 1; ext = array_idx(&view->map->extensions, ctx->cur_ext_map_idx); + i_assert(ext->record_offset + ext->record_size <= + view->map->hdr.record_size); rec = MAIL_INDEX_MAP_IDX(view->map, seq-1); old_data = PTR_OFFSET(rec, ext->record_offset); diff -r 612eb505775f -r b97c3be33b04 src/lib-index/mail-transaction-log-append.c --- a/src/lib-index/mail-transaction-log-append.c Sun Aug 31 09:31:27 2008 +0300 +++ b/src/lib-index/mail-transaction-log-append.c Sun Aug 31 10:22:10 2008 +0300 @@ -271,7 +271,7 @@ intro->hdr_size = rext->hdr_size; intro->record_size = rext->record_size; intro->record_align = rext->record_align; - intro->flags = MAIL_TRANSACTION_EXT_INTRO_FLAG_NO_RESIZE; + intro->flags = MAIL_TRANSACTION_EXT_INTRO_FLAG_NO_SHRINK; intro->name_size = idx != (uint32_t)-1 ? 0 : strlen(rext->name); } diff -r 612eb505775f -r b97c3be33b04 src/lib-index/mail-transaction-log.h --- a/src/lib-index/mail-transaction-log.h Sun Aug 31 09:31:27 2008 +0300 +++ b/src/lib-index/mail-transaction-log.h Sun Aug 31 10:22:10 2008 +0300 @@ -88,8 +88,9 @@ }; enum { - /* Ignore hdr_size, record_size and record_align */ - MAIL_TRANSACTION_EXT_INTRO_FLAG_NO_RESIZE = 0x01 + /* Don't shrink hdr_size, record_size or record_align but grow them + if necessary. */ + MAIL_TRANSACTION_EXT_INTRO_FLAG_NO_SHRINK = 0x01 }; struct mail_transaction_ext_intro {