mail-index-sync-update.c revision f6d5c9fbdac9af5c4d3f467f828dc6f056309d5e
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher/* Copyright (c) 2004-2016 Dovecot authors, see the included COPYING file */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher/* If we have less than this many bytes to sync from log file, don't bother
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher reading the main index */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#define MAIL_INDEX_SYNC_MIN_READ_INDEX_SIZE 2048
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallaghermail_index_sync_update_log_offset(struct mail_index_sync_map_ctx *ctx,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* handling lost changes in view syncing */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (prev_offset == ctx->ext_intro_end_offset &&
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* previous transaction was an extension introduction.
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher we probably came here from
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_index_sync_ext_reset(). if there are any more
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher views which want to continue syncing it needs the
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher intro. so back up a bit more.
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher don't do this in case the last transaction in the
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher log is the extension intro, so we don't keep trying
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher to sync it over and over again. */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_assert(ctx->view->index->log->head->hdr.file_seq == prev_seq);
fd555d130dc733509347fa096a2cb858b014a196Simo Sorcestatic void mail_index_sync_replace_map(struct mail_index_sync_map_ctx *ctx,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_index_sync_update_log_offset(ctx, view->map, FALSE);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ctx->type != MAIL_INDEX_SYNC_HANDLER_VIEW)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_index_modseq_sync_map_replaced(ctx->modseq_ctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallaghermail_index_sync_move_to_private_memory(struct mail_index_sync_map_ctx *ctx)
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek if (!MAIL_INDEX_MAP_IS_IN_MEMORY(ctx->view->map))
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce mail_index_modseq_sync_map_replaced(ctx->modseq_ctx);
fd555d130dc733509347fa096a2cb858b014a196Simo Sorcemail_index_sync_get_atomic_map(struct mail_index_sync_map_ctx *ctx)
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce (void)mail_index_sync_move_to_private_memory(ctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_index_record_map_move_to_private(ctx->view->map);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_index_modseq_sync_map_replaced(ctx->modseq_ctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallaghermail_index_header_update_counts(struct mail_index_header *hdr,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (((old_flags ^ new_flags) & MAIL_SEEN) != 0) {
681742138b2afbbefa7f14de937beb438409208eSimo Sorce /* different seen-flag */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (hdr->seen_messages_count >= hdr->messages_count) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (++hdr->seen_messages_count == hdr->messages_count)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher hdr->first_unseen_uid_lowwater = hdr->next_uid;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (((old_flags ^ new_flags) & MAIL_DELETED) != 0) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* different deleted-flag */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (hdr->deleted_messages_count > hdr->messages_count) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher hdr->deleted_messages_count > hdr->messages_count) {
fd555d130dc733509347fa096a2cb858b014a196Simo Sorcemail_index_sync_header_update_counts_all(struct mail_index_sync_map_ctx *ctx,
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce const char *error;
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce unsigned int i, count;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher maps = array_get(&ctx->view->map->rec_map->maps, &count);
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce for (i = 0; i < count; i++) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (mail_index_header_update_counts(&maps[i]->hdr,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_index_sync_set_corrupted(ctx, "%s", error);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallaghermail_index_sync_header_update_counts(struct mail_index_sync_map_ctx *ctx,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (uid >= ctx->view->map->hdr.next_uid) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_index_sync_set_corrupted(ctx, "uid %u >= next_uid %u",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (mail_index_header_update_counts(&ctx->view->map->hdr,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_index_sync_set_corrupted(ctx, "%s", error);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallaghermail_index_header_update_lowwaters(struct mail_index_sync_map_ctx *ctx,
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek unsigned int i, count;
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek maps = array_get(&ctx->view->map->rec_map->maps, &count);
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek for (i = 0; i < count; i++) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher maps[i]->hdr.first_unseen_uid_lowwater = uid;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher uid < maps[i]->hdr.first_deleted_uid_lowwater)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher maps[i]->hdr.first_deleted_uid_lowwater = uid;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallaghersync_expunge_call_handlers(struct mail_index_sync_map_ctx *ctx,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher const struct mail_index_expunge_handler *eh;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher array_foreach(&ctx->expunge_handlers, eh) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher rec = MAIL_INDEX_REC_AT_SEQ(ctx->view->map, seq);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* FIXME: does expunge handler's return value matter?
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher we probably shouldn't disallow expunges if the
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher handler returns failure.. should it be just changed
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher to return void? */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallaghersync_expunge_handlers_init(struct mail_index_sync_map_ctx *ctx)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* call expunge handlers only when syncing index file */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ctx->type != MAIL_INDEX_SYNC_HANDLER_FILE)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_index_sync_init_expunge_handlers(ctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (!array_is_created(&ctx->expunge_handlers))
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallaghersync_expunge_range(struct mail_index_sync_map_ctx *ctx, const ARRAY_TYPE(seq_range) *seqs)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher unsigned int i, count;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher uint32_t dest_seq1, prev_seq2, orig_rec_count;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher map = mail_index_sync_get_atomic_map(ctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* call the expunge handlers first */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher for (i = 0; i < count; i++) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher orig_rec_count = map->rec_map->records_count;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher for (i = 0; i < count; i++) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_index_sync_header_update_counts(ctx, rec->uid, rec->flags, 0);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* @UNSAFE: move (prev_seq2+1) .. (seq1-1) to its
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher final location in the map if necessary */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher uint32_t move_count = (seq1-1) - (prev_seq2+1) + 1;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher memmove(MAIL_INDEX_REC_AT_SEQ(map, dest_seq1),
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_index_modseq_expunge(ctx->modseq_ctx, seq1, seq2);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* Final stragglers */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher uint32_t final_move_count = orig_rec_count - prev_seq2;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher memmove(MAIL_INDEX_REC_AT_SEQ(map, dest_seq1),
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void *sync_append_record(struct mail_index_map *map)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher append_pos = map->rec_map->records_count * map->hdr.record_size;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = buffer_get_space_unsafe(map->rec_map->buffer, append_pos,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher buffer_get_modifiable_data(map->rec_map->buffer, NULL);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic bool sync_update_ignored_change(struct mail_index_sync_map_ctx *ctx)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct mail_index_transaction_commit_result *result =
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher uoff_t prev_log_offset, trans_start_offset, trans_end_offset;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* we'll return TRUE if this modseq change was written within the
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher transaction that was just committed */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher trans_end_offset = result->log_file_offset;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher trans_start_offset = trans_end_offset - result->commit_size;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (prev_log_offset < trans_start_offset ||
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallaghersync_modseq_update(struct mail_index_sync_map_ctx *ctx,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher const struct mail_transaction_modseq_update *u,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher const struct mail_transaction_modseq_update *end;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher for (; u < end; u++) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher else if (!mail_index_lookup_seq(view, u->uid, &seq))
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher min_modseq = ((uint64_t)u->modseq_high32 << 32) |
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher mail_index_modseq_set(view, seq, min_modseq);
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher "modseqs updated before they were enabled");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret == 0 && sync_update_ignored_change(ctx))
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher view->index->sync_commit_result->ignored_modseq_changes++;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_index_modseq_update_highest(ctx->modseq_ctx, highest_modseq);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic int sync_append(const struct mail_index_record *rec,
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher "Append with UID %u, but next_uid = %u",
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek /* move to memory. the mapping is written when unlocking so we don't
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek waste time re-mmap()ing multiple times or waste space growing index
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek file too large */
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek map = mail_index_sync_move_to_private_memory(ctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (rec->uid <= map->rec_map->last_appended_uid) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_assert(map->hdr.messages_count < map->rec_map->records_count);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* the flags may have changed since it was added to map.
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher use the updated flags already, so flag counters won't get
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher old_rec = MAIL_INDEX_MAP_IDX(map, map->hdr.messages_count);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* don't rely on buffer->used being at the correct position.
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher at least expunges can move it */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher map->rec_map->last_appended_uid = rec->uid;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if ((new_flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher map->hdr.flags |= MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_index_header_update_lowwaters(ctx, rec->uid, new_flags);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_index_sync_header_update_counts(ctx, rec->uid, 0, new_flags);
681742138b2afbbefa7f14de937beb438409208eSimo Sorcestatic int sync_flag_update(const struct mail_transaction_flag_update *u,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (!mail_index_lookup_seq_range(view, u->uid1, u->uid2, &seq1, &seq2))
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (!MAIL_TRANSACTION_FLAG_UPDATE_IS_INTERNAL(u)) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_index_modseq_update_flags(ctx->modseq_ctx,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if ((u->add_flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher view->map->hdr.flags |= MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* we're not modifying any counted/lowwatered flags */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher rec = MAIL_INDEX_REC_AT_SEQ(view->map, seq);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher rec->flags = (rec->flags & flag_mask) | u->add_flags;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher rec = MAIL_INDEX_REC_AT_SEQ(view->map, seq);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher rec->flags = (rec->flags & flag_mask) | u->add_flags;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_index_header_update_lowwaters(ctx, rec->uid,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_index_sync_header_update_counts_all(ctx, rec->uid,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic int sync_header_update(const struct mail_transaction_header_update *u,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#define MAIL_INDEX_HEADER_UPDATE_FIELD_IN_RANGE(u, field) \
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ((u)->offset <= offsetof(struct mail_index_header, field) && \
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher (u)->offset + (u)->size > offsetof(struct mail_index_header, field))
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct mail_index_map *map = ctx->view->map;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher uint32_t orig_log_file_tail_offset = map->hdr.log_file_tail_offset;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher uint32_t orig_next_uid = map->hdr.next_uid;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (u->offset >= map->hdr.base_header_size ||
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher u->offset + u->size > map->hdr.base_header_size) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Header update outside range: %u + %u > %u",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher u->offset, u->size, map->hdr.base_header_size);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher buffer_write(map->hdr_copy_buf, u->offset, u + 1, u->size);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if ((uint32_t)(u->offset + u->size) <= sizeof(map->hdr)) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher } else if (u->offset < sizeof(map->hdr)) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* next_uid update tried to shrink its value. this can happen
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher in some race conditions with e.g. with dsync, so just
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher silently ignore it. */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* the tail offset updates are intended for internal transaction
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher log handling. we'll update the offset in the header only when
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher the sync is finished. */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher map->hdr.log_file_tail_offset = orig_log_file_tail_offset;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallaghermail_index_sync_record_real(struct mail_index_sync_map_ctx *ctx,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher const struct mail_transaction_header *hdr,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher const struct mail_index_record *rec, *end;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher case MAIL_TRANSACTION_EXPUNGE|MAIL_TRANSACTION_EXPUNGE_PROT: {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher const struct mail_transaction_expunge *rec = data, *end;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* this is simply a request for expunge */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (mail_index_lookup_seq_range(ctx->view,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher seq_range_array_add_range(&seqs, seq1, seq2);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher case MAIL_TRANSACTION_EXPUNGE_GUID|MAIL_TRANSACTION_EXPUNGE_PROT: {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher const struct mail_transaction_expunge_guid *rec = data, *end;
d3d297c62e0340151da1d4ce1e082dcfcb45b431Jakub Hrozek if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* this is simply a request for expunge */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (mail_index_lookup_seq(ctx->view, rec->uid, &seq))
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher const struct mail_transaction_flag_update *rec, *end;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher const struct mail_transaction_header_update *rec;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher unsigned int i;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if ((i % 4) != 0)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher const struct mail_transaction_ext_intro *rec = data;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher unsigned int i;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* should be just extra padding */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* name_size checked by _log_view_next() */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_assert(i + sizeof(*rec) + rec->name_size <= hdr->size);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = mail_index_sync_ext_intro(ctx, rec);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if ((i % 4) != 0)
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek /* old versions have only new_reset_id */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "ext reset: invalid record size");
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek memcpy(&rec, data, I_MIN(hdr->size, sizeof(rec)));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher const struct mail_transaction_ext_hdr_update *rec;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher unsigned int i;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i + sizeof(*rec) + rec->size > hdr->size) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "ext hdr update: invalid record size");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = mail_index_sync_ext_hdr_update(ctx, rec->offset,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if ((i % 4) != 0)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher const struct mail_transaction_ext_hdr_update32 *rec;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher unsigned int i;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "ext hdr update: invalid record size");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = mail_index_sync_ext_hdr_update(ctx, rec->offset,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if ((i % 4) != 0)
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher const struct mail_transaction_ext_rec_update *rec;
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher unsigned int i, record_size;
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher "Extension record updated "
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher "without intro prefix");
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher ext = array_idx(&ctx->view->map->extensions,
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek /* the record is padded to 32bits in the transaction log */
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce record_size = (sizeof(*rec) + ext->record_size + 3) & ~3;
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce "ext rec update: invalid record size");
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher ret = mail_index_sync_ext_rec_update(ctx, rec);
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek const struct mail_transaction_ext_atomic_inc *rec, *end;
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek "Extension record updated "
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek "without intro prefix");
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek ret = mail_index_sync_ext_atomic_inc(ctx, rec);
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek const struct mail_transaction_keyword_update *rec = data;
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce const struct mail_transaction_keyword_reset *rec = data;
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce ret = mail_index_sync_keywords_reset(ctx, hdr, rec);
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce const struct mail_transaction_modseq_update *rec = data;
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce /* next sync finishes the deletion */
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek ctx->view->index->index_delete_requested = TRUE;
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce /* transaction log reading handles this */
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce ctx->view->index->index_delete_requested = FALSE;
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce modseq = mail_transaction_log_view_get_prev_modseq(ctx->view->log_view);
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce mail_index_modseq_update_highest(ctx->modseq_ctx, modseq);
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce "Unknown transaction record type 0x%x",
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorceint mail_index_sync_record(struct mail_index_sync_map_ctx *ctx,
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce const void *data)
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce ret = mail_index_sync_record_real(ctx, hdr, data);
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorcevoid mail_index_sync_map_init(struct mail_index_sync_map_ctx *sync_map_ctx,
#ifdef DEBUG
del++;
seen++;
const void *tdata;
int ret;
if (ret <= 0) {
if (had_dirty)
if (reset) {
&tdata)) > 0) {
if (had_dirty)
#ifdef DEBUG