mail-index-sync-update.c revision 3cdea46b2af97ab30861ee235678822278217514
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2004 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen#include "ioloop.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "buffer.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "file-set-size.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mmap-util.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-view-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-sync-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-transaction-log.h"
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen#include "mail-transaction-util.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen#include <stdlib.h>
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenstatic void mail_index_sync_replace_map(struct mail_index_view *view,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct mail_index_map *map)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen mail_index_unmap(view->index, view->map);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen view->map = map;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen view->map->refcount++;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen mail_index_unmap(view->index, view->index->map);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen view->index->map = map;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen view->index->hdr = &map->hdr;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen map->write_to_disk = TRUE;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstatic void
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenmail_index_sync_init_expunge_handlers(struct mail_index_sync_map_ctx *ctx)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const mail_index_expunge_handler_t *const *handlers;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const struct mail_index_ext *extensions;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const uint32_t *id_map;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct mail_index_expunge_handler eh;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen size_t handlers_count, id_map_size, size;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen uint32_t ext_id;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen handlers = buffer_get_data(ctx->view->index->expunge_handlers,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen &handlers_count);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen handlers_count /= sizeof(*handlers);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (handlers_count == 0)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* set expunge handlers */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen memset(&eh, 0, sizeof(eh));
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ctx->expunge_handlers != NULL)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen buffer_set_used_size(ctx->expunge_handlers, 0);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen else {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ctx->expunge_handlers =
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen buffer_create_dynamic(default_pool, 256);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen extensions = ctx->view->map->extensions->data;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen id_map = buffer_get_data(ctx->view->map->ext_id_map, &id_map_size);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen id_map_size /= sizeof(*id_map);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen size = I_MIN(handlers_count, id_map_size);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen for (ext_id = 0; ext_id < size; ext_id++) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (handlers[ext_id] == NULL || id_map[ext_id] == (uint32_t)-1)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen continue;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen eh.handler = handlers[ext_id];
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen eh.context = &ctx->extra_context[ext_id];
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen eh.record_offset = extensions[id_map[ext_id]].record_offset;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen buffer_append(ctx->expunge_handlers, &eh, sizeof(eh));
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ctx->expunge_handlers_set = TRUE;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ctx->expunge_handlers_used = TRUE;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstatic void
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenmail_index_sync_deinit_expunge_handlers(struct mail_index_sync_map_ctx *ctx)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const struct mail_index_expunge_handler *eh;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen size_t i, size;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ctx->expunge_handlers == NULL)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen eh = buffer_get_data(ctx->expunge_handlers, &size);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen size /= sizeof(*eh);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen for (i = 0; i < size; i++) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (eh->context != NULL)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen eh[i].handler(ctx, 0, NULL, eh->context);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen buffer_free(ctx->expunge_handlers);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstatic void mail_index_sync_init_handlers(struct mail_index_sync_map_ctx *ctx)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen size_t size;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ctx->view->map->extensions == NULL)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* set space for extra contexts */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen size = sizeof(void *) * (ctx->view->index->extensions->used /
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen sizeof(struct mail_index_ext));
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ctx->extra_context_buf == NULL) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ctx->extra_context_buf =
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen buffer_create_dynamic(default_pool, size);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen } else {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen buffer_set_used_size(ctx->extra_context_buf, 0);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen buffer_append_zero(ctx->extra_context_buf, size);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ctx->extra_context =
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen buffer_get_modifyable_data(ctx->extra_context_buf, NULL);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ctx->expunge_handlers_set = FALSE;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstatic void mail_index_sync_deinit_handlers(struct mail_index_sync_map_ctx *ctx)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen const struct mail_index_sync_handler *sync_handlers;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen size_t i, size;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ctx->extra_context == NULL)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen sync_handlers = buffer_get_data(ctx->view->index->sync_handlers, &size);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen size /= sizeof(*sync_handlers);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_assert(size <= ctx->extra_context_buf->used / sizeof(void *));
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen for (i = 0; i < size; i++) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ctx->extra_context[i] != NULL) {
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen sync_handlers[i].callback(ctx, 0, NULL, NULL,
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen &ctx->extra_context[i]);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen buffer_free(ctx->extra_context_buf);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic void
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenmail_index_header_update_counts(struct mail_index_header *hdr,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen uint8_t old_flags, uint8_t new_flags)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen if (((old_flags ^ new_flags) & MAIL_RECENT) != 0) {
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen /* different recent-flag */
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen if ((old_flags & MAIL_RECENT) == 0)
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen hdr->recent_messages_count++;
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen else if (--hdr->recent_messages_count == 0)
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen hdr->first_recent_uid_lowwater = hdr->next_uid;
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen }
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (((old_flags ^ new_flags) & MAIL_SEEN) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* different seen-flag */
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen if ((old_flags & MAIL_SEEN) != 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen hdr->seen_messages_count--;
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen else if (++hdr->seen_messages_count == hdr->messages_count)
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen hdr->first_unseen_uid_lowwater = hdr->next_uid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (((old_flags ^ new_flags) & MAIL_DELETED) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* different deleted-flag */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((old_flags & MAIL_DELETED) == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen hdr->deleted_messages_count++;
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen else if (--hdr->deleted_messages_count == 0)
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen hdr->first_deleted_uid_lowwater = hdr->next_uid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic void
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenmail_index_header_update_lowwaters(struct mail_index_header *hdr,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen const struct mail_index_record *rec)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((rec->flags & MAIL_RECENT) != 0 &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rec->uid < hdr->first_recent_uid_lowwater)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen hdr->first_recent_uid_lowwater = rec->uid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((rec->flags & MAIL_SEEN) == 0 &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rec->uid < hdr->first_unseen_uid_lowwater)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen hdr->first_unseen_uid_lowwater = rec->uid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((rec->flags & MAIL_DELETED) != 0 &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rec->uid < hdr->first_deleted_uid_lowwater)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen hdr->first_deleted_uid_lowwater = rec->uid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
53238473bf77147660aa6db9daa68a8a685e9381Timo Sirainenstatic int sync_expunge(const struct mail_transaction_expunge *e, void *context)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen struct mail_index_sync_map_ctx *ctx = context;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen struct mail_index_view *view = ctx->view;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct mail_index_map *map = view->map;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_record *rec;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen uint32_t count, seq, seq1, seq2;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct mail_index_expunge_handler *expunge_handlers, *eh;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen size_t i, expunge_handlers_count;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
03dbd273251103f745c08966f1809c02870390ffTimo Sirainen if (e->uid1 > e->uid2 || e->uid1 == 0) {
03dbd273251103f745c08966f1809c02870390ffTimo Sirainen mail_transaction_log_view_set_corrupted(ctx->view->log_view,
03dbd273251103f745c08966f1809c02870390ffTimo Sirainen "Invalid UID range in expunge (%u .. %u)",
03dbd273251103f745c08966f1809c02870390ffTimo Sirainen e->uid1, e->uid2);
03dbd273251103f745c08966f1809c02870390ffTimo Sirainen return -1;
03dbd273251103f745c08966f1809c02870390ffTimo Sirainen }
03dbd273251103f745c08966f1809c02870390ffTimo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (!view->map->write_to_disk) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* expunges have to be atomic. so we'll have to copy
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen the mapping, do the changes there and then finally
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen replace the whole index file. to avoid extra disk
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen I/O we copy the index into memory rather than to
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen temporary file */
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map = mail_index_map_to_memory(map, map->hdr.record_size);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen mail_index_sync_replace_map(view, map);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen i_assert(MAIL_INDEX_MAP_IS_IN_MEMORY(map));
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen if (mail_index_lookup_uid_range(view, e->uid1, e->uid2,
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen &seq1, &seq2) < 0)
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen return -1;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (seq1 == 0)
53238473bf77147660aa6db9daa68a8a685e9381Timo Sirainen return 1;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen if (ctx->type != MAIL_INDEX_SYNC_HANDLER_VIEW) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (!ctx->expunge_handlers_set)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_index_sync_init_expunge_handlers(ctx);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen expunge_handlers =
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen buffer_get_modifyable_data(ctx->expunge_handlers,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen &expunge_handlers_count);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen expunge_handlers_count /= sizeof(*expunge_handlers);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen } else {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* syncing view - don't call expunge handlers */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen expunge_handlers = NULL;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen expunge_handlers_count = 0;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen for (seq = seq1; seq <= seq2; seq++) {
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen rec = MAIL_INDEX_MAP_IDX(map, seq-1);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen mail_index_header_update_counts(&map->hdr, rec->flags, 0);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen for (i = 0; i < expunge_handlers_count; i++) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen eh = &expunge_handlers[i];
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen for (seq = seq1; seq <= seq2; seq++) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen rec = MAIL_INDEX_MAP_IDX(map, seq-1);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen eh->handler(ctx, seq,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen PTR_OFFSET(rec, eh->record_offset),
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen eh->context);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen /* @UNSAFE */
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen count = seq2 - seq1 + 1;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen memmove(MAIL_INDEX_MAP_IDX(map, seq1-1), MAIL_INDEX_MAP_IDX(map, seq2),
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen (map->records_count - seq2) * map->hdr.record_size);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen map->records_count -= count;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr.messages_count -= count;
3cdea46b2af97ab30861ee235678822278217514Timo Sirainen view->hdr.messages_count -= count;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (map->buffer != NULL) {
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen buffer_set_used_size(map->buffer, map->records_count *
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr.record_size);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen map->records = buffer_get_modifyable_data(map->buffer, NULL);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return 1;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstatic int sync_append(const struct mail_index_record *rec, void *context)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen{
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen struct mail_index_sync_map_ctx *ctx = context;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen struct mail_index_view *view = ctx->view;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct mail_index_map *map = view->map;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen void *dest;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (rec->uid < map->hdr.next_uid) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen mail_transaction_log_view_set_corrupted(view->log_view,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen "Append with UID %u, but next_uid = %u",
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen rec->uid, map->hdr.next_uid);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return -1;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (MAIL_INDEX_MAP_IS_IN_MEMORY(map)) {
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen i_assert(map->records_count * map->hdr.record_size ==
ace3c14e47a5a865df8aeea2fabc993b609dd163Timo Sirainen buffer_get_used_size(map->buffer));
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen dest = buffer_append_space_unsafe(map->buffer,
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr.record_size);
ace3c14e47a5a865df8aeea2fabc993b609dd163Timo Sirainen map->records = buffer_get_modifyable_data(map->buffer, NULL);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen } else {
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen i_assert((map->records_count+1) * map->hdr.record_size <=
ace3c14e47a5a865df8aeea2fabc993b609dd163Timo Sirainen map->mmap_size);
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen dest = MAIL_INDEX_MAP_IDX(map, map->records_count);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen memcpy(dest, rec, sizeof(*rec));
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen memset(PTR_OFFSET(dest, sizeof(*rec)), 0,
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr.record_size - sizeof(*rec));
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr.messages_count++;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr.next_uid = rec->uid+1;
ace3c14e47a5a865df8aeea2fabc993b609dd163Timo Sirainen map->records_count++;
3cdea46b2af97ab30861ee235678822278217514Timo Sirainen view->hdr.messages_count++;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
dd8de60250511cc729b67249e61dfc6b4debff11Timo Sirainen if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr.flags |= MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
dd8de60250511cc729b67249e61dfc6b4debff11Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen mail_index_header_update_counts(&map->hdr, 0, rec->flags);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen mail_index_header_update_lowwaters(&map->hdr, rec);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic int sync_flag_update(const struct mail_transaction_flag_update *u,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen void *context)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen struct mail_index_sync_map_ctx *ctx = context;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen struct mail_index_view *view = ctx->view;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct mail_index_header *hdr;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mail_index_record *rec;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint8_t flag_mask, old_flags;
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen keywords_mask_t keyword_mask;
46ba60afe16f39d49100ee79f45cd8b70e0e857cTimo Sirainen uint32_t i, idx, seq1, seq2;
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen int update_keywords;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
03dbd273251103f745c08966f1809c02870390ffTimo Sirainen if (u->uid1 > u->uid2 || u->uid1 == 0) {
03dbd273251103f745c08966f1809c02870390ffTimo Sirainen mail_transaction_log_view_set_corrupted(ctx->view->log_view,
03dbd273251103f745c08966f1809c02870390ffTimo Sirainen "Invalid UID range in flag update (%u .. %u)",
03dbd273251103f745c08966f1809c02870390ffTimo Sirainen u->uid1, u->uid2);
03dbd273251103f745c08966f1809c02870390ffTimo Sirainen return -1;
03dbd273251103f745c08966f1809c02870390ffTimo Sirainen }
03dbd273251103f745c08966f1809c02870390ffTimo Sirainen
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen if (mail_index_lookup_uid_range(view, u->uid1, u->uid2,
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen &seq1, &seq2) < 0)
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen return -1;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainen if (seq1 == 0)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen hdr = &view->map->hdr;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if ((u->add_flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen hdr->flags |= MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen update_keywords = FALSE;
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen for (i = 0; i < INDEX_KEYWORDS_BYTE_COUNT; i++) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (u->add_keywords[i] != 0 ||
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen u->remove_keywords[i] != 0)
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen update_keywords = TRUE;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen keyword_mask[i] = ~u->remove_keywords[i];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen flag_mask = ~u->remove_flags;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
46ba60afe16f39d49100ee79f45cd8b70e0e857cTimo Sirainen for (idx = seq1-1; idx < seq2; idx++) {
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen rec = MAIL_INDEX_MAP_IDX(view->map, idx);
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen old_flags = rec->flags;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen rec->flags = (rec->flags & flag_mask) | u->add_flags;
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen if (update_keywords) {
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen for (i = 0; i < INDEX_KEYWORDS_BYTE_COUNT; i++) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen rec->keywords[i] = u->add_keywords[i] |
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen (rec->keywords[i] & keyword_mask[i]);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen mail_index_header_update_counts(hdr, old_flags, rec->flags);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen mail_index_header_update_lowwaters(hdr, rec);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return 1;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen}
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic int sync_header_update(const struct mail_transaction_header_update *u,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen void *context)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mail_index_sync_map_ctx *ctx = context;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen struct mail_index_map *map = ctx->view->map;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (u->offset >= map->hdr.base_header_size ||
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen u->offset + u->size > map->hdr.base_header_size) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen mail_transaction_log_view_set_corrupted(ctx->view->log_view,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen "Header update outside range: %u + %u > %u",
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen u->offset, u->size, map->hdr.base_header_size);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return -1;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen buffer_write(map->hdr_copy_buf, u->offset, u + 1, u->size);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr_base = map->hdr_copy_buf->data;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen /* @UNSAFE */
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if ((uint32_t)(u->offset + u->size) <= sizeof(map->hdr)) {
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen memcpy(PTR_OFFSET(&map->hdr, u->offset),
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen u + 1, u->size);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen } else if (u->offset < sizeof(map->hdr)) {
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen memcpy(PTR_OFFSET(&map->hdr, u->offset),
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen u + 1, sizeof(map->hdr) - u->offset);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return 1;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstatic struct mail_index_ext_header *
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenget_ext_header(struct mail_index_map *map, const struct mail_index_ext *ext)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct mail_index_ext_header *ext_hdr;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen uint32_t offset;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen void *hdr_base;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* do some kludgy jumping to get to it. */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen offset = ext->hdr_offset -
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen MAIL_INDEX_HEADER_SIZE_ALIGN(sizeof(*ext_hdr) +
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen strlen(ext->name));
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen hdr_base = buffer_get_modifyable_data(map->hdr_copy_buf, NULL);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen ext_hdr = PTR_OFFSET(hdr_base, offset);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_assert(memcmp((char *)(ext_hdr + 1),
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext->name, strlen(ext->name)) == 0);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return ext_hdr;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenstatic int mail_index_ext_align_cmp(const void *p1, const void *p2)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen const struct mail_index_ext *const *e1 = p1, *const *e2 = p2;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return (int)(*e2)->record_align - (int)(*e1)->record_align;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenstatic struct mail_index_map *
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainensync_ext_reorder(struct mail_index_map *map, uint32_t ext_id, uint16_t old_size)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct mail_index_map *new_map;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct mail_index_ext *ext, **sorted;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct mail_index_ext_header *ext_hdr;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen uint16_t *old_offsets, min_align;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen uint32_t offset, old_records_count, rec_idx;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen const void *src;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen size_t i, size;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen t_push();
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext = buffer_get_modifyable_data(map->extensions, &size);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen size /= sizeof(*ext);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* @UNSAFE */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen old_offsets = t_new(uint16_t, size);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen sorted = t_new(struct mail_index_ext *, size);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen for (i = 0; i < size; i++) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen old_offsets[i] = ext[i].record_offset;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext[i].record_offset = 0;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen sorted[i] = &ext[i];
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen qsort(sorted, size, sizeof(struct mail_index_ext *),
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen mail_index_ext_align_cmp);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* we simply try to use the extensions with largest alignment
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen requirement first. FIXME: if the extension sizes don't match
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen alignmentation, this may not give the minimal layout. */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen offset = sizeof(struct mail_index_record);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen for (;;) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen min_align = (uint16_t)-1;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen for (i = 0; i < size; i++) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (sorted[i]->record_offset == 0) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if ((offset % sorted[i]->record_align) == 0)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen break;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (sorted[i]->record_align < min_align)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen min_align = sorted[i]->record_align;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (i == size) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (min_align == (uint16_t)-1) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* all done */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen break;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* we have to leave space here */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen i_assert(min_align > 1 && min_align < (uint16_t)-1);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen offset += min_align - (offset % min_align);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen } else {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen sorted[i]->record_offset = offset;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen offset += sorted[i]->record_size;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen i_assert(offset < (uint16_t)-1);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if ((offset % sizeof(uint32_t)) != 0) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* keep 32bit alignment */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen offset += sizeof(uint32_t) - (offset % sizeof(uint32_t));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* create a new mapping without records. a bit kludgy. */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen old_records_count = map->records_count;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen map->records_count = 0;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen new_map = mail_index_map_to_memory(map, offset);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen map->records_count = old_records_count;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
413fbe597e7ae0fa9dd6c8c66de6637658eea5e5Timo Sirainen if (old_size > ext[ext_id].record_size) {
413fbe597e7ae0fa9dd6c8c66de6637658eea5e5Timo Sirainen /* we are shrinking the record */
413fbe597e7ae0fa9dd6c8c66de6637658eea5e5Timo Sirainen old_size = ext[ext_id].record_size;
413fbe597e7ae0fa9dd6c8c66de6637658eea5e5Timo Sirainen }
413fbe597e7ae0fa9dd6c8c66de6637658eea5e5Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* now copy the records to new mapping */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen src = map->records;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen offset = 0;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen for (rec_idx = 0; rec_idx < old_records_count; rec_idx++) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen buffer_write(new_map->buffer, offset, src,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen sizeof(struct mail_index_record));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen for (i = 0; i < size; i++) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen buffer_write(new_map->buffer,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen offset + ext[i].record_offset,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen CONST_PTR_OFFSET(src, old_offsets[i]),
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen i == ext_id ? old_size :
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext[i].record_size);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen src = CONST_PTR_OFFSET(src, map->hdr.record_size);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen offset += new_map->hdr.record_size;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
eb4e310cbf876dea5c1a5e5e0da1ba52b0c42208Timo Sirainen if (new_map->buffer->used !=
eb4e310cbf876dea5c1a5e5e0da1ba52b0c42208Timo Sirainen old_records_count * new_map->hdr.record_size) {
413fbe597e7ae0fa9dd6c8c66de6637658eea5e5Timo Sirainen /* we didn't fully write the last record */
eb4e310cbf876dea5c1a5e5e0da1ba52b0c42208Timo Sirainen i_assert(new_map->buffer->used ==
eb4e310cbf876dea5c1a5e5e0da1ba52b0c42208Timo Sirainen old_records_count * new_map->hdr.record_size -
eb4e310cbf876dea5c1a5e5e0da1ba52b0c42208Timo Sirainen (ext[ext_id].record_size - old_size));
413fbe597e7ae0fa9dd6c8c66de6637658eea5e5Timo Sirainen buffer_append_zero(new_map->buffer,
413fbe597e7ae0fa9dd6c8c66de6637658eea5e5Timo Sirainen ext[ext_id].record_size - old_size);
413fbe597e7ae0fa9dd6c8c66de6637658eea5e5Timo Sirainen }
413fbe597e7ae0fa9dd6c8c66de6637658eea5e5Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen new_map->records = buffer_get_modifyable_data(new_map->buffer, NULL);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen new_map->records_count = old_records_count;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* update record offsets in headers */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen for (i = 0; i < size; i++) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext_hdr = get_ext_header(new_map, &ext[i]);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext_hdr->record_offset = ext[i].record_offset;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen t_pop();
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return new_map;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstatic void
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainensync_ext_resize(const struct mail_transaction_ext_intro *u, uint32_t ext_id,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct mail_index_sync_map_ctx *ctx)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct mail_index_map *map = ctx->view->map;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct mail_index_ext *ext;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct mail_index_ext_header *ext_hdr;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen uint32_t old_size, new_size, old_record_size;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen int modified = FALSE;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext = buffer_get_modifyable_data(map->extensions, NULL);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext += ext_id;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen old_size = MAIL_INDEX_HEADER_SIZE_ALIGN(ext->hdr_size);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen new_size = MAIL_INDEX_HEADER_SIZE_ALIGN(u->hdr_size);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (new_size < old_size) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* header shrinked */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen buffer_delete(map->hdr_copy_buf, ext->hdr_offset + new_size,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen old_size - new_size);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen modified = TRUE;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen } else if (new_size > old_size) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* header grown */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen buffer_insert_zero(map->hdr_copy_buf,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext->hdr_offset + old_size,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen new_size - old_size);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen modified = TRUE;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen old_record_size = ext->record_size;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext->hdr_size = u->hdr_size;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext->record_size = u->record_size;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext->record_align = u->record_align;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (old_record_size != u->record_size)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen modified = TRUE;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (modified) {
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr_base = map->hdr_copy_buf->data;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr.header_size = map->hdr_copy_buf->used;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext_hdr = get_ext_header(map, ext);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext_hdr->reset_id = ext->reset_id;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext_hdr->hdr_size = ext->hdr_size;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext_hdr->record_offset = ext->record_offset;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext_hdr->record_size = ext->record_size;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext_hdr->record_align = ext->record_align;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (old_record_size != u->record_size) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen map = sync_ext_reorder(map, ext_id, old_record_size);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen mail_index_sync_replace_map(ctx->view, map);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainenstatic int sync_ext_intro(const struct mail_transaction_ext_intro *u,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen void *context)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mail_index_sync_map_ctx *ctx = context;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct mail_index_map *map = ctx->view->map;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen struct mail_index_ext_header ext_hdr;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen const struct mail_index_ext *ext;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen const char *name;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen buffer_t *hdr_buf;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen uint32_t ext_id, hdr_offset;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (u->ext_id != (uint32_t)-1 &&
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen (map->extensions == NULL ||
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen u->ext_id >= map->extensions->used / sizeof(*ext))) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen mail_transaction_log_view_set_corrupted(ctx->view->log_view,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen "Extension introduction for unknown id %u", u->ext_id);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return -1;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (u->ext_id == (uint32_t)-1 && u->name_size == 0) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen mail_transaction_log_view_set_corrupted(ctx->view->log_view,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen "Extension introduction without id or name");
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return -1;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen t_push();
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (u->ext_id != (uint32_t)-1) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen name = NULL;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ext_id = u->ext_id;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen } else {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen name = t_strndup(u + 1, u->name_size);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ext_id = mail_index_map_lookup_ext(map, name);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (ext_id != (uint32_t)-1) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* exists already */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext = map->extensions->data;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext += ext_id;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (u->reset_id == ext->reset_id) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* check if we need to resize anything */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen sync_ext_resize(u, ext_id, ctx);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ctx->cur_ext_ignore = FALSE;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen } else {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* extension was reset and this transaction hadn't
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen yet seen it. ignore this update. */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ctx->cur_ext_ignore = TRUE;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen t_pop();
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ctx->cur_ext_id = ext_id;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return 1;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen hdr_buf = map->hdr_copy_buf;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (MAIL_INDEX_HEADER_SIZE_ALIGN(hdr_buf->used) != hdr_buf->used) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* we need to add padding between base header and extensions */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen buffer_append_zero(hdr_buf,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen MAIL_INDEX_HEADER_SIZE_ALIGN(hdr_buf->used) -
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen hdr_buf->used);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* register record offset initially using zero,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen sync_ext_reorder() will fix it. */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen hdr_offset = map->hdr_copy_buf->used + sizeof(ext_hdr) + strlen(name);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen hdr_offset = MAIL_INDEX_HEADER_SIZE_ALIGN(hdr_offset);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext_id = mail_index_map_register_ext(ctx->view->index, map, name,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen hdr_offset, u->hdr_size, 0,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen u->record_size, u->record_align,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen u->reset_id);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext = map->extensions->data;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext += ext_id;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* <ext_hdr> <name> [padding] [header data] */
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen memset(&ext_hdr, 0, sizeof(ext_hdr));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext_hdr.name_size = strlen(name);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext_hdr.reset_id = ext->reset_id;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen ext_hdr.hdr_size = ext->hdr_size;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen ext_hdr.record_offset = ext->record_offset;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen ext_hdr.record_size = ext->record_size;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext_hdr.record_align = ext->record_align;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen buffer_append(hdr_buf, &ext_hdr, sizeof(ext_hdr));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen buffer_append(hdr_buf, name, strlen(name));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* header must begin and end in correct alignment */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen buffer_append_zero(hdr_buf,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen MAIL_INDEX_HEADER_SIZE_ALIGN(hdr_buf->used) - hdr_buf->used +
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen MAIL_INDEX_HEADER_SIZE_ALIGN(ext->hdr_size));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen i_assert(hdr_buf->used ==
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen hdr_offset + MAIL_INDEX_HEADER_SIZE_ALIGN(ext->hdr_size));
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr.header_size = hdr_buf->used;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr_base = map->hdr_copy_buf->data;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen t_pop();
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_index_sync_init_handlers(ctx);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen map = sync_ext_reorder(map, ext_id, 0);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen mail_index_sync_replace_map(ctx->view, map);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ctx->cur_ext_ignore = FALSE;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ctx->cur_ext_id = ext_id;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return 1;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstatic int sync_ext_reset(const struct mail_transaction_ext_reset *u,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen void *context)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen{
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen struct mail_index_sync_map_ctx *ctx = context;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mail_index_view *view = ctx->view;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mail_index_map *map = view->map;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct mail_index_ext_header *ext_hdr;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct mail_index_ext *ext;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mail_index_record *rec;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen uint32_t i;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ctx->cur_ext_id == (uint32_t)-1) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen mail_transaction_log_view_set_corrupted(view->log_view,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen "Extension reset without intro prefix");
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return -1;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ctx->cur_ext_ignore)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return 1;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext = buffer_get_modifyable_data(map->extensions, NULL);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext += ctx->cur_ext_id;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext->reset_id = u->new_reset_id;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen memset(buffer_get_space_unsafe(map->hdr_copy_buf, ext->hdr_offset,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen ext->hdr_size), 0, ext->hdr_size);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr_base = map->hdr_copy_buf->data;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen for (i = 0; i < view->map->records_count; i++) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen rec = MAIL_INDEX_MAP_IDX(view->map, i);
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen memset(PTR_OFFSET(rec, ext->record_offset), 0,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen ext->record_size);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext_hdr = get_ext_header(map, ext);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext_hdr->reset_id = u->new_reset_id;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return 1;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainenstatic int sync_ext_hdr_update(const struct mail_transaction_ext_hdr_update *u,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen void *context)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mail_index_sync_map_ctx *ctx = context;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mail_index_map *map = ctx->view->map;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen const struct mail_index_ext *ext;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ctx->cur_ext_id == (uint32_t)-1) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen mail_transaction_log_view_set_corrupted(ctx->view->log_view,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen "Extension header update without intro prefix");
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return -1;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ctx->cur_ext_ignore)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return 1;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen ext = map->extensions->data;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext += ctx->cur_ext_id;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen buffer_write(map->hdr_copy_buf, ext->hdr_offset + u->offset,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen u + 1, u->size);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr_base = map->hdr_copy_buf->data;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainenstatic int
d143077bd518de129b8d446fb58e003903e50867Timo Sirainensync_ext_rec_update(const struct mail_transaction_ext_rec_update *u,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen void *context)
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen{
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen struct mail_index_sync_map_ctx *ctx = context;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen struct mail_index_view *view = ctx->view;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen struct mail_index_record *rec;
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen const struct mail_index_sync_handler *sync_handlers;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const struct mail_index_ext *ext;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen void *old_data;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen uint32_t seq;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen int ret;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_assert(ctx->cur_ext_id != (uint32_t)-1);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_assert(!ctx->cur_ext_ignore);
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen if (mail_index_lookup_uid_range(view, u->uid, u->uid, &seq, &seq) < 0)
567e57b09a49bbb2a146b13f8617698eb56237feTimo Sirainen return -1;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (seq == 0)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return 1;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext = view->map->extensions->data;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext += ctx->cur_ext_id;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen rec = MAIL_INDEX_MAP_IDX(view->map, seq-1);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen old_data = PTR_OFFSET(rec, ext->record_offset);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* @UNSAFE */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen sync_handlers = view->index->sync_handlers->data;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen sync_handlers += ctx->cur_ext_id;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* call sync handlers only when we're syncing index (not view) */
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen if ((sync_handlers->type & ctx->type) != 0) {
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen ret = sync_handlers->callback(ctx, seq, old_data, u + 1,
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen &ctx->extra_context[ctx->cur_ext_id]);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ret <= 0)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return ret;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen memcpy(old_data, u + 1, ext->record_size);
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen return 1;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen}
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic int mail_index_grow(struct mail_index *index, struct mail_index_map *map,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen unsigned int count)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen void *hdr_copy;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen size_t size, hdr_copy_size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6a675eda973195f8c00c101519521b788781ba37Timo Sirainen if (MAIL_INDEX_MAP_IS_IN_MEMORY(map))
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen return 0;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen i_assert(map == index->map);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen size = map->hdr.header_size +
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen (map->records_count + count) * map->hdr.record_size;
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen if (size <= map->mmap_size)
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen return 0;
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen
690af4a90eaf8611c2573d34126bb7a852c50a44Timo Sirainen /* when we grow fast, do it exponentially */
690af4a90eaf8611c2573d34126bb7a852c50a44Timo Sirainen if (count < index->last_grow_count)
690af4a90eaf8611c2573d34126bb7a852c50a44Timo Sirainen count = index->last_grow_count;
e4fb5bfcdff32d337d054cce36e00e1cdfaae9f8Timo Sirainen if (count < MAIL_INDEX_MAX_POWER_GROW)
e4fb5bfcdff32d337d054cce36e00e1cdfaae9f8Timo Sirainen count = nearest_power(count);
690af4a90eaf8611c2573d34126bb7a852c50a44Timo Sirainen index->last_grow_count = count;
690af4a90eaf8611c2573d34126bb7a852c50a44Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen size = map->hdr.header_size +
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen (map->records_count + count) * map->hdr.record_size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (file_set_size(index->fd, (off_t)size) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return mail_index_set_syscall_error(index, "file_set_size()");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainen /* we only wish to grow the file, but mail_index_map() updates the
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainen headers as well and may break our modified hdr_copy. so, take
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainen a backup of it and put it back afterwards */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen t_push();
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen i_assert(map->hdr_copy_buf->used == map->hdr.header_size);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen hdr_copy_size = map->hdr_copy_buf->used;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen hdr_copy = t_malloc(hdr_copy_size);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen memcpy(hdr_copy, map->hdr_copy_buf->data, hdr_copy_size);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen memcpy(hdr_copy, &map->hdr, sizeof(map->hdr));
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (mail_index_map(index, TRUE) <= 0) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen t_pop();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
c165abbc0344ff8a4c0553dbdeb0df2259013138Timo Sirainen map = index->map;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen buffer_reset(map->hdr_copy_buf);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen buffer_append(map->hdr_copy_buf, hdr_copy, hdr_copy_size);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr_base = map->hdr_copy_buf->data;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen memcpy(&map->hdr, hdr_copy, sizeof(map->hdr));
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->records_count = map->hdr.messages_count;
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainen
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen i_assert(map->mmap_size >= size);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen t_pop();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainenstatic void
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainenmail_index_update_day_headers(struct mail_index_header *hdr, uint32_t uid)
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen{
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen const int max_days =
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen sizeof(hdr->day_first_uid) / sizeof(hdr->day_first_uid[0]);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen struct tm tm;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen time_t stamp;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen int i, days;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen /* get beginning of today */
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen tm = *localtime(&ioloop_time);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen tm.tm_hour = 0;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen tm.tm_min = 0;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen tm.tm_sec = 0;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen stamp = mktime(&tm);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen if (stamp == (time_t)-1)
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen i_panic("mktime(today) failed");
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen if ((time_t)hdr->day_stamp >= stamp)
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen return;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen /* get number of days since last message */
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen days = (stamp - hdr->day_stamp) / (3600*24);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen if (days > max_days)
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen days = max_days;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen /* @UNSAFE: move days forward and fill the missing days with old
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen day_first_uid[0]. */
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen memcpy(hdr->day_first_uid + days,
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen hdr->day_first_uid, max_days - days);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen for (i = 1; i < days; i++)
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen hdr->day_first_uid[i] = hdr->day_first_uid[0];
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen hdr->day_stamp = stamp;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen hdr->day_first_uid[0] = uid;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen}
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenint mail_index_sync_record(struct mail_index_sync_map_ctx *ctx,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen const struct mail_transaction_header *hdr,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen const void *data)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen int ret = 0;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen case MAIL_TRANSACTION_APPEND: {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen const struct mail_index_record *rec, *end;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen end = CONST_PTR_OFFSET(data, hdr->size);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen for (rec = data; rec < end; rec++) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ret = sync_append(rec, ctx);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (ret <= 0)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen case MAIL_TRANSACTION_EXPUNGE:
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen case MAIL_TRANSACTION_EXPUNGE|MAIL_TRANSACTION_EXPUNGE_PROT: {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen const struct mail_transaction_expunge *rec, *end;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen end = CONST_PTR_OFFSET(data, hdr->size);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen for (rec = data; rec < end; rec++) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ret = sync_expunge(rec, ctx);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (ret <= 0)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen case MAIL_TRANSACTION_FLAG_UPDATE: {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen const struct mail_transaction_flag_update *rec, *end;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen end = CONST_PTR_OFFSET(data, hdr->size);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen for (rec = data; rec < end; rec++) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ret = sync_flag_update(rec, ctx);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (ret <= 0)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen case MAIL_TRANSACTION_HEADER_UPDATE: {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen const struct mail_transaction_header_update *rec;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen unsigned int i;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen for (i = 0; i < hdr->size; ) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen rec = CONST_PTR_OFFSET(data, i);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ret = sync_header_update(rec, ctx);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (ret <= 0)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen i += sizeof(*rec) + rec->size;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if ((i % 4) != 0)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen i += 4 - (i % 4);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen case MAIL_TRANSACTION_EXT_INTRO: {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen const struct mail_transaction_ext_intro *rec = data;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen unsigned int i;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen for (i = 0; i < hdr->size; ) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (i + sizeof(*rec) > hdr->size) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen /* should be just extra padding */
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen rec = CONST_PTR_OFFSET(data, i);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ret = sync_ext_intro(rec, ctx);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (ret <= 0)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen i += sizeof(*rec) + rec->name_size;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if ((i % 4) != 0)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen i += 4 - (i % 4);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen case MAIL_TRANSACTION_EXT_RESET: {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const struct mail_transaction_ext_reset *rec = data;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ret = sync_ext_reset(rec, ctx);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen case MAIL_TRANSACTION_EXT_HDR_UPDATE: {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen const struct mail_transaction_ext_hdr_update *rec = data;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen unsigned int i;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen for (i = 0; i < hdr->size; ) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen rec = CONST_PTR_OFFSET(data, i);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ret = sync_ext_hdr_update(rec, ctx);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (ret <= 0)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen i += sizeof(*rec) + rec->size;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if ((i % 4) != 0)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen i += 4 - (i % 4);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen case MAIL_TRANSACTION_EXT_REC_UPDATE: {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen const struct mail_transaction_ext_rec_update *rec, *end;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen const struct mail_index_ext *ext;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen unsigned int record_size;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ctx->cur_ext_id == (uint32_t)-1) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_transaction_log_view_set_corrupted(
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ctx->view->log_view,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen "Extension record update update "
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen "without intro prefix");
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ret = -1;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ctx->cur_ext_ignore) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ret = 1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen break;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ext = ctx->view->map->extensions->data;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen record_size = sizeof(*rec) + ext[ctx->cur_ext_id].record_size;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen rec = data;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen end = CONST_PTR_OFFSET(data, hdr->size);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen while (rec < end) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ret = sync_ext_rec_update(rec, ctx);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (ret <= 0)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen rec = CONST_PTR_OFFSET(rec, record_size);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen default:
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen i_unreached();
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return ret;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenvoid mail_index_sync_map_init(struct mail_index_sync_map_ctx *sync_map_ctx,
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen struct mail_index_view *view,
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen enum mail_index_sync_handler_type type)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen memset(sync_map_ctx, 0, sizeof(*sync_map_ctx));
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen sync_map_ctx->view = view;
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen sync_map_ctx->cur_ext_id = (uint32_t)-1;
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen sync_map_ctx->type = type;
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen mail_index_sync_init_handlers(sync_map_ctx);
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen}
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainenvoid mail_index_sync_map_deinit(struct mail_index_sync_map_ctx *sync_map_ctx)
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen{
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen if (sync_map_ctx->expunge_handlers_used)
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen mail_index_sync_deinit_expunge_handlers(sync_map_ctx);
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen mail_index_sync_deinit_handlers(sync_map_ctx);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainenint mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx,
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen int sync_only_external)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index *index = sync_ctx->index;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct mail_index_view *view = sync_ctx->view;
215daa7d5bf9a849849586490fd6fdd28a724dd8Timo Sirainen struct mail_index_map *map;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen struct mail_index_sync_map_ctx sync_map_ctx;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen const struct mail_transaction_header *thdr;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen const void *data;
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen unsigned int count, old_lock_id;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen uint32_t seq, i, first_append_uid;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen uoff_t offset;
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen int ret, had_dirty, skipped, check_ext_offsets;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen mail_index_sync_map_init(&sync_map_ctx, view,
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen MAIL_INDEX_SYNC_HANDLER_INDEX);
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen /* we'll have to update view->lock_id to avoid mail_index_view_lock()
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen trying to update the file later. */
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen old_lock_id = view->lock_id;
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainen if (mail_index_lock_exclusive(index, &view->lock_id) < 0)
5c1a8aee989af87bddefd71e2aa83aa2bd695155Timo Sirainen return -1;
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen mail_index_unlock(index, old_lock_id);
5c1a8aee989af87bddefd71e2aa83aa2bd695155Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen /* NOTE: locking may change index->map so make sure the assignment is
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen after locking */
215daa7d5bf9a849849586490fd6fdd28a724dd8Timo Sirainen map = index->map;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen if (MAIL_INDEX_MAP_IS_IN_MEMORY(map))
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen map->write_to_disk = TRUE;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (map->hdr_base != map->hdr_copy_buf->data) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen buffer_reset(map->hdr_copy_buf);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen buffer_append(map->hdr_copy_buf, map->hdr_base,
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr.header_size);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr_base = map->hdr_copy_buf->data;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen i_assert(map->hdr.base_header_size >= sizeof(map->hdr));
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen mail_index_unmap(index, view->map);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen view->map = map;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen view->map->refcount++;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen had_dirty = (map->hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) != 0;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (had_dirty)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr.flags &= ~MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen first_append_uid = 0;
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen check_ext_offsets = TRUE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view, &thdr,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen &data, &skipped)) > 0) {
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen if ((thdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen if (sync_only_external) {
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen /* we're syncing only external changes. */
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen continue;
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen }
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen } else if (check_ext_offsets) {
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen uint32_t prev_seq;
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen uoff_t prev_offset;
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen mail_transaction_log_view_get_prev_pos(view->log_view,
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen &prev_seq,
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen &prev_offset);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (prev_offset < map->hdr.log_file_ext_offset) {
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen /* we have already synced this change */
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen continue;
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen }
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen check_ext_offsets = FALSE;
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen }
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if ((thdr->type & MAIL_TRANSACTION_APPEND) != 0) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen const struct mail_index_record *rec = data;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen if (first_append_uid == 0)
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen first_append_uid = rec->uid;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen map = view->map;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen count = thdr->size / sizeof(*rec);
c165abbc0344ff8a4c0553dbdeb0df2259013138Timo Sirainen if (mail_index_grow(index, map, count) < 0) {
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen ret = -1;
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen break;
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen }
90a6478adca64af3b909498711bb034a5ddb79a9Timo Sirainen if (map != index->map) {
90a6478adca64af3b909498711bb034a5ddb79a9Timo Sirainen map = index->map;
90a6478adca64af3b909498711bb034a5ddb79a9Timo Sirainen mail_index_unmap(view->index, view->map);
90a6478adca64af3b909498711bb034a5ddb79a9Timo Sirainen view->map = map;
90a6478adca64af3b909498711bb034a5ddb79a9Timo Sirainen view->map->refcount++;
90a6478adca64af3b909498711bb034a5ddb79a9Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (mail_index_sync_record(&sync_map_ctx, thdr, data) < 0) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen ret = -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen map = view->map;
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen mail_index_sync_map_deinit(&sync_map_ctx);
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen if (ret < 0) {
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen mail_index_view_unlock(view);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return -1;
fec0e90484c5f2c9da9cdc62c0897408023d4c6eTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen i_assert(map->records_count == map->hdr.messages_count);
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen mail_transaction_log_get_head(index->log, &seq, &offset);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr.log_file_seq = seq;
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen if (!sync_only_external)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr.log_file_int_offset = offset;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr.log_file_ext_offset = offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen if (first_append_uid != 0)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen mail_index_update_day_headers(&map->hdr, first_append_uid);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if ((map->hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) == 0 &&
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen had_dirty) {
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen /* do we have dirty flags anymore? */
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen const struct mail_index_record *rec;
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen for (i = 0; i < map->records_count; i++) {
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen rec = MAIL_INDEX_MAP_IDX(map, i);
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) {
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr.flags |=
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen break;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen }
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen }
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen if (!MAIL_INDEX_MAP_IS_IN_MEMORY(map)) {
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen map->mmap_used_size = index->hdr->header_size +
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->records_count * map->hdr.record_size;
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen memcpy(map->mmap_base, &map->hdr, sizeof(map->hdr));
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen memcpy(PTR_OFFSET(map->mmap_base, sizeof(map->hdr)),
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen PTR_OFFSET(map->hdr_base, sizeof(map->hdr)),
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr.header_size - sizeof(map->hdr));
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen if (msync(map->mmap_base, map->mmap_used_size, MS_SYNC) < 0) {
5c1a8aee989af87bddefd71e2aa83aa2bd695155Timo Sirainen mail_index_set_syscall_error(index, "msync()");
5c1a8aee989af87bddefd71e2aa83aa2bd695155Timo Sirainen ret = -1;
5c1a8aee989af87bddefd71e2aa83aa2bd695155Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
f172291ed740e6af3ce3e7c9c2ef0fe1d3ad7963Timo Sirainen i_assert(view->map == index->map);
3cdea46b2af97ab30861ee235678822278217514Timo Sirainen view->hdr = map->hdr;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainen mail_index_view_unlock(view);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}