From: Timo Sirainen Date: Fri, 3 Jun 2016 14:54:36 +0000 (+0300) Subject: lib-index: Allow growing ext record_size after mail_index_update_ext() X-Git-Tag: 2.2.25.rc1~194 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e6696669bff159e93dc040f1c8574e938348353c;p=thirdparty%2Fdovecot%2Fcore.git lib-index: Allow growing ext record_size after mail_index_update_ext() The existing records will just get some zero-padding at the end of records. --- diff --git a/src/lib-index/mail-index-transaction-update.c b/src/lib-index/mail-index-transaction-update.c index ac1cf62bc5..38f9905b97 100644 --- a/src/lib-index/mail-index-transaction-update.c +++ b/src/lib-index/mail-index-transaction-update.c @@ -713,6 +713,33 @@ void mail_index_update_header(struct mail_index_transaction *t, } } +static void +mail_index_ext_rec_updates_resize(struct mail_index_transaction *t, + uint32_t ext_id, uint16_t new_record_size) +{ + ARRAY_TYPE(seq_array) *array, old_array; + unsigned int i; + + if (!array_is_created(&t->ext_rec_updates)) + return; + array = array_idx_modifiable(&t->ext_rec_updates, ext_id); + if (!array_is_created(array)) + return; + + old_array = *array; + memset(array, 0, sizeof(*array)); + mail_index_seq_array_alloc(array, new_record_size); + + /* copy the records' beginnings. leave the end zero-filled. */ + for (i = 0; i < array_count(&old_array); i++) { + const void *old_record = array_idx(&old_array, i); + + memcpy(array_append_space(array), old_record, + old_array.arr.element_size); + } + array_free(&old_array); +} + void mail_index_ext_resize(struct mail_index_transaction *t, uint32_t ext_id, uint32_t hdr_size, uint16_t record_size, uint16_t record_align) @@ -741,12 +768,13 @@ void mail_index_ext_resize(struct mail_index_transaction *t, uint32_t ext_id, old_header_size = ext->hdr_size; } - /* allow only header size changes if extension records have already - been changed in transaction */ - i_assert(!array_is_created(&t->ext_rec_updates) || - record_size == (uint16_t)-1 || - (old_record_size == record_size && - old_record_align == record_align)); + if (record_size != old_record_size) { + /* if record_size grows, we'll just resize the existing + ext_rec_updates array. it's not possible to shrink + record_size without data loss. */ + i_assert(record_size > old_record_size); + mail_index_ext_rec_updates_resize(t, ext_id, record_size); + } t->log_ext_updates = TRUE; diff --git a/src/lib-index/mail-index-util.c b/src/lib-index/mail-index-util.c index b633539588..659d622764 100644 --- a/src/lib-index/mail-index-util.c +++ b/src/lib-index/mail-index-util.c @@ -116,6 +116,18 @@ bool mail_index_seq_array_lookup(const ARRAY_TYPE(seq_array) *array, mail_index_seq_record_cmp, idx_r); } +void mail_index_seq_array_alloc(ARRAY_TYPE(seq_array) *array, + size_t record_size) +{ + size_t aligned_record_size = (record_size + 3) & ~3; + + i_assert(!array_is_created(array)); + + array_create(array, default_pool, + sizeof(uint32_t) + aligned_record_size, + 1024 / (sizeof(uint32_t) + aligned_record_size)); +} + bool mail_index_seq_array_add(ARRAY_TYPE(seq_array) *array, uint32_t seq, const void *record, size_t record_size, void *old_record) @@ -126,11 +138,8 @@ bool mail_index_seq_array_add(ARRAY_TYPE(seq_array) *array, uint32_t seq, /* records need to be 32bit aligned */ aligned_record_size = (record_size + 3) & ~3; - if (!array_is_created(array)) { - array_create(array, default_pool, - sizeof(seq) + aligned_record_size, - 1024 / (sizeof(seq) + aligned_record_size)); - } + if (!array_is_created(array)) + mail_index_seq_array_alloc(array, record_size); i_assert(array->arr.element_size == sizeof(seq) + aligned_record_size); if (mail_index_seq_array_lookup(array, seq, &idx)) { diff --git a/src/lib-index/mail-index-util.h b/src/lib-index/mail-index-util.h index eeb17e9499..b61e16a23a 100644 --- a/src/lib-index/mail-index-util.h +++ b/src/lib-index/mail-index-util.h @@ -13,6 +13,8 @@ int mail_index_unpack_num(const uint8_t **p, const uint8_t *end, bool mail_index_seq_array_lookup(const ARRAY_TYPE(seq_array) *array, uint32_t seq, unsigned int *idx_r); +void mail_index_seq_array_alloc(ARRAY_TYPE(seq_array) *array, + size_t record_size); bool mail_index_seq_array_add(ARRAY_TYPE(seq_array) *array, uint32_t seq, const void *record, size_t record_size, void *old_record) ATTR_NULL(5);