# HG changeset patch # User Timo Sirainen # Date 1213765773 -10800 # Node ID efb782e078b953263dac77365b92ef559db2b9d8 # Parent 5bedea448cf97df1a345ec877857c77d61dee7a9 mail_index_update_header_ext() can now be called multiple times for the same extension. diff -r 5bedea448cf9 -r efb782e078b9 src/lib-index/mail-index-transaction-private.h --- a/src/lib-index/mail-index-transaction-private.h Wed Jun 18 08:08:45 2008 +0300 +++ b/src/lib-index/mail-index-transaction-private.h Wed Jun 18 08:09:33 2008 +0300 @@ -10,10 +10,10 @@ }; struct mail_index_transaction_ext_hdr_update { - uint32_t ext_id; - uint16_t offset; - uint16_t size; - /* unsigned char data[]; */ + size_t alloc_size; + /* mask is in bytes, not bits */ + unsigned char *mask; + unsigned char *data; }; struct mail_index_transaction_vfuncs { @@ -48,7 +48,7 @@ unsigned char post_hdr_mask[sizeof(struct mail_index_header)]; ARRAY_DEFINE(ext_hdr_updates, - struct mail_index_transaction_ext_hdr_update *); + struct mail_index_transaction_ext_hdr_update); ARRAY_DEFINE(ext_rec_updates, ARRAY_TYPE(seq_array)); ARRAY_DEFINE(ext_resizes, struct mail_transaction_ext_intro); ARRAY_DEFINE(ext_resets, struct mail_transaction_ext_reset); diff -r 5bedea448cf9 -r efb782e078b9 src/lib-index/mail-index-transaction.c --- a/src/lib-index/mail-index-transaction.c Wed Jun 18 08:08:45 2008 +0300 +++ b/src/lib-index/mail-index-transaction.c Wed Jun 18 08:09:33 2008 +0300 @@ -27,7 +27,7 @@ void mail_index_transaction_reset(struct mail_index_transaction *t) { ARRAY_TYPE(seq_array) *recs; - struct mail_index_transaction_ext_hdr_update **ext_hdrs; + struct mail_index_transaction_ext_hdr_update *ext_hdrs; unsigned i, count; if (array_is_created(&t->ext_rec_updates)) { @@ -42,8 +42,10 @@ if (array_is_created(&t->ext_hdr_updates)) { ext_hdrs = array_get_modifiable(&t->ext_hdr_updates, &count); - for (i = 0; i < count; i++) - i_free(ext_hdrs[i]); + for (i = 0; i < count; i++) { + i_free(ext_hdrs[i].data); + i_free(ext_hdrs[i].mask); + } array_free(&t->ext_hdr_updates); } @@ -1134,11 +1136,11 @@ } } if (array_is_created(&t->ext_hdr_updates)) { - struct mail_index_transaction_ext_hdr_update *const *hdr; + const struct mail_index_transaction_ext_hdr_update *hdr; hdr = array_get(&t->ext_hdr_updates, &count); for (i = 0; i < count; i++) { - if (hdr[i] != NULL) + if (hdr[i].alloc_size > 0) return TRUE; } } @@ -1178,11 +1180,14 @@ if (array_is_created(&t->ext_hdr_updates) && ext_id < array_count(&t->ext_hdr_updates)) { /* if extension headers have been updated, clear them */ - struct mail_index_transaction_ext_hdr_update **hdr; + struct mail_index_transaction_ext_hdr_update *hdr; hdr = array_idx_modifiable(&t->ext_hdr_updates, ext_id); - if (*hdr != NULL) - i_free_and_null(*hdr); + if (hdr->alloc_size > 0) { + i_free_and_null(hdr->mask); + i_free_and_null(hdr->data); + } + hdr->alloc_size = 0; } if (array_is_created(&t->ext_resets) && ext_id < array_count(&t->ext_resets)) { @@ -1206,23 +1211,25 @@ uint32_t ext_id, size_t offset, const void *data, size_t size) { - struct mail_index_transaction_ext_hdr_update *hdr, **pos; + struct mail_index_transaction_ext_hdr_update *hdr; + size_t new_size; - hdr = i_malloc(sizeof(*hdr) + size); - hdr->ext_id = ext_id; - hdr->offset = offset; - hdr->size = size; - memcpy(hdr + 1, data, size); + i_assert(offset <= (uint16_t)-1 && size <= (uint16_t)-1 && + offset + size <= (uint16_t)-1); if (!array_is_created(&t->ext_hdr_updates)) i_array_init(&t->ext_hdr_updates, ext_id + 2); - pos = array_idx_modifiable(&t->ext_hdr_updates, ext_id); - if (*pos != NULL) { - i_panic("mail_index_update_header_ext() doesn't currently " - "support multiple updates to the same ext header"); + hdr = array_idx_modifiable(&t->ext_hdr_updates, ext_id); + if (hdr->alloc_size < offset || hdr->alloc_size - offset < size) { + i_assert(size < (size_t)-1 - offset); + new_size = nearest_power(offset + size); + hdr->mask = i_realloc(hdr->mask, hdr->alloc_size, new_size); + hdr->data = i_realloc(hdr->data, hdr->alloc_size, new_size); + hdr->alloc_size = new_size; } - *pos = hdr; + memset(hdr->mask + offset, 1, size); + memcpy(hdr->data + offset, data, size); t->log_ext_updates = TRUE; } diff -r 5bedea448cf9 -r efb782e078b9 src/lib-index/mail-transaction-log-append.c --- a/src/lib-index/mail-transaction-log-append.c Wed Jun 18 08:08:45 2008 +0300 +++ b/src/lib-index/mail-transaction-log-append.c Wed Jun 18 08:09:33 2008 +0300 @@ -289,18 +289,35 @@ static void log_append_ext_hdr_update(struct log_append_context *ctx, - struct mail_index_transaction_ext_hdr_update *hdr) + const struct mail_index_transaction_ext_hdr_update *hdr) { - struct mail_transaction_ext_hdr_update *trans_hdr; buffer_t *buf; - unsigned int hdr_size; + const unsigned char *data, *mask; + struct mail_transaction_ext_hdr_update u; + uint16_t offset; + bool started = FALSE; + + memset(&u, 0, sizeof(u)); + + data = hdr->data; + mask = hdr->mask; - hdr_size = sizeof(*trans_hdr) + hdr->size + 4; - buf = buffer_create_static_hard(pool_datastack_create(), hdr_size); - trans_hdr = buffer_append_space_unsafe(buf, sizeof(*trans_hdr)); - trans_hdr->offset = hdr->offset; - trans_hdr->size = hdr->size; - buffer_append(buf, hdr + 1, hdr->size); + buf = buffer_create_dynamic(pool_datastack_create(), 256); + for (offset = 0; offset <= hdr->alloc_size; offset++) { + if (offset < hdr->alloc_size && mask[offset] != 0) { + if (!started) { + u.offset = offset; + started = TRUE; + } + } else { + if (started) { + u.size = offset - u.offset; + buffer_append(buf, &u, sizeof(u)); + buffer_append(buf, data + u.offset, u.size); + started = FALSE; + } + } + } if (buf->used % 4 != 0) buffer_append_zero(buf, 4 - buf->used % 4); log_append_buffer(ctx, buf, NULL, MAIL_TRANSACTION_EXT_HDR_UPDATE); @@ -311,7 +328,7 @@ { struct mail_index_transaction *t = ctx->trans; const struct mail_transaction_ext_intro *resize; - struct mail_index_transaction_ext_hdr_update *const *hdrs; + const struct mail_index_transaction_ext_hdr_update *hdrs; struct mail_transaction_ext_reset ext_reset; unsigned int update_count, resize_count, ext_count = 0; unsigned int hdrs_count, reset_id_count, reset_count; @@ -377,7 +394,7 @@ (ext_id < update_count && array_is_created(&update[ext_id])) || ext_reset.new_reset_id != 0 || - (ext_id < hdrs_count && hdrs[ext_id] != NULL)) { + (ext_id < hdrs_count && hdrs[ext_id].alloc_size > 0)) { reset_id = ext_id < reset_id_count && ext_reset.new_reset_id == 0 ? reset_ids[ext_id] : 0; @@ -389,9 +406,9 @@ log_append_buffer(ctx, buf, NULL, MAIL_TRANSACTION_EXT_RESET); } - if (ext_id < hdrs_count && hdrs[ext_id] != NULL) { + if (ext_id < hdrs_count && hdrs[ext_id].alloc_size > 0) { T_BEGIN { - log_append_ext_hdr_update(ctx, hdrs[ext_id]); + log_append_ext_hdr_update(ctx, &hdrs[ext_id]); } T_END; } }