]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Added support for per-index sized mail_index_record.
authorTimo Sirainen <tss@iki.fi>
Sun, 13 Jun 2004 23:38:47 +0000 (02:38 +0300)
committerTimo Sirainen <tss@iki.fi>
Sun, 13 Jun 2004 23:38:47 +0000 (02:38 +0300)
--HG--
branch : HEAD

13 files changed:
src/lib-index/mail-index-fsck.c
src/lib-index/mail-index-lock.c
src/lib-index/mail-index-private.h
src/lib-index/mail-index-sync-update.c
src/lib-index/mail-index-sync.c
src/lib-index/mail-index-transaction.c
src/lib-index/mail-index-view-sync.c
src/lib-index/mail-index-view.c
src/lib-index/mail-index.c
src/lib-index/mail-index.h
src/lib-index/mail-transaction-log.c
src/lib-index/mail-transaction-util.c
src/lib-index/mail-transaction-util.h

index 76bb8599a29c9433a23153e9d69ecd96ed6b817f..b392065c38cb9db2b3d79416653d070733a082f4 100644 (file)
@@ -27,8 +27,8 @@ static int mail_index_fsck_locked(struct mail_index *index,
                                  const char **error_r)
 {
        struct mail_index_header hdr;
-       const struct mail_index_record *rec, *end;
-       uint32_t last_uid;
+       const struct mail_index_record *rec;
+       uint32_t i, last_uid;
 
        *error_r = NULL;
 
@@ -49,8 +49,8 @@ static int mail_index_fsck_locked(struct mail_index *index,
        hdr.first_unseen_uid_lowwater = 0;
        hdr.first_deleted_uid_lowwater = 0;
 
-       end = index->map->records + index->map->records_count; last_uid = 0;
-       for (rec = index->map->records; rec != end; rec++) {
+       rec = index->map->records; last_uid = 0;
+       for (i = 0; i < index->map->records_count; i++) {
                if (rec->uid <= last_uid) {
                        *error_r = "Record UIDs are not ordered";
                        return 0;
@@ -75,6 +75,7 @@ static int mail_index_fsck_locked(struct mail_index *index,
                        hdr.first_deleted_uid_lowwater = rec->uid;
 
                last_uid = rec->uid;
+               rec = CONST_PTR_OFFSET(rec, index->record_size);
        }
 
        if (hdr.next_uid <= last_uid) {
index 11da7a3cde4940a491736a364ed7576f25a79b53..26d0adfc884ffde08e00fa4787470a188c277077 100644 (file)
@@ -187,7 +187,7 @@ static int mail_index_copy(struct mail_index *index)
        ret = write_full(fd, index->map->hdr, sizeof(*index->map->hdr));
        if (ret < 0 || write_full(fd, index->map->records,
                                  index->map->records_count *
-                                 sizeof(struct mail_index_record)) < 0) {
+                                 index->record_size) < 0) {
                mail_index_file_set_syscall_error(index, path, "write_full()");
                (void)close(fd);
                (void)unlink(path);
index 36bd22241ae2a2db8f8b0525534734fda7096a8a..fb13a8319af2ff55798ab07d50971bc156d0dac9 100644 (file)
@@ -17,11 +17,15 @@ struct mail_transaction_header;
 #define MAIL_INDEX_MAP_IS_IN_MEMORY(map) \
        ((map)->buffer != NULL)
 
+#define MAIL_INDEX_MAP_IDX(index, map, idx) \
+       ((struct mail_index_record *) \
+               PTR_OFFSET((map)->records, (idx) * (index)->record_size))
+
 struct mail_index_map {
        int refcount;
 
        const struct mail_index_header *hdr;
-       struct mail_index_record *records;
+       void *records; /* struct mail_index_record[] */
        unsigned int records_count;
 
        void *mmap_base;
@@ -45,6 +49,7 @@ struct mail_index {
 
        mode_t mode;
        gid_t gid;
+       unsigned int record_size;
 
        char *filepath;
        int fd;
@@ -99,7 +104,8 @@ int mail_index_map_lock_mprotect(struct mail_index *index,
 int mail_index_map(struct mail_index *index, int force);
 /* Unreference given mapping and unmap it if it's dropped to zero. */
 void mail_index_unmap(struct mail_index *index, struct mail_index_map *map);
-struct mail_index_map *mail_index_map_to_memory(struct mail_index_map *map);
+struct mail_index_map *
+mail_index_map_to_memory(struct mail_index *index, struct mail_index_map *map);
 
 void mail_index_update_cache(struct mail_index_transaction *t,
                             uint32_t seq, uint32_t offset);
index 57fcbbbcb5f5ad1035a3922a0f28a10ada131a2f..cd475aadee7b298cf2e76505b2262eedf1915a1c 100644 (file)
@@ -56,6 +56,7 @@ mail_index_header_update_lowwaters(struct mail_index_header *hdr,
 static void mail_index_sync_expunge(struct mail_index_view *view,
                                    const struct mail_transaction_expunge *e)
 {
+       struct mail_index *index = view->index;
        struct mail_index_map *map = view->map;
        struct mail_index_header *hdr = &map->hdr_copy;
        struct mail_index_record *rec;
@@ -70,22 +71,24 @@ static void mail_index_sync_expunge(struct mail_index_view *view,
        if (seq1 == 0)
                return;
 
-       rec = &map->records[seq1-1];
-       for (seq = seq1; seq <= seq2; seq++, rec++)
+       for (seq = seq1; seq <= seq2; seq++) {
+                rec = MAIL_INDEX_MAP_IDX(index, map, seq-1);
                mail_index_header_update_counts(hdr, rec->flags, 0);
+       }
 
        /* @UNSAFE */
        count = seq2 - seq1 + 1;
-       memcpy(map->records + (seq1-1), map->records + seq2,
-              (map->records_count - seq2) * sizeof(*map->records));
+       memcpy(MAIL_INDEX_MAP_IDX(index, map, seq-1),
+               MAIL_INDEX_MAP_IDX(index, map, seq2),
+              (map->records_count - seq2) * view->index->record_size);
 
        map->records_count -= count;
        hdr->messages_count -= count;
        view->messages_count -= count;
 
        if (map->buffer != NULL) {
-               buffer_set_used_size(map->buffer,
-                                    map->records_count * sizeof(*rec));
+               buffer_set_used_size(map->buffer, map->records_count *
+                                    view->index->record_size);
                map->records = buffer_get_modifyable_data(map->buffer, NULL);
        }
 }
@@ -101,6 +104,7 @@ static int sync_expunge(const struct mail_transaction_expunge *e, void *context)
 static int sync_append(const struct mail_index_record *rec, void *context)
 {
        struct mail_index_view *view = context;
+       struct mail_index *index = view->index;
        struct mail_index_map *map = view->map;
 
        if (rec->uid < map->hdr_copy.next_uid) {
@@ -111,14 +115,15 @@ static int sync_append(const struct mail_index_record *rec, void *context)
        }
 
        if (MAIL_INDEX_MAP_IS_IN_MEMORY(map)) {
-               i_assert(map->records_count * sizeof(*rec) ==
+               i_assert(map->records_count * index->record_size ==
                         buffer_get_used_size(map->buffer));
-               buffer_append(map->buffer, rec, sizeof(*rec));
+               buffer_append(map->buffer, rec, index->record_size);
                map->records = buffer_get_modifyable_data(map->buffer, NULL);
        } else {
-               i_assert((map->records_count+1) * sizeof(*rec) <=
+               i_assert((map->records_count+1) * index->record_size <=
                         map->mmap_size);
-               map->records[map->records_count] = *rec;
+               memcpy(MAIL_INDEX_MAP_IDX(index, map, map->records_count),
+                      rec, index->record_size);
        }
 
        map->hdr_copy.messages_count++;
@@ -135,12 +140,12 @@ static int sync_flag_update(const struct mail_transaction_flag_update *u,
                            void *context)
 {
         struct mail_index_view *view = context;
-       struct mail_index_record *rec, *end;
+       struct mail_index_record *rec;
        struct mail_index_header *hdr;
        uint8_t flag_mask, old_flags;
        keywords_mask_t keyword_mask;
-       uint32_t seq1, seq2;
-       int i, update_keywords, ret;
+       uint32_t i, seq1, seq2;
+       int update_keywords, ret;
 
        ret = mail_index_lookup_uid_range(view, u->uid1, u->uid2, &seq1, &seq2);
        i_assert(ret == 0);
@@ -162,9 +167,9 @@ static int sync_flag_update(const struct mail_transaction_flag_update *u,
        }
         flag_mask = ~u->remove_flags;
 
-       rec = &view->map->records[seq1-1];
-       end = rec + (seq2 - seq1) + 1;
-       for (; rec != end; rec++) {
+       for (i = seq1-1; i < seq2; i++) {
+                rec = MAIL_INDEX_MAP_IDX(view->index, view->map, i);
+
                old_flags = rec->flags;
                rec->flags = (rec->flags & flag_mask) | u->add_flags;
                if (update_keywords) {
@@ -191,8 +196,10 @@ static int sync_cache_update(const struct mail_transaction_cache_update *u,
                                          &seq, &seq);
        i_assert(ret == 0);
 
-       if (seq != 0)
-               view->map->records[seq-1].cache_offset = u->cache_offset;
+       if (seq != 0) {
+               MAIL_INDEX_MAP_IDX(view->index, view->map, seq-1)->
+                       cache_offset = u->cache_offset;
+       }
        return 1;
 }
 
@@ -218,7 +225,7 @@ static int mail_index_grow(struct mail_index *index, struct mail_index_map *map,
        i_assert(map == index->map);
 
        size = map->hdr->header_size +
-               (map->records_count + count) * sizeof(struct mail_index_record);
+               (map->records_count + count) * index->record_size;
        if (size <= map->mmap_size)
                return 0;
 
@@ -230,7 +237,7 @@ static int mail_index_grow(struct mail_index *index, struct mail_index_map *map,
        index->last_grow_count = count;
 
        size = map->hdr->header_size +
-               (map->records_count + count) * sizeof(struct mail_index_record);
+               (map->records_count + count) * index->record_size;
        if (file_set_size(index->fd, (off_t)size) < 0)
                return mail_index_set_syscall_error(index, "file_set_size()");
 
@@ -282,7 +289,7 @@ int mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx)
                           replace the whole index file. to avoid extra disk
                           I/O we copy the index into memory rather than to
                           temporary file */
-                       map = mail_index_map_to_memory(map);
+                       map = mail_index_map_to_memory(index, map);
                        mail_index_unmap(index, view->map);
                        view->map = map;
                        view->map->refcount++;
@@ -293,12 +300,13 @@ int mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx)
                }
 
                if ((hdr->type & MAIL_TRANSACTION_APPEND) != 0) {
-                       count = hdr->size / sizeof(struct mail_index_record);
+                       count = hdr->size / index->record_size;
                        if (mail_index_grow(index, view->map, count) < 0)
                                return -1;
                }
 
-               if (mail_transaction_map(hdr, data, &mail_index_map_sync_funcs,
+               if (mail_transaction_map(index, hdr, data,
+                                        &mail_index_map_sync_funcs,
                                         view) < 0) {
                        ret = -1;
                        break;
@@ -316,9 +324,11 @@ int mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx)
        if ((map->hdr_copy.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) == 0 &&
            had_dirty) {
                /* do we have dirty flags anymore? */
+               const struct mail_index_record *rec;
+
                for (i = 0; i < map->records_count; i++) {
-                       if ((map->records[i].flags &
-                            MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) {
+                       rec = MAIL_INDEX_MAP_IDX(index, map, i);
+                       if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) {
                                map->hdr_copy.flags |=
                                        MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
                                break;
@@ -328,7 +338,7 @@ int mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx)
 
        if (!MAIL_INDEX_MAP_IS_IN_MEMORY(map)) {
                map->mmap_used_size = index->hdr->header_size +
-                       map->records_count * sizeof(struct mail_index_record);
+                       map->records_count * index->record_size;
 
                memcpy(map->mmap_base, &map->hdr_copy, sizeof(map->hdr_copy));
                if (msync(map->mmap_base, map->mmap_used_size, MS_SYNC) < 0) {
index 9bebeb7e74b9fe5f5fc45b81711aae734b5d0c58..d025ecdea8649fdde7d7eaaac6c04c095593e102 100644 (file)
@@ -297,7 +297,7 @@ int mail_index_sync_next(struct mail_index_sync_ctx *ctx,
                sync_rec->type = MAIL_INDEX_SYNC_TYPE_APPEND;
                sync_rec->appends = buffer_get_data(ctx->appends_buf,
                                                    &sync_rec->appends_count);
-               sync_rec->appends_count /= sizeof(*sync_rec->appends);
+               sync_rec->appends_count /= ctx->index->record_size;
                sync_rec->uid1 = sync_rec->uid2 = 0;
                return 1;
        }
index 89db21ae8dafa112064a4d8ac05e799e8c86cd34..ea9d85e4475be2aa1657f9229d9366cf6025eb75 100644 (file)
@@ -54,9 +54,12 @@ mail_index_buffer_convert_to_uids(struct mail_index_view *view,
        for (i = 0; i < size; i += record_size) {
                seq = (uint32_t *)&data[i];
 
-               seq[0] = view->map->records[seq[0]-1].uid;
-               if (range)
-                       seq[1] = view->map->records[seq[1]-1].uid;
+               seq[0] = MAIL_INDEX_MAP_IDX(view->index, view->map,
+                                           seq[0]-1)->uid;
+               if (range) {
+                       seq[1] = MAIL_INDEX_MAP_IDX(view->index, view->map,
+                                                   seq[1]-1)->uid;
+               }
        }
 }
 
@@ -124,8 +127,9 @@ void mail_index_append(struct mail_index_transaction *t, uint32_t uid,
                        mail_index_view_get_message_count(t->view)+1;
        }
 
-       rec = buffer_append_space_unsafe(t->appends, sizeof(*rec));
-       memset(rec, 0, sizeof(*rec));
+       rec = buffer_append_space_unsafe(t->appends,
+                                        t->view->index->record_size);
+       memset(rec, 0, t->view->index->record_size);
        rec->uid = uid;
 }
 
@@ -262,8 +266,9 @@ void mail_index_update_flags(struct mail_index_transaction *t, uint32_t seq,
                /* just appended message, modify it directly */
                i_assert(seq > 0 && seq <= t->last_new_seq);
 
-               pos = (seq - t->first_new_seq) * sizeof(*rec);
-               rec = buffer_get_space_unsafe(t->appends, pos, sizeof(*rec));
+               pos = (seq - t->first_new_seq) * t->view->index->record_size;
+               rec = buffer_get_space_unsafe(t->appends, pos,
+                                             t->view->index->record_size);
                mail_index_record_modify_flags(rec, modify_type,
                                               flags, keywords);
                return;
index 2fe0cc16552b815b0b09af98bb8b0d7041729f7d..7c47601c7910aff789375a2a7bc1eead7ce9af07 100644 (file)
@@ -125,7 +125,7 @@ int mail_index_view_sync_begin(struct mail_index_view *view,
                if (view->map != view->index->map)
                        ctx->sync_map_update = TRUE;
 
-               map = mail_index_map_to_memory(view->map);
+               map = mail_index_map_to_memory(view->index, view->map);
                mail_index_unmap(view->index, view->map);
                view->map = map;
        }
@@ -189,7 +189,7 @@ static int mail_index_view_sync_next_trans(struct mail_index_view_sync_ctx *ctx,
           see only updated information. */
        if (ctx->sync_map_update &&
            (ctx->hdr->type & MAIL_TRANSACTION_EXPUNGE) == 0) {
-               if (mail_transaction_map(ctx->hdr, ctx->data,
+               if (mail_transaction_map(view->index, ctx->hdr, ctx->data,
                                         &mail_index_map_sync_funcs, view) < 0)
                        return -1;
        }
index da5118df2dfd46b3196ef471070fdcf1cb51165f..86085a727b47c804bf0cdc1909b3393bae49cfdb 100644 (file)
@@ -173,7 +173,7 @@ int mail_index_lookup(struct mail_index_view *view, uint32_t seq,
        if (mail_index_view_lock(view) < 0)
                return -1;
 
-       rec = &view->map->records[seq-1];
+       rec = MAIL_INDEX_MAP_IDX(view->index, view->map, seq-1);
        if (view->map == view->index->map) {
                *rec_r = rec;
                return 0;
@@ -190,12 +190,13 @@ int mail_index_lookup(struct mail_index_view *view, uint32_t seq,
        map = view->index->map;
        while (seq > 0) {
                // FIXME: we could be skipping more by uid diff
-               if (map->records[--seq].uid <= uid)
+               seq--;
+               if (MAIL_INDEX_MAP_IDX(view->index, map, seq-1)->uid <= uid)
                        break;
        }
 
-       *rec_r = map->records[seq].uid == uid ?
-               &map->records[seq] : rec;
+       *rec_r = MAIL_INDEX_MAP_IDX(view->index, map, seq)->uid == uid ?
+               MAIL_INDEX_MAP_IDX(view->index, map, seq) : rec;
        return 0;
 }
 
@@ -208,7 +209,7 @@ int mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq,
        if (mail_index_view_lock(view) < 0)
                return -1;
 
-       *uid_r = view->map->records[seq-1].uid;
+       *uid_r = MAIL_INDEX_MAP_IDX(view->index, view->map, seq-1)->uid;
        return 0;
 }
 
@@ -216,10 +217,11 @@ static uint32_t mail_index_bsearch_uid(struct mail_index_view *view,
                                       uint32_t uid, uint32_t *left_idx_p,
                                       int nearest_side)
 {
-       const struct mail_index_record *rec;
-       uint32_t idx, left_idx, right_idx;
+       const struct mail_index_record *rec_base, *rec;
+       uint32_t idx, left_idx, right_idx, record_size;
 
-       rec = view->map->records;
+       rec_base = view->map->records;
+       record_size = view->index->record_size;
 
        idx = left_idx = *left_idx_p;
        right_idx = view->messages_count;
@@ -227,9 +229,10 @@ static uint32_t mail_index_bsearch_uid(struct mail_index_view *view,
        while (left_idx < right_idx) {
                idx = (left_idx + right_idx) / 2;
 
-               if (rec[idx].uid < uid)
+                rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
+               if (rec->uid < uid)
                        left_idx = idx+1;
-               else if (rec[idx].uid > uid)
+               else if (rec->uid > uid)
                        right_idx = idx;
                else
                        break;
@@ -241,14 +244,15 @@ static uint32_t mail_index_bsearch_uid(struct mail_index_view *view,
        }
 
         *left_idx_p = left_idx;
-       if (rec[idx].uid != uid) {
+       rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
+       if (rec->uid != uid) {
                if (nearest_side > 0) {
                        /* we want uid or larger */
-                       return rec[idx].uid > uid ? idx+1 :
+                       return rec->uid > uid ? idx+1 :
                                idx == view->messages_count-1 ? 0 : idx+2;
                } else {
                        /* we want uid or smaller */
-                       return rec[idx].uid < uid ? idx + 1 : idx;
+                       return rec->uid < uid ? idx + 1 : idx;
                }
        }
 
@@ -279,7 +283,8 @@ int mail_index_lookup_uid_range(struct mail_index_view *view,
        left_idx = 0;
        *first_seq_r = mail_index_bsearch_uid(view, first_uid, &left_idx, 1);
        if (*first_seq_r == 0 ||
-           view->map->records[*first_seq_r-1].uid > last_uid) {
+           MAIL_INDEX_MAP_IDX(view->index, view->map, *first_seq_r-1)->uid >
+           last_uid) {
                *first_seq_r = 0;
                *last_seq_r = 0;
                return 0;
@@ -326,8 +331,8 @@ int mail_index_lookup_first(struct mail_index_view *view, enum mail_flags flags,
                        return 0;
        }
 
-       rec = &view->map->records[seq-1];
        for (; seq <= view->messages_count; seq++, rec++) {
+               rec = MAIL_INDEX_MAP_IDX(view->index, view->map, seq-1);
                if ((rec->flags & flags_mask) == (uint8_t)flags) {
                        *seq_r = seq;
                        break;
index 5259fbcdda454bf807d4083e6cd7137c1efa5d8a..31ebbc948c65aa137adafec95c7d9a9b2843090b 100644 (file)
@@ -24,6 +24,7 @@ struct mail_index *mail_index_alloc(const char *dir, const char *prefix)
        index->dir = i_strdup(dir);
        index->prefix = i_strdup(prefix);
        index->fd = -1;
+       index->record_size = sizeof(struct mail_index_record);
 
        index->mode = 0600;
        index->gid = (gid_t)-1;
@@ -40,20 +41,28 @@ void mail_index_free(struct mail_index *index)
        i_free(index);
 }
 
+uint16_t mail_index_register_record_extra(struct mail_index *index,
+                                         uint16_t size)
+{
+       i_assert(!index->opened);
+       i_assert(index->record_size + size <= 65535);
+
+       index->record_size += size;
+       return index->record_size - size;
+}
+
 static int mail_index_check_header(struct mail_index *index,
                                   struct mail_index_map *map)
 {
        const struct mail_index_header *hdr = map->hdr;
-       unsigned char compat_data[3];
+       unsigned char compat_data[sizeof(hdr->compat_data)];
 
+       memset(compat_data, 0, sizeof(compat_data));
 #ifndef WORDS_BIGENDIAN
        compat_data[0] = MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
-#else
-       compat_data[0] = 0;
 #endif
        compat_data[1] = sizeof(uoff_t);
        compat_data[2] = sizeof(time_t);
-       compat_data[3] = sizeof(keywords_mask_t);
 
        if (hdr->major_version != MAIL_INDEX_MAJOR_VERSION) {
                /* major version change - handle silently(?) */
@@ -77,6 +86,22 @@ static int mail_index_check_header(struct mail_index *index,
                return -1;
        }
 
+       if (hdr->keywords_mask_size != sizeof(keywords_mask_t)) {
+               mail_index_set_error(index, "Corrupted index file %s: "
+                                    "keywords_mask_size mismatch: %d != %d",
+                                    index->filepath, hdr->keywords_mask_size,
+                                    (int)sizeof(keywords_mask_t));
+               return -1;
+       }
+
+       if (hdr->record_size != index->record_size) {
+               mail_index_set_error(index, "Corrupted index file %s: "
+                                    "record_size mismatch: %d != %d",
+                                    index->filepath, hdr->record_size,
+                                    (int)index->record_size);
+               return -1;
+       }
+
        if (hdr->next_uid == 0)
                return 0;
 
@@ -157,11 +182,11 @@ static int mail_index_mmap(struct mail_index *index, struct mail_index_map *map)
 
        hdr = map->mmap_base;
        map->mmap_used_size = hdr->header_size +
-               hdr->messages_count * sizeof(struct mail_index_record);
+               hdr->messages_count * index->record_size;
 
        if (map->mmap_used_size > map->mmap_size) {
                records_count = (map->mmap_size - hdr->header_size) /
-                       sizeof(struct mail_index_record);
+                       index->record_size;
                mail_index_set_error(index, "Corrupted index file %s: "
                                     "messages_count too large (%u > %u)",
                                     index->filepath, map->hdr->messages_count,
@@ -202,8 +227,7 @@ static int mail_index_read_map(struct mail_index *index,
                        pos += ret;
        }
        if (ret >= 0 && pos >= MAIL_INDEX_HEADER_MIN_SIZE) {
-               records_size = hdr.messages_count *
-                       sizeof(struct mail_index_record);
+               records_size = hdr.messages_count * index->record_size;
 
                if (map->buffer == NULL) {
                        map->buffer = buffer_create_dynamic(default_pool,
@@ -298,7 +322,7 @@ int mail_index_map(struct mail_index *index, int force)
                        return -1;
 
                used_size = hdr->header_size +
-                       hdr->messages_count * sizeof(struct mail_index_record);
+                       hdr->messages_count * index->record_size;
                if (map->mmap_size >= used_size && !force) {
                        map->records_count = hdr->messages_count;
                        return 1;
@@ -340,7 +364,8 @@ int mail_index_map(struct mail_index *index, int force)
        return 1;
 }
 
-struct mail_index_map *mail_index_map_to_memory(struct mail_index_map *map)
+struct mail_index_map *
+mail_index_map_to_memory(struct mail_index *index, struct mail_index_map *map)
 {
        const struct mail_index_header *hdr;
        struct mail_index_map *mem_map;
@@ -351,7 +376,7 @@ struct mail_index_map *mail_index_map_to_memory(struct mail_index_map *map)
                return map;
        }
 
-        size = map->records_count * sizeof(struct mail_index_record);
+        size = map->records_count * index->record_size;
 
        mem_map = i_new(struct mail_index_map, 1);
        mem_map->refcount = 1;
@@ -525,7 +550,8 @@ static int mail_index_create(struct mail_index *index,
        return 1;
 }
 
-static void mail_index_header_init(struct mail_index_header *hdr)
+static void mail_index_header_init(struct mail_index *index,
+                                  struct mail_index_header *hdr)
 {
        time_t now = time(NULL);
 
@@ -534,13 +560,14 @@ static void mail_index_header_init(struct mail_index_header *hdr)
        hdr->major_version = MAIL_INDEX_MAJOR_VERSION;
        hdr->minor_version = MAIL_INDEX_MINOR_VERSION;
        hdr->header_size = sizeof(*hdr);
+       hdr->record_size = index->record_size;
+       hdr->keywords_mask_size = sizeof(keywords_mask_t);
 
 #ifndef WORDS_BIGENDIAN
        hdr->compat_data[0] = MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
 #endif
        hdr->compat_data[1] = sizeof(uoff_t);
        hdr->compat_data[2] = sizeof(time_t);
-       hdr->compat_data[3] = sizeof(keywords_mask_t);
 
        hdr->indexid = now;
 
@@ -561,7 +588,7 @@ static int mail_index_open_files(struct mail_index *index,
                /* doesn't exist, or corrupted */
                if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
                        return 0;
-               mail_index_header_init(&hdr);
+               mail_index_header_init(index, &hdr);
                index->hdr = &hdr;
        } else if (ret < 0)
                return -1;
index a11e31a52eab952fa91ef66d9d4d3878010998da..dd2113daaeb42927944b10ebc263cd80fd75e407 100644 (file)
@@ -6,7 +6,7 @@
 #define MAIL_INDEX_MAJOR_VERSION 4
 #define MAIL_INDEX_MINOR_VERSION 0
 
-#define MAIL_INDEX_HEADER_MIN_SIZE 72
+#define MAIL_INDEX_HEADER_MIN_SIZE 80
 
 /* Number of keywords in mail_index_record. */
 #define INDEX_KEYWORDS_COUNT (3*8)
@@ -62,12 +62,15 @@ struct mail_index_header {
           increased to contain new non-critical fields. */
        uint8_t major_version;
        uint8_t minor_version;
+
        uint16_t header_size;
+       uint16_t record_size;
+       uint16_t keywords_mask_size;
 
        /* 0 = flags
           1 = sizeof(uoff_t)
           2 = sizeof(time_t)
-          3 = sizeof(keywords_mask_t) */
+          3 = unused */
        uint8_t compat_data[4];
 
        uint32_t indexid;
@@ -133,6 +136,12 @@ struct mail_index_view_sync_ctx;
 struct mail_index *mail_index_alloc(const char *dir, const char *prefix);
 void mail_index_free(struct mail_index *index);
 
+/* register extra data to be used in mail_index_record. calls to this function
+   must remain in same order as long as the index exists, or it breaks.
+   returns the relative offset in mail_index_record for the data. */
+uint16_t mail_index_register_record_extra(struct mail_index *index,
+                                         uint16_t size);
+
 int mail_index_open(struct mail_index *index, enum mail_index_open_flags flags);
 void mail_index_close(struct mail_index *index);
 
index b9817eb95cf49586f422ce4b4576522b9c7ecffa..8de3ffd0e710903e549bd6b3db3c9912ee500601 100644 (file)
@@ -874,11 +874,13 @@ static int mail_transaction_log_fix_appends(struct mail_transaction_log *log,
        const struct mail_transaction_header *hdr;
        const void *data;
        size_t size;
+       uint32_t record_size;
        int ret, deleted = FALSE;
 
        if (t->appends == NULL)
                return 0;
 
+       record_size = log->index->record_size;
        appends = buffer_get_modifyable_data(t->appends, &size);
        end = PTR_OFFSET(appends, size);
 
@@ -902,9 +904,9 @@ static int mail_transaction_log_fix_appends(struct mail_transaction_log *log,
 
                old = data;
                old_end = CONST_PTR_OFFSET(old, hdr->size);
-               for (; old != old_end; old++) {
+               while (old != old_end) {
                        /* appends are sorted */
-                       for (rec = appends; rec != end; rec++) {
+                       for (rec = appends; rec != end; ) {
                                if (rec->uid >= old->uid) {
                                        if (rec->uid == old->uid) {
                                                rec->uid = 0;
@@ -912,7 +914,9 @@ static int mail_transaction_log_fix_appends(struct mail_transaction_log *log,
                                        }
                                        break;
                                }
+                               rec = PTR_OFFSET(rec, record_size);
                        }
+                        old = CONST_PTR_OFFSET(old, record_size);
                }
        }
 
index be545ba1dde54b7c9ccd7e8db538707415b3e660..b5b090ab0619845ba77360a6431c422e3c40579c 100644 (file)
@@ -15,7 +15,7 @@ struct mail_transaction_expunge_iter_ctx {
 
 const struct mail_transaction_type_map mail_transaction_type_map[] = {
        { MAIL_TRANSACTION_APPEND, MAIL_INDEX_SYNC_TYPE_APPEND,
-         sizeof(struct mail_index_record) },
+         1 }, /* index-specific size, use 1 */
        { MAIL_TRANSACTION_EXPUNGE, MAIL_INDEX_SYNC_TYPE_EXPUNGE,
          sizeof(struct mail_transaction_expunge) },
        { MAIL_TRANSACTION_FLAG_UPDATE, MAIL_INDEX_SYNC_TYPE_FLAGS,
@@ -51,7 +51,8 @@ mail_transaction_type_mask_get(enum mail_index_sync_type sync_type)
        return type;
 }
 
-int mail_transaction_map(const struct mail_transaction_header *hdr,
+int mail_transaction_map(struct mail_index *index,
+                        const struct mail_transaction_header *hdr,
                         const void *data,
                         struct mail_transaction_map_functions *map,
                         void *context)
@@ -61,15 +62,17 @@ int mail_transaction_map(const struct mail_transaction_header *hdr,
        switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
        case MAIL_TRANSACTION_APPEND: {
                const struct mail_index_record *rec, *end;
+               uint32_t record_size = index->record_size;
 
                if (map->append == NULL)
                        break;
 
                end = CONST_PTR_OFFSET(data, hdr->size);
-               for (rec = data; rec != end; rec++) {
+               for (rec = data; rec != end; ) {
                        ret = map->append(rec, context);
                        if (ret <= 0)
                                break;
+                       rec = CONST_PTR_OFFSET(rec, record_size);
                }
                break;
        }
index c67bc37e93193350162a48e9a68f21dafc1a79e9..b90d55d20b993f4c1c2f64c00c4706e75da1ba2f 100644 (file)
@@ -24,7 +24,8 @@ mail_transaction_type_lookup(enum mail_transaction_type type);
 enum mail_transaction_type
 mail_transaction_type_mask_get(enum mail_index_sync_type sync_type);
 
-int mail_transaction_map(const struct mail_transaction_header *hdr,
+int mail_transaction_map(struct mail_index *index,
+                        const struct mail_transaction_header *hdr,
                         const void *data,
                         struct mail_transaction_map_functions *map,
                         void *context);