mail-index-view-sync.c revision d39c0e195c67be5f2b0a15f25a8d6039bef02711
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher/* Copyright (C) 2003-2004 Timo Sirainen */
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher const struct mail_transaction_header *hdr;
e65df5b966b27e13283c65f59f99ac44781e0333Simo Sorce const void *data;
cc98edd9479d4622634a1275c98058916c14059aStephen Gallagherview_sync_get_expunges(struct mail_index_view *view, buffer_t **expunges_r)
cc98edd9479d4622634a1275c98058916c14059aStephen Gallagher const struct mail_transaction_header *hdr;
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březina struct mail_transaction_expunge *src, *src_end, *dest;
002f84aea86371aa079b867c0ec39396b97109d3Lukas Slebodnik if (mail_transaction_log_view_set(view->log_view,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *expunges_r = buffer_create_dynamic(default_pool, 512);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher while ((ret = mail_transaction_log_view_next(view->log_view,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0);
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek /* convert to sequences */
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek src = dest = buffer_get_modifyable_data(*expunges_r, &size);
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek ret = mail_index_lookup_uid_range(view, src->uid1,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#define MAIL_INDEX_VIEW_VISIBLE_SYNC_MASK \
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (MAIL_TRANSACTION_EXPUNGE | MAIL_TRANSACTION_APPEND | \
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MAIL_TRANSACTION_FLAG_UPDATE | MAIL_TRANSACTION_KEYWORD_UPDATE | \
d921c1eba437662437847279f251a0a5d8f70127Maximint mail_index_view_sync_begin(struct mail_index_view *view,
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer /* We must sync flags as long as view is mmap()ed, as the flags may
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer have already changed under us. */
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer i_assert((sync_mask & MAIL_INDEX_SYNC_TYPE_FLAGS) != 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail_index_view_lock_head(view, TRUE) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* get list of all expunges first */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (view_sync_get_expunges(view, &expunges) < 0)
07d82f79d2970a08628ebf71343441ec55faa6faPavel Březina /* only flags, appends and expunges can be left to be synced later */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher want_mask = mail_transaction_type_mask_get(sync_mask);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert((want_mask & ~MAIL_INDEX_VIEW_VISIBLE_SYNC_MASK) == 0);
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose if (mail_transaction_log_view_set(view->log_view,
32381402a4a9afc003782c9e2301fc59c9bda2a9Yassir Elley ctx = i_new(struct mail_index_view_sync_ctx, 1);
e124844907ed6973915e4d56f5442ecd07535a12Jakub Hrozek mail_index_sync_map_init(&ctx->sync_map_ctx, view,
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0 &&
e07a94a66985b674c5df11ca466792902164c4e2George McCollister (sync_mask & MAIL_INDEX_SYNC_TYPE_APPEND) != 0) {
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer /* keep the old mapping without expunges until we're
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose fully synced */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* we need a private copy of the map if we don't want to
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher sync expunges. we need to sync mapping only if we're not
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher using the latest one. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uint32_t old_records_count = view->map->records_count;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher view->map->records_count = view->hdr.messages_count;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher view->map->records_count = old_records_count;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (map->hdr_base != map->hdr_copy_buf->data) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_append(map->hdr_copy_buf, map->hdr_base,
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose /* start from our old view's header. */
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina i_assert(map->records_count == map->hdr.messages_count);
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagherstatic int view_is_transaction_synced(struct mail_index_view *view,
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik const struct mail_index_view_log_sync_pos *pos, *end;
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher pos = buffer_get_data(view->log_syncs, &size);
539b1be3507abdf8ac235b06eeed5011b0b5cde2Ondrej Kos if (pos->log_file_offset == offset && pos->log_file_seq == seq)
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozekstatic int mail_index_view_sync_next_trans(struct mail_index_view_sync_ctx *ctx,
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek struct mail_transaction_log_view *log_view = ctx->view->log_view;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = mail_transaction_log_view_next(log_view, &ctx->hdr, &ctx->data,
b50dffea929ee5cd0c59ba3c4822337cc162ff92Kamil Dudka mail_transaction_log_view_get_prev_pos(log_view, seq_r, offset_r);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* skip flag changes that we committed ourself or have already synced */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (view_is_transaction_synced(view, *seq_r, *offset_r))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* expunges have to be synced afterwards so that caller can still get
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek information of the messages. otherwise caller most likely wants to
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek see only updated information. */
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek (ctx->hdr->type & MAIL_TRANSACTION_EXPUNGE) == 0) {
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek if (mail_index_sync_record(&ctx->sync_map_ctx, ctx->hdr,
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek if ((ctx->hdr->type & ctx->trans_sync_mask) == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ((((u)->add_flags | (u)->remove_flags) & \
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek ~(MAIL_INDEX_MAIL_FLAG_DIRTY | MAIL_RECENT)) == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghermail_index_view_sync_get_rec(struct mail_index_view_sync_ctx *ctx,
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik const struct mail_transaction_header *hdr = ctx->hdr;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik const struct mail_transaction_expunge *exp =
72e60fd4eabcfbcdbfe01e8c38b94052bc6c2067Jakub Hrozek const struct mail_transaction_flag_update *update =
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik update = CONST_PTR_OFFSET(data, ctx->data_offset);
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik const struct mail_transaction_keyword_update *update = data;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik ctx->data_offset = sizeof(*update) + update->name_size;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik ctx->data_offset += 4 - (ctx->data_offset % 4);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik uids = CONST_PTR_OFFSET(data, ctx->data_offset);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik /* FIXME: this isn't exactly correct.. but no-one cares? */
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik rec->type = MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik const struct mail_transaction_keyword_reset *reset =
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik rec->type = MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherint mail_index_view_sync_next(struct mail_index_view_sync_ctx *ctx,
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek if (ctx->hdr == NULL || ctx->data_offset == ctx->hdr->size) {
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek ret = mail_index_view_sync_next_trans(ctx, &seq,
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce } while (ret == 0);
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce } while (!mail_index_view_sync_get_rec(ctx, sync_rec));
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnikmail_index_view_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik data = buffer_get_data(ctx->expunges, &size);
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnikvoid mail_index_view_sync_end(struct mail_index_view_sync_ctx *ctx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_index_sync_map_deinit(&ctx->sync_map_ctx);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (view->log_syncs != NULL && !ctx->skipped_some)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!ctx->last_read && ctx->hdr != NULL &&
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* we didn't sync everything */
9d453f1e8b28983b363b44c49b7cd701a994fd97Nikolai Kondrashov mail_index_unmap(view->index, view->map);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (void)mail_transaction_log_view_set(view->log_view,