mail-index-sync-update.c revision 1df526903ed039e8ff966a223c43b8d04eddf3c7
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher/* Copyright (c) 2004-2014 Dovecot authors, see the included COPYING file */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#include "lib.h"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#include "ioloop.h"
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher#include "array.h"
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek#include "mmap-util.h"
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek#include "mail-index-modseq.h"
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek#include "mail-index-view-private.h"
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek#include "mail-index-sync-private.h"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#include "mail-transaction-log.h"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#include "mail-transaction-log-private.h"
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan/* If we have less than this many bytes to sync from log file, don't bother
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek reading the main index */
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek#define MAIL_INDEX_SYNC_MIN_READ_INDEX_SIZE 2048
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozekstatic void
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozekmail_index_sync_update_log_offset(struct mail_index_sync_map_ctx *ctx,
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher struct mail_index_map *map, bool eol)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan uint32_t prev_seq;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher uoff_t prev_offset;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
7a14e8f66c0e932fe2954d792614a3b61d444bd1Jakub Hrozek mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek &prev_seq, &prev_offset);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (prev_seq == 0) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher /* handling lost changes in view syncing */
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher return;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher }
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek if (!eol) {
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek if (prev_offset == ctx->ext_intro_end_offset &&
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek prev_seq == ctx->ext_intro_seq) {
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek /* previous transaction was an extension introduction.
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek we probably came here from
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek mail_index_sync_ext_reset(). if there are any more
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan views which want to continue syncing it needs the
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan intro. so back up a bit more.
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher don't do this in case the last transaction in the
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan log is the extension intro, so we don't keep trying
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan to sync it over and over again. */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan prev_offset = ctx->ext_intro_offset;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher map->hdr.log_file_seq = prev_seq;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher } else {
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek i_assert(ctx->view->index->log->head->hdr.file_seq == prev_seq);
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek if (map->hdr.log_file_seq != prev_seq) {
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek map->hdr.log_file_seq = prev_seq;
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek map->hdr.log_file_tail_offset = 0;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan map->hdr.log_file_head_offset = prev_offset;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic void mail_index_sync_replace_map(struct mail_index_sync_map_ctx *ctx,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan struct mail_index_map *map)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan{
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher struct mail_index_view *view = ctx->view;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_assert(view->map != map);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher mail_index_sync_update_log_offset(ctx, view->map, FALSE);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher mail_index_unmap(&view->map);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan view->map = map;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher if (ctx->type != MAIL_INDEX_SYNC_HANDLER_VIEW)
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher view->index->map = map;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher mail_index_modseq_sync_map_replaced(ctx->modseq_ctx);
fbeb1aba9e11e7aab8adac943276ca040f0c5311Jakub Hrozek}
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozekstatic struct mail_index_map *
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozekmail_index_sync_move_to_private_memory(struct mail_index_sync_map_ctx *ctx)
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek{
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek struct mail_index_map *map = ctx->view->map;
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek if (map->refcount > 1) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan map = mail_index_map_clone(map);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_index_sync_replace_map(ctx, map);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (!MAIL_INDEX_MAP_IS_IN_MEMORY(ctx->view->map))
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_index_map_move_to_memory(ctx->view->map);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_index_modseq_sync_map_replaced(ctx->modseq_ctx);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return map;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan}
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivanstruct mail_index_map *
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanmail_index_sync_get_atomic_map(struct mail_index_sync_map_ctx *ctx)
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher{
fbeb1aba9e11e7aab8adac943276ca040f0c5311Jakub Hrozek (void)mail_index_sync_move_to_private_memory(ctx);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher mail_index_record_map_move_to_private(ctx->view->map);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher mail_index_modseq_sync_map_replaced(ctx->modseq_ctx);
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek return ctx->view->map;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic int
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanmail_index_header_update_counts(struct mail_index_header *hdr,
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher uint8_t old_flags, uint8_t new_flags,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan const char **error_r)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan{
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher if (((old_flags ^ new_flags) & MAIL_SEEN) != 0) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher /* different seen-flag */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if ((old_flags & MAIL_SEEN) != 0) {
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher if (hdr->seen_messages_count == 0) {
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher *error_r = "Seen counter wrong";
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return -1;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan hdr->seen_messages_count--;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan } else {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher if (hdr->seen_messages_count >= hdr->messages_count) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher *error_r = "Seen counter wrong";
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher return -1;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher if (++hdr->seen_messages_count == hdr->messages_count)
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan hdr->first_unseen_uid_lowwater = hdr->next_uid;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (((old_flags ^ new_flags) & MAIL_DELETED) != 0) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher /* different deleted-flag */
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher if ((old_flags & MAIL_DELETED) == 0) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan hdr->deleted_messages_count++;
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher if (hdr->deleted_messages_count > hdr->messages_count) {
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher *error_r = "Deleted counter wrong";
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return -1;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan } else {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (hdr->deleted_messages_count == 0 ||
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher hdr->deleted_messages_count > hdr->messages_count) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher *error_r = "Deleted counter wrong";
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return -1;
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher }
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (--hdr->deleted_messages_count == 0)
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher hdr->first_deleted_uid_lowwater = hdr->next_uid;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return 0;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan}
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagherstatic void
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozekmail_index_sync_header_update_counts_all(struct mail_index_sync_map_ctx *ctx,
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek uint32_t uid,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan uint8_t old_flags, uint8_t new_flags)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan struct mail_index_map *const *maps;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher const char *error;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher unsigned int i, count;
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek maps = array_get(&ctx->view->map->rec_map->maps, &count);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan for (i = 0; i < count; i++) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (uid >= maps[i]->hdr.next_uid)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan continue;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek if (mail_index_header_update_counts(&maps[i]->hdr,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan old_flags, new_flags,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan &error) < 0)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_index_sync_set_corrupted(ctx, "%s", error);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic void
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanmail_index_sync_header_update_counts(struct mail_index_sync_map_ctx *ctx,
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher uint32_t uid, uint8_t old_flags,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan uint8_t new_flags)
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek{
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek const char *error;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek if (uid >= ctx->view->map->hdr.next_uid) {
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek mail_index_sync_set_corrupted(ctx, "uid %u >= next_uid %u",
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan uid, ctx->view->map->hdr.next_uid);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan } else {
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek if (mail_index_header_update_counts(&ctx->view->map->hdr,
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek old_flags, new_flags,
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek &error) < 0)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_index_sync_set_corrupted(ctx, "%s", error);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic void
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanmail_index_header_update_lowwaters(struct mail_index_sync_map_ctx *ctx,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan uint32_t uid, enum mail_flags flags)
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher{
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher struct mail_index_map *const *maps;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan unsigned int i, count;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan maps = array_get(&ctx->view->map->rec_map->maps, &count);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan for (i = 0; i < count; i++) {
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher if ((flags & MAIL_SEEN) == 0 &&
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher uid < maps[i]->hdr.first_unseen_uid_lowwater)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan maps[i]->hdr.first_unseen_uid_lowwater = uid;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher if ((flags & MAIL_DELETED) != 0 &&
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan uid < maps[i]->hdr.first_deleted_uid_lowwater)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan maps[i]->hdr.first_deleted_uid_lowwater = uid;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivanstatic void
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivansync_expunge_call_handlers(struct mail_index_sync_map_ctx *ctx,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan uint32_t seq1, uint32_t seq2)
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan const struct mail_index_expunge_handler *eh;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan struct mail_index_record *rec;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan uint32_t seq;
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan array_foreach(&ctx->expunge_handlers, eh) {
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher for (seq = seq1; seq <= seq2; seq++) {
7797e361155f7ce937085fd98e360469d7baf1b6Jakub Hrozek rec = MAIL_INDEX_REC_AT_SEQ(ctx->view->map, seq);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* FIXME: does expunge handler's return value matter?
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher we probably shouldn't disallow expunges if the
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher handler returns failure.. should it be just changed
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan to return void? */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan (void)eh->handler(ctx, seq,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan PTR_OFFSET(rec, eh->record_offset),
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan eh->sync_context, eh->context);
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher }
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan}
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagherstatic bool
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivansync_expunge_handlers_init(struct mail_index_sync_map_ctx *ctx)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* call expunge handlers only when syncing index file */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (ctx->type != MAIL_INDEX_SYNC_HANDLER_FILE)
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan return FALSE;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan if (!ctx->expunge_handlers_set)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_index_sync_init_expunge_handlers(ctx);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher if (!array_is_created(&ctx->expunge_handlers))
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek return FALSE;
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek return TRUE;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek}
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozekstatic void
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozeksync_expunge_range(struct mail_index_sync_map_ctx *ctx, const ARRAY_TYPE(seq_range) *seqs)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek{
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek struct mail_index_map *map;
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek const struct seq_range *range;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek unsigned int i, count;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek uint32_t dest_seq1, prev_seq2, orig_rec_count;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek map = mail_index_sync_get_atomic_map(ctx);
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek /* call the expunge handlers first */
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek range = array_get(seqs, &count);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek i_assert(count > 0);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek if (sync_expunge_handlers_init(ctx)) {
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek for (i = 0; i < count; i++) {
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek sync_expunge_call_handlers(ctx,
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek range[i].seq1, range[i].seq2);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek }
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek }
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek prev_seq2 = 0;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek dest_seq1 = 1;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek orig_rec_count = map->rec_map->records_count;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek for (i = 0; i < count; i++) {
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek uint32_t seq1 = range[i].seq1;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek uint32_t seq2 = range[i].seq2;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek struct mail_index_record *rec;
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek uint32_t seq_count, seq;
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek i_assert(seq1 > prev_seq2);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek for (seq = seq1; seq <= seq2; seq++) {
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek rec = MAIL_INDEX_REC_AT_SEQ(map, seq);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek mail_index_sync_header_update_counts(ctx, rec->uid, rec->flags, 0);
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek }
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek if (prev_seq2+1 <= seq1-1) {
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek /* @UNSAFE: move (prev_seq2+1) .. (seq1-1) to its
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek final location in the map if necessary */
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek uint32_t move_count = (seq1-1) - (prev_seq2+1) + 1;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek if (prev_seq2+1-1 != dest_seq1-1)
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek memmove(MAIL_INDEX_REC_AT_SEQ(map, dest_seq1),
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek MAIL_INDEX_REC_AT_SEQ(map, prev_seq2+1),
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek move_count * map->hdr.record_size);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek dest_seq1 += move_count;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek }
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek seq_count = seq2 - seq1 + 1;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek map->rec_map->records_count -= seq_count;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek map->hdr.messages_count -= seq_count;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek mail_index_modseq_expunge(ctx->modseq_ctx, seq1, seq2);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek prev_seq2 = seq2;
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek }
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek /* Final stragglers */
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek if (orig_rec_count > prev_seq2) {
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek uint32_t final_move_count = orig_rec_count - prev_seq2;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek memmove(MAIL_INDEX_REC_AT_SEQ(map, dest_seq1),
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek MAIL_INDEX_REC_AT_SEQ(map, prev_seq2+1),
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek final_move_count * map->hdr.record_size);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek }
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek}
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozekstatic void *sync_append_record(struct mail_index_map *map)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek{
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek size_t append_pos;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek void *ret;
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek append_pos = map->rec_map->records_count * map->hdr.record_size;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek ret = buffer_get_space_unsafe(map->rec_map->buffer, append_pos,
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek map->hdr.record_size);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek map->rec_map->records =
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek buffer_get_modifiable_data(map->rec_map->buffer, NULL);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek return ret;
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek}
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozekstatic bool sync_update_ignored_change(struct mail_index_sync_map_ctx *ctx)
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek{
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek struct mail_index_transaction_commit_result *result =
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek ctx->view->index->sync_commit_result;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek uint32_t prev_log_seq;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek uoff_t prev_log_offset, trans_start_offset, trans_end_offset;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek if (result == NULL)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek return FALSE;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek /* we'll return TRUE if this modseq change was written within the
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek transaction that was just committed */
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek &prev_log_seq, &prev_log_offset);
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek if (prev_log_seq != result->log_file_seq)
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek return FALSE;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek trans_end_offset = result->log_file_offset;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek trans_start_offset = trans_end_offset - result->commit_size;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek if (prev_log_offset < trans_start_offset ||
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek prev_log_offset >= trans_end_offset)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return FALSE;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return TRUE;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher}
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic int
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivansync_modseq_update(struct mail_index_sync_map_ctx *ctx,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan const struct mail_transaction_modseq_update *u,
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher unsigned int size)
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan struct mail_index_view *view = ctx->view;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan const struct mail_transaction_modseq_update *end;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan uint32_t seq;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher uint64_t min_modseq, highest_modseq = 0;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek int ret;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan end = CONST_PTR_OFFSET(u, size);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan for (; u < end; u++) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher if (u->uid == 0)
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek seq = 0;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan else if (!mail_index_lookup_seq(view, u->uid, &seq))
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan continue;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan min_modseq = ((uint64_t)u->modseq_high32 << 32) |
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan u->modseq_low32;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan if (highest_modseq < min_modseq)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan highest_modseq = min_modseq;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek ret = seq == 0 ? 1 :
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_index_modseq_set(view, seq, min_modseq);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (ret < 0) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_index_sync_set_corrupted(ctx,
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher "modseqs updated before they were enabled");
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek return -1;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (ret == 0 && sync_update_ignored_change(ctx))
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan view->index->sync_commit_result->ignored_modseq_changes++;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan }
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_index_modseq_update_highest(ctx->modseq_ctx, highest_modseq);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher return 1;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek}
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagherstatic int sync_append(const struct mail_index_record *rec,
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher struct mail_index_sync_map_ctx *ctx)
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher{
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek struct mail_index_view *view = ctx->view;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher struct mail_index_map *map = view->map;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher const struct mail_index_record *old_rec;
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher enum mail_flags new_flags;
7797e361155f7ce937085fd98e360469d7baf1b6Jakub Hrozek void *dest;
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (rec->uid < map->hdr.next_uid) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher mail_index_sync_set_corrupted(ctx,
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek "Append with UID %u, but next_uid = %u",
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan rec->uid, map->hdr.next_uid);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return -1;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek /* move to memory. the mapping is written when unlocking so we don't
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan waste time re-mmap()ing multiple times or waste space growing index
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan file too large */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan map = mail_index_sync_move_to_private_memory(ctx);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher if (rec->uid <= map->rec_map->last_appended_uid) {
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher i_assert(map->hdr.messages_count < map->rec_map->records_count);
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher /* the flags may have changed since it was added to map.
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan use the updated flags already, so flag counters won't get
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher broken. */
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek old_rec = MAIL_INDEX_MAP_IDX(map, map->hdr.messages_count);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_assert(old_rec->uid == rec->uid);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan new_flags = old_rec->flags;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan } else {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher /* don't rely on buffer->used being at the correct position.
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek at least expunges can move it */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan dest = sync_append_record(map);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan memcpy(dest, rec, sizeof(*rec));
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan memset(PTR_OFFSET(dest, sizeof(*rec)), 0,
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher map->hdr.record_size - sizeof(*rec));
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek map->rec_map->records_count++;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan map->rec_map->last_appended_uid = rec->uid;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan new_flags = rec->flags;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_index_modseq_append(ctx->modseq_ctx,
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek map->rec_map->records_count);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan map->hdr.messages_count++;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan map->hdr.next_uid = rec->uid+1;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher if ((new_flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek map->hdr.flags |= MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_index_header_update_lowwaters(ctx, rec->uid, new_flags);
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher mail_index_sync_header_update_counts(ctx, rec->uid, 0, new_flags);
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek return 1;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic int sync_flag_update(const struct mail_transaction_flag_update *u,
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher struct mail_index_sync_map_ctx *ctx)
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan struct mail_index_view *view = ctx->view;
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher struct mail_index_record *rec;
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher uint8_t flag_mask, old_flags;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan uint32_t idx, seq1, seq2;
7797e361155f7ce937085fd98e360469d7baf1b6Jakub Hrozek
7797e361155f7ce937085fd98e360469d7baf1b6Jakub Hrozek if (!mail_index_lookup_seq_range(view, u->uid1, u->uid2, &seq1, &seq2))
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return 1;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek if (!MAIL_TRANSACTION_FLAG_UPDATE_IS_INTERNAL(u)) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_index_modseq_update_flags(ctx->modseq_ctx,
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek u->add_flags | u->remove_flags,
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek seq1, seq2);
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek if ((u->add_flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek view->map->hdr.flags |= MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek flag_mask = ~u->remove_flags;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher if (((u->add_flags | u->remove_flags) &
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek (MAIL_SEEN | MAIL_DELETED)) == 0) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* we're not modifying any counted/lowwatered flags */
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan for (idx = seq1-1; idx < seq2; idx++) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan rec = MAIL_INDEX_MAP_IDX(view->map, idx);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek rec->flags = (rec->flags & flag_mask) | u->add_flags;
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan } else {
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek for (idx = seq1-1; idx < seq2; idx++) {
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek rec = MAIL_INDEX_MAP_IDX(view->map, idx);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek old_flags = rec->flags;
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek rec->flags = (rec->flags & flag_mask) | u->add_flags;
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek mail_index_header_update_lowwaters(ctx, rec->uid,
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek rec->flags);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek mail_index_sync_header_update_counts_all(ctx, rec->uid,
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek old_flags,
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek rec->flags);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek }
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek }
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek return 1;
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek}
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozekstatic int sync_header_update(const struct mail_transaction_header_update *u,
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek struct mail_index_sync_map_ctx *ctx)
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek{
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek#define MAIL_INDEX_HEADER_UPDATE_FIELD_IN_RANGE(u, field) \
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek ((u)->offset <= offsetof(struct mail_index_header, field) && \
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek (u)->offset + (u)->size > offsetof(struct mail_index_header, field))
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek struct mail_index_map *map = ctx->view->map;
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek uint32_t orig_log_file_tail_offset = map->hdr.log_file_tail_offset;
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek uint32_t orig_next_uid = map->hdr.next_uid;
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek if (u->offset >= map->hdr.base_header_size ||
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek u->offset + u->size > map->hdr.base_header_size) {
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek mail_index_sync_set_corrupted(ctx,
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek "Header update outside range: %u + %u > %u",
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek u->offset, u->size, map->hdr.base_header_size);
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek return -1;
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek }
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek buffer_write(map->hdr_copy_buf, u->offset, u + 1, u->size);
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek map->hdr_base = map->hdr_copy_buf->data;
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* @UNSAFE */
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek if ((uint32_t)(u->offset + u->size) <= sizeof(map->hdr)) {
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek memcpy(PTR_OFFSET(&map->hdr, u->offset),
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek u + 1, u->size);
a9228ebcce14888b3123bdf46e610e0900bcd2ccJakub Hrozek } else if (u->offset < sizeof(map->hdr)) {
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek memcpy(PTR_OFFSET(&map->hdr, u->offset),
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek u + 1, sizeof(map->hdr) - u->offset);
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek }
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek if (map->hdr.next_uid < orig_next_uid) {
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek /* next_uid update tried to shrink its value. this can happen
b20208b80e99abb79c00d5ec526caa9465859c52Jakub Hrozek in some race conditions with e.g. with dsync, so just
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek silently ignore it. */
0172959f117b545c8a6b1893f5f56818d82dd624Jakub Hrozek map->hdr.next_uid = orig_next_uid;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek /* the tail offset updates are intended for internal transaction
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher log handling. we'll update the offset in the header only when
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher the sync is finished. */
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher map->hdr.log_file_tail_offset = orig_log_file_tail_offset;
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher return 1;
7797e361155f7ce937085fd98e360469d7baf1b6Jakub Hrozek}
7797e361155f7ce937085fd98e360469d7baf1b6Jakub Hrozek
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic int
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallaghermail_index_sync_record_real(struct mail_index_sync_map_ctx *ctx,
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek const struct mail_transaction_header *hdr,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan const void *data)
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan uint64_t modseq;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher int ret = 0;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan case MAIL_TRANSACTION_APPEND: {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan const struct mail_index_record *rec, *end;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan end = CONST_PTR_OFFSET(data, hdr->size);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan for (rec = data; rec < end; rec++) {
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan ret = sync_append(rec, ctx);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan if (ret <= 0)
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan break;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan break;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher }
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek case MAIL_TRANSACTION_EXPUNGE:
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan case MAIL_TRANSACTION_EXPUNGE|MAIL_TRANSACTION_EXPUNGE_PROT: {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan const struct mail_transaction_expunge *rec = data, *end;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ARRAY_TYPE(seq_range) seqs;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan uint32_t seq1, seq2;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan /* this is simply a request for expunge */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan break;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher }
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek t_array_init(&seqs, 64);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan end = CONST_PTR_OFFSET(data, hdr->size);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan for (; rec != end; rec++) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (mail_index_lookup_seq_range(ctx->view,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan rec->uid1, rec->uid2, &seq1, &seq2))
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan seq_range_array_add_range(&seqs, seq1, seq2);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan sync_expunge_range(ctx, &seqs);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher break;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan case MAIL_TRANSACTION_EXPUNGE_GUID:
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan case MAIL_TRANSACTION_EXPUNGE_GUID|MAIL_TRANSACTION_EXPUNGE_PROT: {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan const struct mail_transaction_expunge_guid *rec = data, *end;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ARRAY_TYPE(seq_range) seqs;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan uint32_t seq;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* this is simply a request for expunge */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher t_array_init(&seqs, 64);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher end = CONST_PTR_OFFSET(data, hdr->size);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (; rec != end; rec++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_assert(rec->uid != 0);
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (mail_index_lookup_seq(ctx->view, rec->uid, &seq))
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher seq_range_array_add(&seqs, seq);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher sync_expunge_range(ctx, &seqs);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher case MAIL_TRANSACTION_FLAG_UPDATE: {
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek const struct mail_transaction_flag_update *rec, *end;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher end = CONST_PTR_OFFSET(data, hdr->size);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (rec = data; rec < end; rec++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = sync_flag_update(rec, ctx);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher if (ret <= 0)
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher break;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher }
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher break;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek case MAIL_TRANSACTION_HEADER_UPDATE: {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const struct mail_transaction_header_update *rec;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher unsigned int i;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; i < hdr->size; ) {
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher rec = CONST_PTR_OFFSET(data, i);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher ret = sync_header_update(rec, ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ret <= 0)
e59e09b5010f262228bbdeb92a79b733bf5854b3Stephen Gallagher break;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek i += sizeof(*rec) + rec->size;
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek if ((i % 4) != 0)
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek i += 4 - (i % 4);
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek }
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek break;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek }
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek case MAIL_TRANSACTION_EXT_INTRO: {
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek const struct mail_transaction_ext_intro *rec = data;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek unsigned int i;
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek uint32_t prev_seq;
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek uoff_t prev_offset;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek &prev_seq, &prev_offset);
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek ctx->ext_intro_seq = prev_seq;
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek ctx->ext_intro_offset = prev_offset;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek ctx->ext_intro_end_offset =
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek prev_offset + hdr->size + sizeof(*hdr);
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek for (i = 0; i < hdr->size; ) {
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek if (i + sizeof(*rec) > hdr->size) {
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek /* should be just extra padding */
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek break;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek }
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek rec = CONST_PTR_OFFSET(data, i);
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek /* name_size checked by _log_view_next() */
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek i_assert(i + sizeof(*rec) + rec->name_size <= hdr->size);
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek ret = mail_index_sync_ext_intro(ctx, rec);
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek if (ret <= 0)
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek break;
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek i += sizeof(*rec) + rec->name_size;
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek if ((i % 4) != 0)
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek i += 4 - (i % 4);
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek }
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek break;
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek }
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek case MAIL_TRANSACTION_EXT_RESET: {
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek struct mail_transaction_ext_reset rec;
e5c33e0bd03a2deb8e5011deeb3ae93f960910eeJakub Hrozek
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek /* old versions have only new_reset_id */
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek if (hdr->size < sizeof(uint32_t)) {
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek mail_index_sync_set_corrupted(ctx,
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek "ext reset: invalid record size");
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek ret = -1;
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek break;
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek }
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek memset(&rec, 0, sizeof(rec));
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek memcpy(&rec, data, I_MIN(hdr->size, sizeof(rec)));
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek ret = mail_index_sync_ext_reset(ctx, &rec);
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek break;
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek }
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek case MAIL_TRANSACTION_EXT_HDR_UPDATE: {
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek const struct mail_transaction_ext_hdr_update *rec;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek unsigned int i;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek for (i = 0; i < hdr->size; ) {
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek rec = CONST_PTR_OFFSET(data, i);
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek if (i + sizeof(*rec) > hdr->size ||
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek i + sizeof(*rec) + rec->size > hdr->size) {
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek mail_index_sync_set_corrupted(ctx,
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek "ext hdr update: invalid record size");
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek ret = -1;
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek break;
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek }
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek ret = mail_index_sync_ext_hdr_update(ctx, rec->offset,
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek rec->size, rec + 1);
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek if (ret <= 0)
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek break;
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek i += sizeof(*rec) + rec->size;
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek if ((i % 4) != 0)
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek i += 4 - (i % 4);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek }
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek break;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek }
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek case MAIL_TRANSACTION_EXT_HDR_UPDATE32: {
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek const struct mail_transaction_ext_hdr_update32 *rec;
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek unsigned int i;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek for (i = 0; i < hdr->size; ) {
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek rec = CONST_PTR_OFFSET(data, i);
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek if (i + sizeof(*rec) > hdr->size ||
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek i + sizeof(*rec) + rec->size > hdr->size) {
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek mail_index_sync_set_corrupted(ctx,
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek "ext hdr update: invalid record size");
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek ret = -1;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek break;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek }
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek ret = mail_index_sync_ext_hdr_update(ctx, rec->offset,
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek rec->size, rec + 1);
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek if (ret <= 0)
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek break;
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher i += sizeof(*rec) + rec->size;
481ec0e1eb0058195732cb320845b41f6f4d43ebJakub Hrozek if ((i % 4) != 0)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i += 4 - (i % 4);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan break;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan case MAIL_TRANSACTION_EXT_REC_UPDATE: {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher const struct mail_transaction_ext_rec_update *rec;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher const struct mail_index_ext *ext;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan unsigned int i, record_size;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan if (ctx->cur_ext_map_idx == (uint32_t)-1) {
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan mail_index_sync_set_corrupted(ctx,
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan "Extension record updated "
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher "without intro prefix");
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = -1;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher break;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan if (ctx->cur_ext_ignore) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = 1;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher break;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ext = array_idx(&ctx->view->map->extensions,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ctx->cur_ext_map_idx);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher /* the record is padded to 32bits in the transaction log */
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher record_size = (sizeof(*rec) + ext->record_size + 3) & ~3;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan for (i = 0; i < hdr->size; i += record_size) {
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher rec = CONST_PTR_OFFSET(data, i);
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher if (i + record_size > hdr->size) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_index_sync_set_corrupted(ctx,
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher "ext rec update: invalid record size");
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek ret = -1;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan break;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher ret = mail_index_sync_ext_rec_update(ctx, rec);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek if (ret <= 0)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan break;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan break;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher }
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek case MAIL_TRANSACTION_EXT_ATOMIC_INC: {
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher const struct mail_transaction_ext_atomic_inc *rec, *end;
486237ee009f1d84fc4c85665dce80ade76f7079Stephen Gallagher
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher if (ctx->cur_ext_map_idx == (uint32_t)-1) {
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher mail_index_sync_set_corrupted(ctx,
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek "Extension record updated "
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher "without intro prefix");
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher ret = -1;
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher break;
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher }
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher if (ctx->cur_ext_ignore) {
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher ret = 1;
486237ee009f1d84fc4c85665dce80ade76f7079Stephen Gallagher break;
486237ee009f1d84fc4c85665dce80ade76f7079Stephen Gallagher }
486237ee009f1d84fc4c85665dce80ade76f7079Stephen Gallagher
486237ee009f1d84fc4c85665dce80ade76f7079Stephen Gallagher end = CONST_PTR_OFFSET(data, hdr->size);
486237ee009f1d84fc4c85665dce80ade76f7079Stephen Gallagher for (rec = data; rec < end; rec++) {
486237ee009f1d84fc4c85665dce80ade76f7079Stephen Gallagher ret = mail_index_sync_ext_atomic_inc(ctx, rec);
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher if (ret <= 0)
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher break;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek }
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher break;
486237ee009f1d84fc4c85665dce80ade76f7079Stephen Gallagher }
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher case MAIL_TRANSACTION_KEYWORD_UPDATE: {
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher const struct mail_transaction_keyword_update *rec = data;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher ret = mail_index_sync_keywords(ctx, hdr, rec);
7797e361155f7ce937085fd98e360469d7baf1b6Jakub Hrozek break;
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher }
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher case MAIL_TRANSACTION_KEYWORD_RESET: {
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek const struct mail_transaction_keyword_reset *rec = data;
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher ret = mail_index_sync_keywords_reset(ctx, hdr, rec);
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher break;
7797e361155f7ce937085fd98e360469d7baf1b6Jakub Hrozek }
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher case MAIL_TRANSACTION_MODSEQ_UPDATE: {
7797e361155f7ce937085fd98e360469d7baf1b6Jakub Hrozek const struct mail_transaction_modseq_update *rec = data;
7797e361155f7ce937085fd98e360469d7baf1b6Jakub Hrozek
7797e361155f7ce937085fd98e360469d7baf1b6Jakub Hrozek ret = sync_modseq_update(ctx, rec, hdr->size);
7797e361155f7ce937085fd98e360469d7baf1b6Jakub Hrozek break;
dd3ba5c5b7d2a9d109963ae9e6c94fff34872221Stephen Gallagher }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek case MAIL_TRANSACTION_INDEX_DELETED:
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek /* next sync finishes the deletion */
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek ctx->view->index->index_delete_requested = TRUE;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek } else {
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek /* transaction log reading handles this */
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek break;
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek case MAIL_TRANSACTION_INDEX_UNDELETED:
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek ctx->view->index->index_delete_requested = FALSE;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek break;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek case MAIL_TRANSACTION_BOUNDARY:
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek break;
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek case MAIL_TRANSACTION_ATTRIBUTE_UPDATE:
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek modseq = mail_transaction_log_view_get_prev_modseq(ctx->view->log_view);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek mail_index_modseq_update_highest(ctx->modseq_ctx, modseq);
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek break;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek default:
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek mail_index_sync_set_corrupted(ctx,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek "Unknown transaction record type 0x%x",
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek (hdr->type & MAIL_TRANSACTION_TYPE_MASK));
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek ret = -1;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek break;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek }
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek return ret;
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek}
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozekint mail_index_sync_record(struct mail_index_sync_map_ctx *ctx,
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek const struct mail_transaction_header *hdr,
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek const void *data)
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek{
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek int ret;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek T_BEGIN {
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek ret = mail_index_sync_record_real(ctx, hdr, data);
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek } T_END;
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek return ret;
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek}
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozekvoid mail_index_sync_map_init(struct mail_index_sync_map_ctx *sync_map_ctx,
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek struct mail_index_view *view,
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek enum mail_index_sync_handler_type type)
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek{
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek memset(sync_map_ctx, 0, sizeof(*sync_map_ctx));
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek sync_map_ctx->view = view;
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek sync_map_ctx->cur_ext_map_idx = (uint32_t)-1;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek sync_map_ctx->type = type;
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek sync_map_ctx->modseq_ctx = mail_index_modseq_sync_begin(sync_map_ctx);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek mail_index_sync_init_handlers(sync_map_ctx);
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek}
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozekvoid mail_index_sync_map_deinit(struct mail_index_sync_map_ctx *sync_map_ctx)
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek{
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek i_assert(sync_map_ctx->modseq_ctx == NULL);
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek if (sync_map_ctx->unknown_extensions != NULL)
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek buffer_free(&sync_map_ctx->unknown_extensions);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek if (sync_map_ctx->expunge_handlers_used)
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek mail_index_sync_deinit_expunge_handlers(sync_map_ctx);
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek mail_index_sync_deinit_handlers(sync_map_ctx);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek}
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozekstatic void mail_index_sync_update_hdr_dirty_flag(struct mail_index_map *map)
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek{
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek const struct mail_index_record *rec;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek unsigned int i;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek if ((map->hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) != 0)
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek return;
5ee3fba0bd812242a1ffe189f5ddf2689e6e6811Jakub Hrozek
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek /* do we have dirty flags anymore? */
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek for (i = 0; i < map->rec_map->records_count; i++) {
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek rec = MAIL_INDEX_MAP_IDX(map, i);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) {
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek map->hdr.flags |= MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek break;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek }
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek }
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek}
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek#ifdef DEBUG
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozekvoid mail_index_map_check(struct mail_index_map *map)
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek{
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek const struct mail_index_header *hdr = &map->hdr;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek unsigned int i, del = 0, seen = 0;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek uint32_t prev_uid = 0;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek i_assert(hdr->messages_count <= map->rec_map->records_count);
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek for (i = 0; i < hdr->messages_count; i++) {
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek const struct mail_index_record *rec;
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek rec = MAIL_INDEX_MAP_IDX(map, i);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek i_assert(rec->uid > prev_uid);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek prev_uid = rec->uid;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek if (rec->flags & MAIL_DELETED) {
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek i_assert(rec->uid >= hdr->first_deleted_uid_lowwater);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek del++;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek }
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek if (rec->flags & MAIL_SEEN)
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek seen++;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek else
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek i_assert(rec->uid >= hdr->first_unseen_uid_lowwater);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek }
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek i_assert(del == hdr->deleted_messages_count);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek i_assert(seen == hdr->seen_messages_count);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek}
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek#endif
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozekint mail_index_sync_map(struct mail_index_map **_map,
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek enum mail_index_sync_handler_type type, bool force)
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek{
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek struct mail_index_map *map = *_map;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek struct mail_index *index = map->index;
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek struct mail_index_view *view;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek struct mail_index_sync_map_ctx sync_map_ctx;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek const struct mail_transaction_header *thdr;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek const void *tdata;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek uint32_t prev_seq;
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek uoff_t start_offset, prev_offset;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek int ret;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek bool had_dirty, reset;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek i_assert(index->map == map || type == MAIL_INDEX_SYNC_HANDLER_VIEW);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek
531661c7bb54eb71853977a64cb30f80c20b963eJakub Hrozek if (index->log->head == NULL) {
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek i_assert(!force);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek return 0;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek }
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek start_offset = type == MAIL_INDEX_SYNC_HANDLER_FILE ?
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek map->hdr.log_file_tail_offset : map->hdr.log_file_head_offset;
a23014d69b56cbdf48ad05229c334648b5309d8fJakub Hrozek if (!force && (index->flags & MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE) == 0) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher /* see if we'd prefer to reopen the index file instead of
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek syncing the current map from the transaction log.
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan don't check this if mmap is disabled, because reopening
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan index causes sync to get lost. */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan uoff_t log_size, index_size;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek if (index->fd == -1 &&
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan index->log->head->hdr.prev_file_seq != 0) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher /* we don't know the index's size, so use the
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan smallest index size we're willing to read */
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan index_size = MAIL_INDEX_SYNC_MIN_READ_INDEX_SIZE;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan } else {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan index_size = map->hdr.header_size +
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher map->rec_map->records_count *
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek map->hdr.record_size;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* this isn't necessary correct currently, but it should be
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher close enough */
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek log_size = index->log->head->last_size;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (log_size > start_offset &&
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan log_size - start_offset > index_size)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return 0;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher view = mail_index_view_open_with_map(index, map);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = mail_transaction_log_view_set(view->log_view,
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher map->hdr.log_file_seq, start_offset,
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek (uint32_t)-1, (uoff_t)-1, &reset);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (ret <= 0) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_index_view_close(&view);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (force && ret == 0) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher /* the seq/offset is probably broken */
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek mail_index_set_error(index, "Index %s: Lost log for "
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan "seq=%u offset=%"PRIuUOFF_T, index->filepath,
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan map->hdr.log_file_seq, start_offset);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan (void)mail_index_fsck(index);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher }
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek /* can't use it. sync by re-reading index. */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return 0;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_transaction_log_get_head(index->log, &prev_seq, &prev_offset);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (prev_seq != map->hdr.log_file_seq ||
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher prev_offset - map->hdr.log_file_tail_offset >
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher MAIL_INDEX_MIN_WRITE_BYTES) {
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher /* we're reading more from log than we would have preferred.
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan remember that we probably want to rewrite index soon. */
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher index->index_min_write = TRUE;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* view referenced the map. avoid unnecessary map cloning by
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan unreferencing the map while view exists. */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan map->refcount--;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan had_dirty = (map->hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) != 0;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (had_dirty)
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher map->hdr.flags &= ~MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher if (map->hdr_base != map->hdr_copy_buf->data) {
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher /* if syncing updates the header, it updates hdr_copy_buf
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher and updates hdr_base to hdr_copy_buf. so the buffer must
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan initially contain a valid header or we'll break it when
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher writing it. */
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek buffer_reset(map->hdr_copy_buf);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan buffer_append(map->hdr_copy_buf, map->hdr_base,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan map->hdr.header_size);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan map->hdr_base = map->hdr_copy_buf->data;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_transaction_log_view_get_prev_pos(view->log_view,
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher &prev_seq, &prev_offset);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher mail_index_sync_map_init(&sync_map_ctx, view, type);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher if (reset) {
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher /* Reset the entire index. Leave only indexid and
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan log_file_seq. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mail_transaction_log_view_get_prev_pos(view->log_view,
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek &prev_seq, &prev_offset);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher map = mail_index_map_alloc(index);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher map->hdr.log_file_seq = prev_seq;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher map->hdr.log_file_tail_offset = 0;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher mail_index_sync_replace_map(&sync_map_ctx, map);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan map = NULL;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* FIXME: when transaction sync lock is removed, we'll need to handle
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher the case when a transaction is committed while mailbox is being
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek synced ([synced transactions][new transaction][ext transaction]).
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan this means int_offset contains [synced] and ext_offset contains
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan all */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan while ((ret = mail_transaction_log_view_next(view->log_view, &thdr,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan &tdata)) > 0) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_transaction_log_view_get_prev_pos(view->log_view,
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher &prev_seq, &prev_offset);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher if (LOG_IS_BEFORE(prev_seq, prev_offset,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan view->map->hdr.log_file_seq,
6463ed1dcdd45416468b3fa178bd856b5a9ed2c3Jakub Hrozek view->map->hdr.log_file_head_offset)) {
261cdde02b40aa8dabb3d69e43586a5a220647e9Jakub Hrozek /* this has been synced already. we're here only to call
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan expunge handlers and extension update handlers. */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_assert(type == MAIL_INDEX_SYNC_HANDLER_FILE);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher if ((thdr->type & MAIL_TRANSACTION_EXTERNAL) != 0)
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek continue;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if ((thdr->type & MAIL_TRANSACTION_EXT_MASK) == 0)
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan continue;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek /* we'll just skip over broken entries */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan (void)mail_index_sync_record(&sync_map_ctx, thdr, tdata);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher map = view->map;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (had_dirty)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_index_sync_update_hdr_dirty_flag(map);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher mail_index_modseq_sync_end(&sync_map_ctx.modseq_ctx);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher mail_index_sync_update_log_offset(&sync_map_ctx, view->map, TRUE);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher#ifdef DEBUG
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan mail_index_map_check(map);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#endif
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek i_assert(map->hdr.indexid == index->indexid || map->hdr.indexid == 0);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* transaction log tracks internally the current tail offset.
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan besides using header updates, it also updates the offset to skip
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher over following external transactions to avoid extra unneeded log
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek reading. */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_assert(map->hdr.log_file_seq == index->log->head->hdr.file_seq);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan if (map->hdr.log_file_tail_offset < index->log->head->max_tail_offset) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan map->hdr.log_file_tail_offset =
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher index->log->head->max_tail_offset;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan buffer_write(map->hdr_copy_buf, 0, &map->hdr, sizeof(map->hdr));
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (!MAIL_INDEX_MAP_IS_IN_MEMORY(map)) {
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan memcpy(map->rec_map->mmap_base, map->hdr_copy_buf->data,
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan map->hdr_copy_buf->used);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek /* restore refcount before closing the view. this is necessary also
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek if map got cloned, because view closing would otherwise destroy it */
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek map->refcount++;
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher mail_index_sync_map_deinit(&sync_map_ctx);
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek mail_index_view_close(&view);
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher i_assert(index->map == map || type == MAIL_INDEX_SYNC_HANDLER_VIEW);
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek if (mail_index_map_check_header(map) <= 0) {
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher mail_index_set_error(index,
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek "Synchronization corrupted index header: %s",
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek index->filepath);
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher (void)mail_index_fsck(index);
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek map = index->map;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek } else if (sync_map_ctx.errors) {
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek /* make sure the index looks valid now */
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek (void)mail_index_fsck(index);
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher map = index->map;
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek }
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher *_map = map;
2cb6f28b3a12bb714bf14494d31eb6b6fff64b8bJakub Hrozek return ret < 0 ? -1 : 1;
be5cc3c013ece0c957f2f8c28a217052227dfd07Jakub Hrozek}
a7797068c4deb6ce2bdbcda27c45ff1bbb4a8e78Jakub Hrozek