mail-index-view-sync.c revision d67f54632110cfb6aafe2d7cd1f99b031c0b208a
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "lib.h"
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen#include "buffer.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "mail-index-view-private.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "mail-index-sync-private.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen#include "mail-transaction-log.h"
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen#include "mail-transaction-util.h"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct mail_index_view_sync_ctx {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mail_index_view *view;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen enum mail_index_sync_type sync_mask;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mail_index_map *sync_map;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen buffer_t *expunges;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t messages_count;
22627da0fb77c1d0d9a8e8bc485ef5540b6f2e69Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const struct mail_transaction_header *hdr;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const void *data;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen size_t data_offset;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int skipped:1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int last_read:1;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen};
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic int
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenview_sync_get_expunges(struct mail_index_view *view, buffer_t **expunges_r)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen const struct mail_transaction_expunge *exp, *end;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen buffer_t *expunges;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen size_t size;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen /* with mask 0 we don't get anything, we'll just read the expunges
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen while seeking to end */
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen if (mail_transaction_log_view_set(view->log_view,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen view->log_file_seq,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen view->log_file_offset,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen view->index->hdr->log_file_seq,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen view->index->hdr->log_file_offset,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen 0) < 0)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (mail_transaction_log_view_next(view->log_view,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen NULL, NULL, NULL) < 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen expunges = mail_transaction_log_view_get_expunges(view->log_view);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen exp = buffer_get_data(expunges, &size);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen end = CONST_PTR_OFFSET(exp, size);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen *expunges_r = buffer_create_dynamic(default_pool, size, (size_t)-1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen for (; exp != end; exp++) {
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainen buffer_append(*expunges_r, &exp->seq1, sizeof(exp->seq1));
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen buffer_append(*expunges_r, &exp->seq2, sizeof(exp->seq2));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_transaction_log_view_unset(view->log_view);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen return 0;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen}
9c2b0eb659540b9db8dd3a8a6a2515921fbe8eebTimo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenint mail_index_view_sync_begin(struct mail_index_view *view,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen enum mail_index_sync_type sync_mask,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mail_index_view_sync_ctx **ctx_r)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen{
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen const struct mail_index_header *hdr;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mail_index_view_sync_ctx *ctx;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mail_index_map *map;
f4c0b1874b0533bcf2df1d28d584ff02cfdae3faTimo Sirainen enum mail_transaction_type mask;
f4c0b1874b0533bcf2df1d28d584ff02cfdae3faTimo Sirainen buffer_t *expunges = NULL;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen /* We must sync flags as long as view is mmap()ed, as the flags may
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen have already changed under us. */
0db5b158a00c08955bdacc99b1e2cd1ec07f4311Timo Sirainen i_assert((sync_mask & MAIL_INDEX_SYNC_TYPE_FLAGS) != 0);
0db5b158a00c08955bdacc99b1e2cd1ec07f4311Timo Sirainen i_assert(view->transactions == 0);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_assert(!view->syncing);
d16b506f5540e3407d256bda35624b38a5ecf88fTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (mail_index_view_lock_head(view, TRUE) < 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen hdr = view->index->hdr;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* get list of all expunges first */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (view_sync_get_expunges(view, &expunges) < 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
a54fa00087ba926a3d966a8449d8d7579e89911cTimo Sirainen
a54fa00087ba926a3d966a8449d8d7579e89911cTimo Sirainen mask = mail_transaction_type_mask_get(sync_mask);
a54fa00087ba926a3d966a8449d8d7579e89911cTimo Sirainen if (mail_transaction_log_view_set(view->log_view,
a54fa00087ba926a3d966a8449d8d7579e89911cTimo Sirainen view->log_file_seq,
a54fa00087ba926a3d966a8449d8d7579e89911cTimo Sirainen view->log_file_offset,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen hdr->log_file_seq,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen hdr->log_file_offset, mask) < 0) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (expunges != NULL)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen buffer_free(expunges);
a54fa00087ba926a3d966a8449d8d7579e89911cTimo Sirainen return -1;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (sync_mask == MAIL_INDEX_SYNC_MASK_ALL) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen map = view->index->map;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen map->refcount++;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen } else {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen map = mail_index_map_to_memory(view->map);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen view->syncing = TRUE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx = i_new(struct mail_index_view_sync_ctx, 1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx->view = view;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx->sync_mask = sync_mask;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx->sync_map = map;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx->expunges = expunges;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx->messages_count = mail_index_view_get_message_count(view);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen *ctx_r = ctx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainenstatic int view_is_transaction_synced(struct mail_index_view *view,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t seq, uoff_t offset)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const unsigned char *data, *end;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen size_t size;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (view->log_syncs == NULL)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen data = buffer_get_data(view->log_syncs, &size);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen end = data + size;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen for (; data < end; ) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (*((const uoff_t *)data) == offset &&
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen *((const uint32_t *)(data + sizeof(uoff_t))) == seq)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen data += sizeof(uoff_t) + sizeof(uint32_t);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int sync_expunge(const struct mail_transaction_expunge *e, void *context)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mail_index_map *map = context;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int idx, count;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen for (idx = e->seq1-1; idx < e->seq2; idx++) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_header_update_counts(&map->hdr_copy,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen map->records[idx].flags, 0);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
d16b506f5540e3407d256bda35624b38a5ecf88fTimo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen count = e->seq2 - e->seq1 + 1;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen buffer_delete(map->buffer,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen (e->seq1-1) * sizeof(struct mail_index_record),
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen count * sizeof(struct mail_index_record));
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen map->records = buffer_get_modifyable_data(map->buffer, NULL);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen map->records_count -= count;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen map->hdr_copy.messages_count -= count;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return 1;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen}
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenstatic int sync_append(const struct mail_index_record *rec, void *context)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen struct mail_index_map *map = context;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen buffer_append(map->buffer, rec, sizeof(*rec));
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen map->records = buffer_get_modifyable_data(map->buffer, NULL);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen map->records_count++;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen map->hdr_copy.messages_count++;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen map->hdr_copy.next_uid = rec->uid+1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen mail_index_header_update_counts(&map->hdr_copy, 0, rec->flags);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_header_update_lowwaters(&map->hdr_copy, rec);
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen return 1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int sync_flag_update(const struct mail_transaction_flag_update *u,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen void *context)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mail_index_map *map = context;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mail_index_record *rec;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int i, idx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint8_t old_flags;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen for (idx = u->seq1-1; idx < u->seq2; idx++) {
a0b89f3b1df99b3a32f44623f13ad1893118825bTimo Sirainen rec = &map->records[idx];
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen old_flags = rec->flags;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen rec->flags = (rec->flags & ~u->remove_flags) | u->add_flags;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen for (i = 0; i < INDEX_KEYWORDS_BYTE_COUNT; i++) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen rec->keywords[i] = u->add_keywords[i] |
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen (rec->keywords[i] & ~u->remove_keywords[i]);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mail_index_header_update_counts(&map->hdr_copy, old_flags,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen rec->flags);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mail_index_header_update_lowwaters(&map->hdr_copy, rec);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return 1;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen}
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenstatic int sync_cache_update(const struct mail_transaction_cache_update *u,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen void *context)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mail_index_map *map = context;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen map->records[u->seq-1].cache_offset = u->cache_offset;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int mail_index_view_sync_map(struct mail_index_view_sync_ctx *ctx)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen static struct mail_transaction_map_functions map_funcs = {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sync_expunge, sync_append, sync_flag_update, sync_cache_update
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen };
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen return mail_transaction_map(ctx->hdr, ctx->data,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen &map_funcs, ctx->sync_map);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenstatic int mail_index_view_sync_next_trans(struct mail_index_view_sync_ctx *ctx,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen uint32_t *seq_r, uoff_t *offset_r)
d16b506f5540e3407d256bda35624b38a5ecf88fTimo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mail_transaction_log_view *log_view = ctx->view->log_view;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mail_index_view *view = ctx->view;
22627da0fb77c1d0d9a8e8bc485ef5540b6f2e69Timo Sirainen int ret, skipped;
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainen ret = mail_transaction_log_view_next(log_view, &ctx->hdr, &ctx->data,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen &skipped);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ret <= 0) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (ret < 0)
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen return -1;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen ctx->last_read = TRUE;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return 1;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (skipped)
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen ctx->skipped = TRUE;
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen mail_transaction_log_view_get_prev_pos(log_view, seq_r, offset_r);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
c44f402f17f9a58ead24ac0083945cae86fb172bTimo Sirainen /* skip flag changes that we committed ourself or have already synced */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (view_is_transaction_synced(view, *seq_r, *offset_r))
c44f402f17f9a58ead24ac0083945cae86fb172bTimo Sirainen return 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ctx->sync_mask != MAIL_INDEX_SYNC_MASK_ALL) {
c44f402f17f9a58ead24ac0083945cae86fb172bTimo Sirainen if (mail_index_view_sync_map(ctx) < 0)
c44f402f17f9a58ead24ac0083945cae86fb172bTimo Sirainen return -1;
c44f402f17f9a58ead24ac0083945cae86fb172bTimo Sirainen }
c44f402f17f9a58ead24ac0083945cae86fb172bTimo Sirainen
c44f402f17f9a58ead24ac0083945cae86fb172bTimo Sirainen return 1;
c44f402f17f9a58ead24ac0083945cae86fb172bTimo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenstatic void
e958a3c4573058f17999f0083a34080ca35e34d8Timo Sirainenmail_index_view_sync_get_rec(struct mail_index_view_sync_ctx *ctx,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen struct mail_index_sync_rec *rec)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
e958a3c4573058f17999f0083a34080ca35e34d8Timo Sirainen const struct mail_transaction_header *hdr = ctx->hdr;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen const void *data = ctx->data;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen case MAIL_TRANSACTION_APPEND: {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_APPEND;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen rec->seq1 = ctx->messages_count + 1;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen ctx->messages_count +=
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen hdr->size / sizeof(struct mail_index_record);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen rec->seq2 = ctx->messages_count;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen rec->appends = NULL;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen ctx->data_offset += hdr->size;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen break;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen case MAIL_TRANSACTION_EXPUNGE: {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen const struct mail_transaction_expunge *exp =
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen CONST_PTR_OFFSET(data, ctx->data_offset);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen ctx->data_offset += sizeof(*exp);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_sync_get_expunge(rec, exp);
a1aaf11831cab8346d6d0dc702e37b3f1d95eb43Timo Sirainen break;
a1aaf11831cab8346d6d0dc702e37b3f1d95eb43Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen case MAIL_TRANSACTION_FLAG_UPDATE: {
a1aaf11831cab8346d6d0dc702e37b3f1d95eb43Timo Sirainen const struct mail_transaction_flag_update *update =
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen CONST_PTR_OFFSET(data, ctx->data_offset);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx->data_offset += sizeof(*update);
c44f402f17f9a58ead24ac0083945cae86fb172bTimo Sirainen mail_index_sync_get_update(rec, update);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen break;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen default:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_unreached();
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenint mail_index_view_sync_next(struct mail_index_view_sync_ctx *ctx,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mail_index_sync_rec *sync_rec)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen struct mail_index_view *view = ctx->view;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t seq;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uoff_t offset;
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen int ret;
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen if (ctx->hdr == NULL || ctx->data_offset == ctx->hdr->size) {
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen ctx->data_offset = 0;
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen do {
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen ret = mail_index_view_sync_next_trans(ctx, &seq,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen &offset);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen if (ret < 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return -1;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ctx->last_read)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (!ctx->skipped) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen view->log_file_seq = seq;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen view->log_file_offset = offset +
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen sizeof(*ctx->hdr) + ctx->hdr->size;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen } while (ret == 0);
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainen
e958a3c4573058f17999f0083a34080ca35e34d8Timo Sirainen if (ctx->skipped) {
e958a3c4573058f17999f0083a34080ca35e34d8Timo Sirainen mail_index_view_add_synced_transaction(view, seq,
e958a3c4573058f17999f0083a34080ca35e34d8Timo Sirainen offset);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen }
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen mail_index_view_sync_get_rec(ctx, sync_rec);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return 1;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen}
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenconst uint32_t *
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenmail_index_view_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen size_t *count_r)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen{
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen const uint32_t *data;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen size_t size;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen data = buffer_get_data(ctx->expunges, &size);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen *count_r = size / (sizeof(uint32_t)*2);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen return data;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen}
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainen
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainenvoid mail_index_view_sync_end(struct mail_index_view_sync_ctx *ctx)
3656c91dcb8336814bebd4500e81c3dde25233e6Timo Sirainen{
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen struct mail_index_view *view = ctx->view;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen i_assert(view->syncing);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (view->log_syncs != NULL && !ctx->skipped)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen buffer_set_used_size(view->log_syncs, 0);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!ctx->last_read && ctx->hdr != NULL &&
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx->data_offset != ctx->hdr->size) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* we didn't sync everything */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen view->inconsistent = TRUE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_unmap(view->index, view->map);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen view->map = ctx->sync_map;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_transaction_log_view_unset(view->log_view);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ctx->expunges != NULL)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen buffer_free(ctx->expunges);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen view->syncing = FALSE;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_free(ctx);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenvoid mail_index_view_add_synced_transaction(struct mail_index_view *view,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen uint32_t log_file_seq,
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen uoff_t log_file_offset)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen{
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (view->log_syncs == NULL) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen view->log_syncs = buffer_create_dynamic(default_pool,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen 128, (size_t)-1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen }
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen buffer_append(view->log_syncs, &log_file_offset,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sizeof(log_file_offset));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen buffer_append(view->log_syncs, &log_file_seq, sizeof(log_file_seq));
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen}
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen