mail-index-sync-update.c revision d12f05c7c391786d0d9795ec3aa4377280bbfaea
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield/* Copyright (C) 2004 Timo Sirainen */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield#include "lib.h"
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield#include "ioloop.h"
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield#include "array.h"
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield#include "mmap-util.h"
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield#include "mail-index-view-private.h"
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield#include "mail-index-sync-private.h"
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield#include "mail-transaction-log.h"
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield#include "mail-transaction-log-private.h"
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield/* If we have less than this many bytes to sync from log file, don't bother
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield reading the main index */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield#define MAIL_INDEX_SYNC_MIN_READ_INDEX_SIZE 2048
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldstatic void
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldmail_index_sync_update_log_offset(struct mail_index_sync_map_ctx *ctx,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield struct mail_index_map *map, bool eol)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield{
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield uint32_t prev_seq;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield uoff_t prev_offset;
96283b546081e7ff709968378fca25cb44f1ab6cStéphane Graber
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield &prev_seq, &prev_offset);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (!eol) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (prev_offset == ctx->ext_intro_end_offset &&
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield prev_seq == ctx->ext_intro_seq) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield /* previous transaction was an extension introduction.
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield we probably came here from
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_sync_ext_reset(). if there are any more
826cde7c2100e1f4419a54b5c930c0854e01e87eMichael H. Warfield views which want to continue syncing it needs the
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield intro. so back up a bit more.
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield don't do this in case the last transaction in the
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield log is the extension intro, so we don't keep trying
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield to sync it over and over again. */
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield prev_offset = ctx->ext_intro_offset;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield }
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield } else {
ec64264d78d4ed608553842ce9e1f07eeab2a032Veres Lajos i_assert(ctx->view->index->log->head->hdr.file_seq == prev_seq);
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield map->hdr.log_file_seq = prev_seq;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield }
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield map->hdr.log_file_head_offset = prev_offset;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield}
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfieldstatic void mail_index_sync_replace_map(struct mail_index_sync_map_ctx *ctx,
826cde7c2100e1f4419a54b5c930c0854e01e87eMichael H. Warfield struct mail_index_map *map)
826cde7c2100e1f4419a54b5c930c0854e01e87eMichael H. Warfield{
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield struct mail_index_view *view = ctx->view;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield i_assert(view->map != map);
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield mail_index_sync_update_log_offset(ctx, view->map, FALSE);
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield mail_index_unmap(&view->map);
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield view->map = map;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield if (ctx->type != MAIL_INDEX_SYNC_HANDLER_VIEW)
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield view->index->map = map;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield}
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfieldvoid mail_index_sync_move_to_private(struct mail_index_sync_map_ctx *ctx)
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield{
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield struct mail_index_map *map = ctx->view->map;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
826cde7c2100e1f4419a54b5c930c0854e01e87eMichael H. Warfield i_assert(MAIL_INDEX_MAP_IS_IN_MEMORY(map) ||
826cde7c2100e1f4419a54b5c930c0854e01e87eMichael H. Warfield map->rec_map->lock_id != 0);
826cde7c2100e1f4419a54b5c930c0854e01e87eMichael H. Warfield
826cde7c2100e1f4419a54b5c930c0854e01e87eMichael H. Warfield if (map->refcount > 1) {
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield map = mail_index_map_clone(map);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_sync_replace_map(ctx, map);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield}
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldstatic void
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldmail_index_sync_move_to_private_memory(struct mail_index_sync_map_ctx *ctx)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield{
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_sync_move_to_private(ctx);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (!MAIL_INDEX_MAP_IS_IN_MEMORY(ctx->view->map))
8ec981fc8b0105da5f071e40811e0c2472a6c3c9Stéphane Graber mail_index_map_move_to_memory(ctx->view->map);
c63c04fcaf1c3a78c70500eae253d72fa9c8358aTAMUKI Shoichi}
96283b546081e7ff709968378fca25cb44f1ab6cStéphane Graber
96283b546081e7ff709968378fca25cb44f1ab6cStéphane Graberstruct mail_index_map *
8ec981fc8b0105da5f071e40811e0c2472a6c3c9Stéphane Grabermail_index_sync_get_atomic_map(struct mail_index_sync_map_ctx *ctx)
8ec981fc8b0105da5f071e40811e0c2472a6c3c9Stéphane Graber{
8ec981fc8b0105da5f071e40811e0c2472a6c3c9Stéphane Graber mail_index_sync_move_to_private_memory(ctx);
8ec981fc8b0105da5f071e40811e0c2472a6c3c9Stéphane Graber ctx->view->map->write_atomic = TRUE;
8ec981fc8b0105da5f071e40811e0c2472a6c3c9Stéphane Graber return ctx->view->map;
8ec981fc8b0105da5f071e40811e0c2472a6c3c9Stéphane Graber}
207bf0e475f1dc6e9a2dac2cee3a209b56427855Stéphane Graber
207bf0e475f1dc6e9a2dac2cee3a209b56427855Stéphane Graberstatic int
207bf0e475f1dc6e9a2dac2cee3a209b56427855Stéphane Grabermail_index_header_update_counts(struct mail_index_header *hdr,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield uint8_t old_flags, uint8_t new_flags,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const char **error_r)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield{
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (((old_flags ^ new_flags) & MAIL_SEEN) != 0) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield /* different seen-flag */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if ((old_flags & MAIL_SEEN) != 0) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (hdr->seen_messages_count == 0) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield *error_r = "Seen counter wrong";
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield return -1;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield hdr->seen_messages_count--;
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield } else {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (hdr->seen_messages_count >= hdr->messages_count) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield *error_r = "Seen counter wrong";
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield return -1;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (++hdr->seen_messages_count == hdr->messages_count)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield hdr->first_unseen_uid_lowwater = hdr->next_uid;
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield }
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield }
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield if (((old_flags ^ new_flags) & MAIL_DELETED) != 0) {
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield /* different deleted-flag */
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield if ((old_flags & MAIL_DELETED) == 0) {
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield hdr->deleted_messages_count++;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (hdr->deleted_messages_count > hdr->messages_count) {
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield *error_r = "Deleted counter wrong";
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield return -1;
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield }
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield } else {
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield if (hdr->deleted_messages_count == 0 ||
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield hdr->deleted_messages_count > hdr->messages_count) {
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield *error_r = "Deleted counter wrong";
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield return -1;
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield }
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (--hdr->deleted_messages_count == 0)
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield hdr->first_deleted_uid_lowwater = hdr->next_uid;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield return 0;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield}
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldstatic void
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldmail_index_sync_header_update_counts_all(struct mail_index_sync_map_ctx *ctx,
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield uint8_t old_flags, uint8_t new_flags)
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield{
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield struct mail_index_map *const *maps;
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield const char *error;
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield unsigned int i, count;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield maps = array_get(&ctx->view->map->rec_map->maps, &count);
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield for (i = 0; i < count; i++) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (mail_index_header_update_counts(&maps[i]->hdr,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield old_flags, new_flags,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield &error) < 0)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_sync_set_corrupted(ctx, "%s", error);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield}
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldstatic void
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldmail_index_sync_header_update_counts(struct mail_index_sync_map_ctx *ctx,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield uint8_t old_flags, uint8_t new_flags,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield bool all)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield{
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const char *error;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (all) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_sync_header_update_counts_all(ctx, old_flags,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield new_flags);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield } else {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (mail_index_header_update_counts(&ctx->view->map->hdr,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield old_flags, new_flags,
17abf2784de1047fb2904ff130ee5efe4ea7b598Elan Ruusamäe &error) < 0)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_sync_set_corrupted(ctx, "%s", error);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield}
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldstatic void
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldmail_index_header_update_lowwaters(struct mail_index_sync_map_ctx *ctx,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const struct mail_index_record *rec)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield{
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield struct mail_index_map *const *maps;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield unsigned int i, count;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield maps = array_get(&ctx->view->map->rec_map->maps, &count);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield for (i = 0; i < count; i++) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if ((rec->flags & MAIL_SEEN) == 0 &&
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield rec->uid < maps[i]->hdr.first_unseen_uid_lowwater)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield maps[i]->hdr.first_unseen_uid_lowwater = rec->uid;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if ((rec->flags & MAIL_DELETED) != 0 &&
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield rec->uid < maps[i]->hdr.first_deleted_uid_lowwater)
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield maps[i]->hdr.first_deleted_uid_lowwater = rec->uid;
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield }
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield}
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfieldstatic int
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfieldsync_expunge_call_handlers(struct mail_index_sync_map_ctx *ctx,
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield uint32_t seq1, uint32_t seq2)
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield{
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield const struct mail_index_expunge_handler *eh;
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield struct mail_index_record *rec;
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield unsigned int i, count;
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield /* call expunge handlers only when syncing index file */
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield if (ctx->type != MAIL_INDEX_SYNC_HANDLER_FILE)
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield return 0;
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield if (!ctx->expunge_handlers_set)
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield mail_index_sync_init_expunge_handlers(ctx);
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield if (!array_is_created(&ctx->expunge_handlers))
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield return 0;
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield eh = array_get(&ctx->expunge_handlers, &count);
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield for (i = 0; i < count; i++, eh++) {
c6df5ca4603c630a7189cdb1653c96bd2808c7e5Michael H. Warfield for (; seq1 <= seq2; seq1++) {
f5067ecbcc1e97052c33269b4afa6375073a91a1Michael H. Warfield rec = MAIL_INDEX_MAP_IDX(ctx->view->map, seq1-1);
f5067ecbcc1e97052c33269b4afa6375073a91a1Michael H. Warfield if (eh->handler(ctx, seq1,
f5067ecbcc1e97052c33269b4afa6375073a91a1Michael H. Warfield PTR_OFFSET(rec, eh->record_offset),
f5067ecbcc1e97052c33269b4afa6375073a91a1Michael H. Warfield eh->sync_context, eh->context) < 0)
f5067ecbcc1e97052c33269b4afa6375073a91a1Michael H. Warfield return -1;
f5067ecbcc1e97052c33269b4afa6375073a91a1Michael H. Warfield }
f5067ecbcc1e97052c33269b4afa6375073a91a1Michael H. Warfield }
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield return 0;
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield}
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfieldstatic int
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfieldsync_expunge(const struct mail_transaction_expunge *e, unsigned int count,
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield struct mail_index_sync_map_ctx *ctx)
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield{
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield struct mail_index_map *map = ctx->view->map;
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield struct mail_index_record *rec;
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield uint32_t seq_count, seq, seq1, seq2;
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield unsigned int i;
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield for (i = 0; i < count; i++, e++) {
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield if (mail_index_lookup_uid_range(ctx->view, e->uid1, e->uid2,
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield &seq1, &seq2) < 0)
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield return -1;
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield if (seq1 == 0) {
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield /* everything expunged already */
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield continue;
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield }
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield map = mail_index_sync_get_atomic_map(ctx);
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield for (seq = seq1; seq <= seq2; seq++) {
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield rec = MAIL_INDEX_MAP_IDX(map, seq-1);
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield mail_index_sync_header_update_counts(ctx,
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield rec->flags, 0,
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield FALSE);
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield }
99c2fb07d74c20d0eec38c05c4ac64e5782d8e7dMichael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (sync_expunge_call_handlers(ctx, seq1, seq2) < 0)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield return -1;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield /* @UNSAFE */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield memmove(MAIL_INDEX_MAP_IDX(map, seq1-1),
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield MAIL_INDEX_MAP_IDX(map, seq2),
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield (map->rec_map->records_count - seq2) *
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->hdr.record_size);
91c5c53f59262704538a7b8f9571d626e4e08011Kalman Olah
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield seq_count = seq2 - seq1 + 1;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->rec_map->records_count -= seq_count;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->hdr.messages_count -= seq_count;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield return 1;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield}
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldvoid mail_index_sync_write_seq_update(struct mail_index_sync_map_ctx *ctx,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield uint32_t seq1, uint32_t seq2)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield{
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield struct mail_index_map *map = ctx->view->map;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (map->rec_map->write_seq_first == 0 ||
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->rec_map->write_seq_first > seq1)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->rec_map->write_seq_first = seq1;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (map->rec_map->write_seq_last < seq2)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->rec_map->write_seq_last = seq2;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield}
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldstatic int sync_append(const struct mail_index_record *rec,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield struct mail_index_sync_map_ctx *ctx)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield{
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield struct mail_index_view *view = ctx->view;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield struct mail_index_map *map = view->map;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield void *dest;
a79df22733c48898aaeb600cc073278236d4b489Stéphane Graber size_t append_pos;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (rec->uid < map->hdr.next_uid) {
a79df22733c48898aaeb600cc073278236d4b489Stéphane Graber mail_index_sync_set_corrupted(ctx,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield "Append with UID %u, but next_uid = %u",
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield rec->uid, map->hdr.next_uid);
a79df22733c48898aaeb600cc073278236d4b489Stéphane Graber return -1;
a79df22733c48898aaeb600cc073278236d4b489Stéphane Graber }
a79df22733c48898aaeb600cc073278236d4b489Stéphane Graber
a79df22733c48898aaeb600cc073278236d4b489Stéphane Graber /* move to memory. the mapping is written when unlocking so we don't
a79df22733c48898aaeb600cc073278236d4b489Stéphane Graber waste time re-mmap()ing multiple times or waste space growing index
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield file too large */
a79df22733c48898aaeb600cc073278236d4b489Stéphane Graber mail_index_sync_move_to_private_memory(ctx);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map = view->map;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield /* don't rely on buffer->used being at the correct position.
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield at least expunges can move it */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield append_pos = map->rec_map->records_count * map->hdr.record_size;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield dest = buffer_get_space_unsafe(map->rec_map->buffer, append_pos,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->hdr.record_size);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->rec_map->records =
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield buffer_get_modifiable_data(map->rec_map->buffer, NULL);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield memcpy(dest, rec, sizeof(*rec));
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield memset(PTR_OFFSET(dest, sizeof(*rec)), 0,
7edae51efcb3cb3a05e7fe850905dc836d120512Claudio Alarcon-Reyes map->hdr.record_size - sizeof(*rec));
7edae51efcb3cb3a05e7fe850905dc836d120512Claudio Alarcon-Reyes
7edae51efcb3cb3a05e7fe850905dc836d120512Claudio Alarcon-Reyes map->hdr.messages_count++;
7edae51efcb3cb3a05e7fe850905dc836d120512Claudio Alarcon-Reyes map->hdr.next_uid = rec->uid+1;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->rec_map->records_count++;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_sync_write_seq_update(ctx, map->hdr.messages_count,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->hdr.messages_count);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->hdr.flags |= MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_header_update_lowwaters(ctx, rec);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_sync_header_update_counts(ctx, 0, rec->flags, FALSE);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield return 1;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield}
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldstatic int sync_flag_update(const struct mail_transaction_flag_update *u,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield struct mail_index_sync_map_ctx *ctx)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield{
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield struct mail_index_view *view = ctx->view;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield struct mail_index_record *rec;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield uint8_t flag_mask, old_flags;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield uint32_t idx, seq1, seq2;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (mail_index_lookup_uid_range(view, u->uid1, u->uid2,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield &seq1, &seq2) < 0)
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield return -1;
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield if (seq1 == 0)
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield return 1;
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield mail_index_sync_write_seq_update(ctx, seq1, seq2);
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield if ((u->add_flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield view->map->hdr.flags |= MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield flag_mask = ~u->remove_flags;
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield if (((u->add_flags | u->remove_flags) &
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield (MAIL_SEEN | MAIL_DELETED)) == 0) {
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield /* we're not modifying any counted/lowwatered flags */
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield for (idx = seq1-1; idx < seq2; idx++) {
7edae51efcb3cb3a05e7fe850905dc836d120512Claudio Alarcon-Reyes rec = MAIL_INDEX_MAP_IDX(view->map, idx);
7edae51efcb3cb3a05e7fe850905dc836d120512Claudio Alarcon-Reyes rec->flags = (rec->flags & flag_mask) | u->add_flags;
7edae51efcb3cb3a05e7fe850905dc836d120512Claudio Alarcon-Reyes }
7edae51efcb3cb3a05e7fe850905dc836d120512Claudio Alarcon-Reyes } else {
7edae51efcb3cb3a05e7fe850905dc836d120512Claudio Alarcon-Reyes for (idx = seq1-1; idx < seq2; idx++) {
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield rec = MAIL_INDEX_MAP_IDX(view->map, idx);
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield old_flags = rec->flags;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield rec->flags = (rec->flags & flag_mask) | u->add_flags;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield mail_index_header_update_lowwaters(ctx, rec);
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield mail_index_sync_header_update_counts(ctx, old_flags,
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield rec->flags, TRUE);
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield }
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield }
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield return 1;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield}
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
826cde7c2100e1f4419a54b5c930c0854e01e87eMichael H. Warfieldstatic int sync_header_update(const struct mail_transaction_header_update *u,
826cde7c2100e1f4419a54b5c930c0854e01e87eMichael H. Warfield struct mail_index_sync_map_ctx *ctx)
826cde7c2100e1f4419a54b5c930c0854e01e87eMichael H. Warfield{
826cde7c2100e1f4419a54b5c930c0854e01e87eMichael H. Warfield struct mail_index_map *map = ctx->view->map;
826cde7c2100e1f4419a54b5c930c0854e01e87eMichael H. Warfield uint32_t orig_log_file_tail_offset = map->hdr.log_file_tail_offset;
826cde7c2100e1f4419a54b5c930c0854e01e87eMichael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (u->offset >= map->hdr.base_header_size ||
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield u->offset + u->size > map->hdr.base_header_size) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_sync_set_corrupted(ctx,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield "Header update outside range: %u + %u > %u",
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield u->offset, u->size, map->hdr.base_header_size);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield return -1;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield buffer_write(map->hdr_copy_buf, u->offset, u + 1, u->size);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->hdr_base = map->hdr_copy_buf->data;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->write_base_header = TRUE;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield /* @UNSAFE */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if ((uint32_t)(u->offset + u->size) <= sizeof(map->hdr)) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield memcpy(PTR_OFFSET(&map->hdr, u->offset),
779b47fdca6975f70541fbc7c25a34393ec5c24bMichael H. Warfield u + 1, u->size);
779b47fdca6975f70541fbc7c25a34393ec5c24bMichael H. Warfield } else if (u->offset < sizeof(map->hdr)) {
779b47fdca6975f70541fbc7c25a34393ec5c24bMichael H. Warfield memcpy(PTR_OFFSET(&map->hdr, u->offset),
779b47fdca6975f70541fbc7c25a34393ec5c24bMichael H. Warfield u + 1, sizeof(map->hdr) - u->offset);
779b47fdca6975f70541fbc7c25a34393ec5c24bMichael H. Warfield }
779b47fdca6975f70541fbc7c25a34393ec5c24bMichael H. Warfield
779b47fdca6975f70541fbc7c25a34393ec5c24bMichael H. Warfield /* the tail offset updates are intended for internal transaction
779b47fdca6975f70541fbc7c25a34393ec5c24bMichael H. Warfield log handling. we'll update the offset in the header only when
779b47fdca6975f70541fbc7c25a34393ec5c24bMichael H. Warfield the sync is finished. */
779b47fdca6975f70541fbc7c25a34393ec5c24bMichael H. Warfield map->hdr.log_file_tail_offset = orig_log_file_tail_offset;
779b47fdca6975f70541fbc7c25a34393ec5c24bMichael H. Warfield return 1;
779b47fdca6975f70541fbc7c25a34393ec5c24bMichael H. Warfield}
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfieldint mail_index_sync_record(struct mail_index_sync_map_ctx *ctx,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const struct mail_transaction_header *hdr,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const void *data)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield{
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield int ret = 0;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield t_push();
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield case MAIL_TRANSACTION_APPEND: {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const struct mail_index_record *rec, *end;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield end = CONST_PTR_OFFSET(data, hdr->size);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield for (rec = data; rec < end; rec++) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ret = sync_append(rec, ctx);
87a92d42cee68cd78e99e99b713299a53589e73fAlexandre Létourneau if (ret <= 0)
6d41f7dfa6faadc1140837185515bf8722d8746ftukiyo break;
87a92d42cee68cd78e99e99b713299a53589e73fAlexandre Létourneau }
87a92d42cee68cd78e99e99b713299a53589e73fAlexandre Létourneau break;
6d41f7dfa6faadc1140837185515bf8722d8746ftukiyo }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield case MAIL_TRANSACTION_EXPUNGE:
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield case MAIL_TRANSACTION_EXPUNGE|MAIL_TRANSACTION_EXPUNGE_PROT: {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const struct mail_transaction_expunge *rec = data, *end;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
3a6ef65aa29206b2f2061fdb020c32118f6d74f2Harald Dunkel /* this is simply a request for expunge */
3a6ef65aa29206b2f2061fdb020c32118f6d74f2Harald Dunkel break;
3a6ef65aa29206b2f2061fdb020c32118f6d74f2Harald Dunkel }
3a6ef65aa29206b2f2061fdb020c32118f6d74f2Harald Dunkel end = CONST_PTR_OFFSET(data, hdr->size);
3a6ef65aa29206b2f2061fdb020c32118f6d74f2Harald Dunkel ret = sync_expunge(rec, end - rec, ctx);
3a6ef65aa29206b2f2061fdb020c32118f6d74f2Harald Dunkel break;
3a6ef65aa29206b2f2061fdb020c32118f6d74f2Harald Dunkel }
3a6ef65aa29206b2f2061fdb020c32118f6d74f2Harald Dunkel case MAIL_TRANSACTION_FLAG_UPDATE: {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const struct mail_transaction_flag_update *rec, *end;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield end = CONST_PTR_OFFSET(data, hdr->size);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield for (rec = data; rec < end; rec++) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ret = sync_flag_update(rec, ctx);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (ret <= 0)
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield break;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
3a6ef65aa29206b2f2061fdb020c32118f6d74f2Harald Dunkel break;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield case MAIL_TRANSACTION_HEADER_UPDATE: {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const struct mail_transaction_header_update *rec;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield unsigned int i;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield for (i = 0; i < hdr->size; ) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield rec = CONST_PTR_OFFSET(data, i);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ret = sync_header_update(rec, ctx);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (ret <= 0)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield break;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i += sizeof(*rec) + rec->size;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if ((i % 4) != 0)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i += 4 - (i % 4);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield break;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield case MAIL_TRANSACTION_EXT_INTRO: {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const struct mail_transaction_ext_intro *rec = data;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield unsigned int i;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield uint32_t prev_seq;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield uoff_t prev_offset;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield &prev_seq, &prev_offset);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ctx->ext_intro_seq = prev_seq;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ctx->ext_intro_offset = prev_offset;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ctx->ext_intro_end_offset =
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield prev_offset + hdr->size + sizeof(*hdr);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield for (i = 0; i < hdr->size; ) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (i + sizeof(*rec) > hdr->size) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield /* should be just extra padding */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield break;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield rec = CONST_PTR_OFFSET(data, i);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (i + sizeof(*rec) + rec->name_size > hdr->size) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_sync_set_corrupted(ctx,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield "ext intro: name_size too large");
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ret = -1;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield break;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ret = mail_index_sync_ext_intro(ctx, rec);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (ret <= 0)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield break;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i += sizeof(*rec) + rec->name_size;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if ((i % 4) != 0)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i += 4 - (i % 4);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield break;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield case MAIL_TRANSACTION_EXT_RESET: {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const struct mail_transaction_ext_reset *rec = data;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (hdr->size != sizeof(*rec)) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_sync_set_corrupted(ctx,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield "ext reset: invalid record size");
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ret = -1;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield break;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ret = mail_index_sync_ext_reset(ctx, rec);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield break;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield case MAIL_TRANSACTION_EXT_HDR_UPDATE: {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const struct mail_transaction_ext_hdr_update *rec = data;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield unsigned int i;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield for (i = 0; i < hdr->size; ) {
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield rec = CONST_PTR_OFFSET(data, i);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (i + sizeof(*rec) > hdr->size ||
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i + sizeof(*rec) + rec->size > hdr->size) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_sync_set_corrupted(ctx,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield "ext hdr update: invalid record size");
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ret = -1;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield break;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ret = mail_index_sync_ext_hdr_update(ctx, rec);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (ret <= 0)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield break;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i += sizeof(*rec) + rec->size;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if ((i % 4) != 0)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i += 4 - (i % 4);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
17abf2784de1047fb2904ff130ee5efe4ea7b598Elan Ruusamäe break;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield case MAIL_TRANSACTION_EXT_REC_UPDATE: {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const struct mail_transaction_ext_rec_update *rec;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const struct mail_index_ext *ext;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield unsigned int i, record_size;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (ctx->cur_ext_id == (uint32_t)-1) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_sync_set_corrupted(ctx,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield "Extension record updated "
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield "without intro prefix");
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ret = -1;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield break;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (ctx->cur_ext_ignore) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ret = 1;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield break;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ext = array_idx(&ctx->view->map->extensions, ctx->cur_ext_id);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield /* the record is padded to 32bits in the transaction log */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield record_size = (sizeof(*rec) + ext->record_size + 3) & ~3;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield for (i = 0; i < hdr->size; i += record_size) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield rec = CONST_PTR_OFFSET(data, i);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (i + record_size > hdr->size) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_sync_set_corrupted(ctx,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield "ext rec update: invalid record size");
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ret = -1;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield break;
17abf2784de1047fb2904ff130ee5efe4ea7b598Elan Ruusamäe }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield ret = mail_index_sync_ext_rec_update(ctx, rec);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (ret <= 0)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield break;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield break;
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield }
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield case MAIL_TRANSACTION_KEYWORD_UPDATE: {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const struct mail_transaction_keyword_update *rec = data;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield ret = mail_index_sync_keywords(ctx, hdr, rec);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield break;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield }
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield case MAIL_TRANSACTION_KEYWORD_RESET: {
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield const struct mail_transaction_keyword_reset *rec = data;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield ret = mail_index_sync_keywords_reset(ctx, hdr, rec);
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield break;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield }
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield default:
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield i_unreached();
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield }
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield t_pop();
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield i_assert(ctx->view->map->rec_map->records_count ==
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield ctx->view->map->hdr.messages_count);
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield return ret;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield}
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfieldvoid mail_index_sync_map_init(struct mail_index_sync_map_ctx *sync_map_ctx,
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield struct mail_index_view *view,
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield enum mail_index_sync_handler_type type)
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield{
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield memset(sync_map_ctx, 0, sizeof(*sync_map_ctx));
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield sync_map_ctx->view = view;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield sync_map_ctx->cur_ext_id = (uint32_t)-1;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield sync_map_ctx->type = type;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield /* make sure we re-read it in case it has changed */
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield sync_map_ctx->view->map->keywords_read = FALSE;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield mail_index_sync_init_handlers(sync_map_ctx);
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield}
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfieldvoid mail_index_sync_map_deinit(struct mail_index_sync_map_ctx *sync_map_ctx)
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield{
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield if (sync_map_ctx->expunge_handlers_used)
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield mail_index_sync_deinit_expunge_handlers(sync_map_ctx);
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield mail_index_sync_deinit_handlers(sync_map_ctx);
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield}
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfieldstatic void mail_index_sync_update_hdr_dirty_flag(struct mail_index_map *map)
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield{
1ecee40b7dcb933d2c9910f07ed26c6a55e18206Michael H. Warfield const struct mail_index_record *rec;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield unsigned int i;
e13923c71155453c856f423e15bdec11d92039faMichael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if ((map->hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) != 0)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield return;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield /* do we have dirty flags anymore? */
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield for (i = 0; i < map->rec_map->records_count; i++) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield rec = MAIL_INDEX_MAP_IDX(map, i);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->hdr.flags |= MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield break;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield }
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield}
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield#ifdef DEBUG
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfieldvoid mail_index_map_check(struct mail_index_map *map)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield{
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const struct mail_index_header *hdr = &map->hdr;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield unsigned int i, del = 0, seen = 0;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i_assert(hdr->messages_count <= map->rec_map->records_count);
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield for (i = 0; i < hdr->messages_count; i++) {
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield const struct mail_index_record *rec;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield rec = MAIL_INDEX_MAP_IDX(map, i);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (rec->flags & MAIL_DELETED) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i_assert(rec->uid >= hdr->first_deleted_uid_lowwater);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield del++;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (rec->flags & MAIL_SEEN)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield seen++;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield else
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i_assert(rec->uid >= hdr->first_unseen_uid_lowwater);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i_assert(del == hdr->deleted_messages_count);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i_assert(seen == hdr->seen_messages_count);
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield}
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield#endif
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfieldint mail_index_sync_map(struct mail_index_map **_map,
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield enum mail_index_sync_handler_type type, bool force)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield{
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield struct mail_index_map *map = *_map;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield struct mail_index *index = map->index;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield struct mail_index_view *view;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield struct mail_index_sync_map_ctx sync_map_ctx;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield const struct mail_transaction_header *thdr;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield const void *tdata;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield uint32_t prev_seq;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield uoff_t start_offset, prev_offset;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield int ret;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield bool had_dirty, reset;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i_assert(index->map == map || type == MAIL_INDEX_SYNC_HANDLER_VIEW);
6bfb727c4bd75d1f5229a862b84e12ec54e67a6f謝致邦
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (mail_index_map_lock(map) < 0)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield return -1;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (!force) {
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield /* see if we'd prefer to reopen the index file instead of
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield syncing the current map from the transaction log */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield uoff_t log_size, index_size;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
3a6ef65aa29206b2f2061fdb020c32118f6d74f2Harald Dunkel if (index->log->head == NULL)
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield return 0;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (index->fd == -1 &&
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield index->log->head->hdr.prev_file_seq != 0) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield /* we don't know the index's size, so use the
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield smallest index size we're willing to read */
3a6ef65aa29206b2f2061fdb020c32118f6d74f2Harald Dunkel index_size = MAIL_INDEX_SYNC_MIN_READ_INDEX_SIZE;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield } else {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield index_size = map->hdr.header_size +
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->rec_map->records_count *
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->hdr.record_size;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
4849ab991b31b90fab06848366f08d689983ad89Michael Werner
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield /* this isn't necessary correct currently, but it should be
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield close enough */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield log_size = index->log->head->last_size;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (log_size > map->hdr.log_file_tail_offset &&
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield log_size - map->hdr.log_file_tail_offset > index_size)
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield return 0;
9f177a00130a70e9c7f64432a8dea3b64e533fe5Stéphane Graber }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
6976826fed04d006608f87ba902a8517358c15ecMichael Adam start_offset = type == MAIL_INDEX_SYNC_HANDLER_FILE ?
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->hdr.log_file_tail_offset : map->hdr.log_file_head_offset;
2ae8252a4f046a8839a70da6a2271e20e8216b99Michael Adam view = mail_index_view_open_with_map(index, map);
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield ret = mail_transaction_log_view_set(view->log_view,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->hdr.log_file_seq, start_offset,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield (uint32_t)-1, (uoff_t)-1, &reset);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (ret <= 0) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (force && ret == 0) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield /* the seq/offset is probably broken */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield (void)mail_index_fsck(index);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield /* can't use it. sync by re-reading index. */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_view_close(&view);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield return 0;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield /* view referenced the map. avoid unnecessary map cloning by
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield unreferencing the map while view exists. */
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield map->refcount--;
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield had_dirty = (map->hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) != 0;
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield if (had_dirty) {
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield map->hdr.flags &= ~MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield map->write_base_header = TRUE;
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield }
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield if (map->hdr_base != map->hdr_copy_buf->data) {
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield /* if syncing updates the header, it updates hdr_copy_buf
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield and updates hdr_base to hdr_copy_buf. so the buffer must
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield initially contain a valid header or we'll break it when
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield writing it. */
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield buffer_reset(map->hdr_copy_buf);
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield buffer_append(map->hdr_copy_buf, map->hdr_base,
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield map->hdr.header_size);
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield map->hdr_base = map->hdr_copy_buf->data;
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield }
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield mail_index_sync_map_init(&sync_map_ctx, view, type);
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield if (reset) {
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield /* Reset the entire index. Leave only indexid and
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield log_file_seq. */
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield mail_transaction_log_view_get_prev_pos(view->log_view,
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield &prev_seq, &prev_offset);
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield map = mail_index_map_alloc(index);
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield map->hdr.log_file_seq = prev_seq;
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield mail_index_sync_replace_map(&sync_map_ctx, map);
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield }
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield map = NULL;
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield /* FIXME: when transaction sync lock is removed, we'll need to handle
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield the case when a transaction is committed while mailbox is being
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield synced ([synced transactions][new transaction][ext transaction]).
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield this means int_offset contains [synced] and ext_offset contains
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield all */
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield while ((ret = mail_transaction_log_view_next(view->log_view, &thdr,
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield &tdata)) > 0) {
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield mail_transaction_log_view_get_prev_pos(view->log_view,
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield &prev_seq, &prev_offset);
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield
08754f305b580801ae800df32ace5dc7b9b191d9Michael H. Warfield if (LOG_IS_BEFORE(prev_seq, prev_offset,
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield view->map->hdr.log_file_seq,
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield view->map->hdr.log_file_head_offset)) {
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield /* this has been synced already. we're here only to call
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield expunge handlers and extension update handlers. */
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield i_assert(type == MAIL_INDEX_SYNC_HANDLER_FILE);
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield if ((thdr->type & MAIL_TRANSACTION_EXTERNAL) != 0)
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield continue;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield if ((thdr->type & MAIL_TRANSACTION_EXT_MASK) == 0)
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield continue;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield }
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield /* we'll just skip over broken entries */
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield (void)mail_index_sync_record(&sync_map_ctx, thdr, tdata);
ec64264d78d4ed608553842ce9e1f07eeab2a032Veres Lajos }
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield map = view->map;
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield if (had_dirty)
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield mail_index_sync_update_hdr_dirty_flag(map);
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield mail_index_sync_update_log_offset(&sync_map_ctx, view->map, TRUE);
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield#ifdef DEBUG
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_map_check(map);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield#endif
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i_assert(map->hdr.indexid == index->indexid);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield /* transaction log tracks internally the current tail offset.
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield besides using header updates, it also updates the offset to skip
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield over following external transactions to avoid extra unneeded log
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield reading. */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->hdr.log_file_tail_offset = index->log->head->max_tail_offset;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield buffer_write(map->hdr_copy_buf, 0, &map->hdr, sizeof(map->hdr));
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (!MAIL_INDEX_MAP_IS_IN_MEMORY(map)) {
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield memcpy(map->rec_map->mmap_base, map->hdr_copy_buf->data,
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->hdr_copy_buf->used);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if (sync_map_ctx.errors) {
b4f7af7a520b23c873e404562ec518a576e63d4cMichael H. Warfield /* avoid the same syncing errors the next time */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_write(index, FALSE);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield }
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield /* restore refcount before closing the view. this is necessary also
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield if map got cloned, because view closing would otherwise destroy it */
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield map->refcount++;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_sync_map_deinit(&sync_map_ctx);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield mail_index_view_close(&view);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield i_assert(index->map == map || type == MAIL_INDEX_SYNC_HANDLER_VIEW);
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield *_map = map;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield return ret < 0 ? -1 : 1;
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield}
164105f6563d98b832f603e28e506dbabed22cf3Michael H. Warfield