]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
mail_index_update_header_ext() can now be called multiple times for the same
authorTimo Sirainen <tss@iki.fi>
Wed, 18 Jun 2008 05:09:33 +0000 (08:09 +0300)
committerTimo Sirainen <tss@iki.fi>
Wed, 18 Jun 2008 05:09:33 +0000 (08:09 +0300)
extension.

--HG--
branch : HEAD

src/lib-index/mail-index-transaction-private.h
src/lib-index/mail-index-transaction.c
src/lib-index/mail-transaction-log-append.c

index c6b47e3dfee81e88ad74502302a823d78cbd8713..c668f6e106a915d020134f38a4dab5a5d26f1af7 100644 (file)
@@ -10,10 +10,10 @@ struct mail_index_transaction_keyword_update {
 };
 
 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 @@ struct mail_index_transaction {
        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);
index c86bd2c4715d9f625272f433115b26e769904199..5100625bbafe0f2b0a6f638968688e6814a0f581 100644 (file)
@@ -27,7 +27,7 @@ mail_index_transaction_has_ext_changes(struct mail_index_transaction *t);
 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 @@ void mail_index_transaction_reset(struct mail_index_transaction *t)
        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 @@ mail_index_transaction_has_ext_changes(struct mail_index_transaction *t)
                }
        }
        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 @@ void mail_index_ext_set_reset_id(struct mail_index_transaction *t,
        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 @@ void mail_index_update_header_ext(struct mail_index_transaction *t,
                                  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;
 }
index ced0c4dd1fcc8f0eac8121a2537f7b9bb631d05e..1fb47f3db2cb157aab077fa97e0358014956acb8 100644 (file)
@@ -289,18 +289,35 @@ static void log_append_ext_intro(struct log_append_context *ctx,
 
 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;
-
-       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);
+       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;
+
+       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 @@ mail_transaction_log_append_ext_intros(struct log_append_context *ctx)
 {
        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 @@ mail_transaction_log_append_ext_intros(struct log_append_context *ctx)
                    (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 @@ mail_transaction_log_append_ext_intros(struct log_append_context *ctx)
                        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;
                }
        }