mail-index-view-sync.c revision 7c5b51bdf43a98e12c654ad437e0b258c5fffbc1
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "buffer.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-view-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-sync-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-transaction-log.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-transaction-util.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_index_view_sync_ctx {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_view *view;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_transaction_type trans_sync_mask;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buffer_t *expunges;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_transaction_header *hdr;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const void *data;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen size_t data_offset;
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen unsigned int skipped_some:1;
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen unsigned int last_read:1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int sync_map_update:1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen};
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenview_sync_get_expunges(struct mail_index_view *view, buffer_t **expunges_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_transaction_header *hdr;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_transaction_expunge *src, *src_end, *dest;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const void *data;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen size_t size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *expunges_r = buffer_create_dynamic(default_pool, 512, (size_t)-1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
7888a9d2008eab9985096c46e1da9ee985c22a2aTimo Sirainen /* with mask 0 we don't get anything, we'll just read the expunges
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while seeking to end */
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen if (mail_transaction_log_view_set(view->log_view,
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen view->log_file_seq,
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen view->log_file_offset,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->index->hdr->log_file_seq,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->index->hdr->log_file_offset,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen MAIL_TRANSACTION_EXPUNGE) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &hdr, &data, NULL)) > 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_transaction_log_sort_expunges(*expunges_r,
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen data, hdr->size);
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen }
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen if (ret == 0) {
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen /* convert to sequences */
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen src = dest = buffer_get_modifyable_data(*expunges_r, &size);
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen src_end = src + size / sizeof(*src);
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen for (; src != src_end; src++) {
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen ret = mail_index_lookup_uid_range(view, src->uid1,
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen src->uid2,
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen &dest->uid1,
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen &dest->uid2);
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen i_assert(ret == 0);
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen if (dest->uid1 == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen size -= sizeof(*dest);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen dest++;
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen }
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen buffer_set_used_size(*expunges_r, size);
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen } else {
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen buffer_set_used_size(*expunges_r, 0);
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen }
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen return ret;
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define MAIL_INDEX_VIEW_VISIBLE_SYNC_MASK \
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (MAIL_TRANSACTION_EXPUNGE | MAIL_TRANSACTION_APPEND | \
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen MAIL_TRANSACTION_FLAG_UPDATE)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_index_view_sync_begin(struct mail_index_view *view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_index_sync_type sync_mask,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_view_sync_ctx **ctx_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_index_header *hdr;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_view_sync_ctx *ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_map *map;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_transaction_type mask, want_mask;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buffer_t *expunges = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen /* We must sync flags as long as view is mmap()ed, as the flags may
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen have already changed under us. */
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen i_assert((sync_mask & MAIL_INDEX_SYNC_TYPE_FLAGS) != 0);
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen i_assert(!view->syncing);
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen if (mail_index_view_lock_head(view, TRUE) < 0)
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen return -1;
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen hdr = view->index->hdr;
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0) {
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen /* get list of all expunges first */
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen if (view_sync_get_expunges(view, &expunges) < 0)
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen return -1;
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen }
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen /* only flags, appends and expunges can be left to be synced later */
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen want_mask = mail_transaction_type_mask_get(sync_mask);
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen i_assert((want_mask & ~MAIL_INDEX_VIEW_VISIBLE_SYNC_MASK) == 0);
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen mask = want_mask |
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen (MAIL_TRANSACTION_TYPE_MASK ^
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen MAIL_INDEX_VIEW_VISIBLE_SYNC_MASK);
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen if (mail_transaction_log_view_set(view->log_view,
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen view->log_file_seq,
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainen view->log_file_offset,
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen hdr->log_file_seq,
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainen hdr->log_file_offset, mask) < 0) {
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen if (expunges != NULL)
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen buffer_free(expunges);
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen return -1;
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainen }
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainen
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainen ctx = i_new(struct mail_index_view_sync_ctx, 1);
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainen ctx->view = view;
f75188af11dce30be322cc2eefa3e3884871abf7Timo Sirainen ctx->trans_sync_mask = want_mask;
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainen ctx->expunges = expunges;
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainen if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0) {
ed1f14af0d426b5550521a58fc414d130aa14172Timo Sirainen view->new_map = view->index->map;
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen view->new_map->refcount++;
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen /* keep the old mapping without expunges until we're
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen fully synced */
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen } else {
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen /* we need a private copy of the map if we don't want to
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen sync expunges */
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen if (view->map != view->index->map)
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen ctx->sync_map_update = TRUE;
ed1f14af0d426b5550521a58fc414d130aa14172Timo Sirainen
ed1f14af0d426b5550521a58fc414d130aa14172Timo Sirainen map = mail_index_map_to_memory(view->map,
ed1f14af0d426b5550521a58fc414d130aa14172Timo Sirainen view->map->hdr->record_size);
ed1f14af0d426b5550521a58fc414d130aa14172Timo Sirainen mail_index_unmap(view->index, view->map);
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen view->map = map;
8eeafcb306872435f3171e6acf5a9937aec3a175Timo Sirainen }
8eeafcb306872435f3171e6acf5a9937aec3a175Timo Sirainen
8eeafcb306872435f3171e6acf5a9937aec3a175Timo Sirainen mail_index_view_unref_maps(view);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->syncing = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *ctx_r = ctx;
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainen return 0;
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainen}
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainenstatic int view_is_transaction_synced(struct mail_index_view *view,
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainen uint32_t seq, uoff_t offset)
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainen{
f75188af11dce30be322cc2eefa3e3884871abf7Timo Sirainen const unsigned char *data, *end;
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainen size_t size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainen if (view->log_syncs == NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen data = buffer_get_data(view->log_syncs, &size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen end = data + size;
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen for (; data < end; ) {
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen if (*((const uoff_t *)data) == offset &&
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen *((const uint32_t *)(data + sizeof(uoff_t))) == seq)
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen return 1;
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen data += sizeof(uoff_t) + sizeof(uint32_t);
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen }
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen return 0;
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen}
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainenstatic int mail_index_view_sync_next_trans(struct mail_index_view_sync_ctx *ctx,
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen uint32_t *seq_r, uoff_t *offset_r)
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen{
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen struct mail_transaction_log_view *log_view = ctx->view->log_view;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen struct mail_index_view *view = ctx->view;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen int ret, skipped;
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen ret = mail_transaction_log_view_next(log_view, &ctx->hdr, &ctx->data,
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen &skipped);
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen if (ret <= 0) {
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainen if (ret < 0)
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainen return -1;
8830fab191cab8440281eb641dfdd93974b2933bTimo Sirainen
f75188af11dce30be322cc2eefa3e3884871abf7Timo Sirainen ctx->hdr = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->last_read = TRUE;
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (skipped)
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen ctx->skipped_some = TRUE;
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainen mail_transaction_log_view_get_prev_pos(log_view, seq_r, offset_r);
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainen /* skip flag changes that we committed ourself or have already synced */
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainen if (view_is_transaction_synced(view, *seq_r, *offset_r))
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainen return 0;
f75188af11dce30be322cc2eefa3e3884871abf7Timo Sirainen
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainen /* expunges have to be synced afterwards so that caller can still get
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen information of the messages. otherwise caller most likely wants to
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen see only updated information. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ctx->sync_map_update &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (ctx->hdr->type & MAIL_TRANSACTION_EXPUNGE) == 0) {
527ed64bc924b4a13b570a8450f8be3efdf71879Timo Sirainen struct mail_index_sync_map_ctx sync_map_ctx;
527ed64bc924b4a13b570a8450f8be3efdf71879Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memset(&sync_map_ctx, 0, sizeof(sync_map_ctx));
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen sync_map_ctx.view = view;
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen if (mail_transaction_map(view->index, ctx->hdr, ctx->data,
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen &mail_index_map_sync_funcs,
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen &sync_map_ctx) < 0)
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen return -1;
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen }
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen if ((ctx->hdr->type & ctx->trans_sync_mask) == 0)
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen}
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen#define FLAG_UPDATE_IS_INTERNAL(u, empty) \
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen ((((u)->add_flags | (u)->remove_flags) & \
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen ~(MAIL_INDEX_MAIL_FLAG_DIRTY | MAIL_RECENT)) == 0 && \
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memcmp((u)->add_keywords, empty, INDEX_KEYWORDS_BYTE_COUNT) == 0 && \
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memcmp((u)->add_keywords, empty, INDEX_KEYWORDS_BYTE_COUNT) == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainenstatic int
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainenmail_index_view_sync_get_rec(struct mail_index_view_sync_ctx *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_sync_rec *rec)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen static keywords_mask_t empty_keywords = { 0, };
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_transaction_header *hdr = ctx->hdr;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const void *data = ctx->data;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen case MAIL_TRANSACTION_APPEND: {
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_APPEND;
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen rec->uid1 = rec->uid2 = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->data_offset += hdr->size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case MAIL_TRANSACTION_EXPUNGE: {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_transaction_expunge *exp =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen CONST_PTR_OFFSET(data, ctx->data_offset);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->data_offset += sizeof(*exp);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_sync_get_expunge(rec, exp);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case MAIL_TRANSACTION_FLAG_UPDATE: {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_transaction_flag_update *update =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen CONST_PTR_OFFSET(data, ctx->data_offset);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (;;) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->data_offset += sizeof(*update);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!FLAG_UPDATE_IS_INTERNAL(update, empty_keywords))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ctx->data_offset == ctx->hdr->size)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
c1d45cada20777e1973579d40d0ebe43f89bb053Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_sync_get_update(rec, update);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen default:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_unreached();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_index_view_sync_next(struct mail_index_view_sync_ctx *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_sync_rec *sync_rec)
a8012fea2a7315033bc467acbf46be8e7323318cTimo Sirainen{
a8012fea2a7315033bc467acbf46be8e7323318cTimo Sirainen struct mail_index_view *view = ctx->view;
a8012fea2a7315033bc467acbf46be8e7323318cTimo Sirainen uint32_t seq;
834b90e1f426d1e3308670e09c050bcdea546eb8Timo Sirainen uoff_t offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0add8c99ca65e56dbf613595fc37c41aafff3f7fTimo Sirainen do {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ctx->hdr == NULL || ctx->data_offset == ctx->hdr->size) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->data_offset = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen do {
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen ret = mail_index_view_sync_next_trans(ctx, &seq,
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainen &offset);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret < 0)
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen return -1;
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen if (ctx->last_read)
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen return 0;
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen if (!ctx->skipped_some) {
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen view->log_file_seq = seq;
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen view->log_file_offset = offset +
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen sizeof(*ctx->hdr) +
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen ctx->hdr->size;
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen }
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen } while (ret == 0);
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen if (ctx->skipped_some) {
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen mail_index_view_add_synced_transaction(view,
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen seq,
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen offset);
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen }
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen }
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen } while (!mail_index_view_sync_get_rec(ctx, sync_rec));
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen
d6f50f100ce17fa4b3a89e9567a5ff993b38b872Timo Sirainen return 1;
0add8c99ca65e56dbf613595fc37c41aafff3f7fTimo Sirainen}
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainenconst uint32_t *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_index_view_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen size_t *count_r)
b7cf555b699d73f2d71de0dabc088af6a7be3627Timo Sirainen{
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainen const uint32_t *data;
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainen size_t size;
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainen
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen data = buffer_get_data(ctx->expunges, &size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *count_r = size / (sizeof(uint32_t)*2);
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainen return data;
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainen}
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_view_sync_end(struct mail_index_view_sync_ctx *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_view *view = ctx->view;
6eb30032b4a50c383dea4c9c74342d906de6ad36Timo Sirainen
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen i_assert(view->syncing);
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (view->log_syncs != NULL && !ctx->skipped_some)
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen buffer_set_used_size(view->log_syncs, 0);
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (!ctx->last_read && ctx->hdr != NULL &&
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen ctx->data_offset != ctx->hdr->size) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen /* we didn't sync everything */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen view->inconsistent = TRUE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (view->new_map != NULL) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen mail_index_unmap(view->index, view->map);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen view->map = view->new_map;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen view->new_map = NULL;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen view->map_protected = FALSE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if ((ctx->trans_sync_mask & MAIL_TRANSACTION_APPEND) != 0)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen view->messages_count = view->map->records_count;
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen
1225a5a7ce39f1d5545d5ed3b84ecd4f72438d36Timo Sirainen (void)mail_transaction_log_view_set(view->log_view,
1225a5a7ce39f1d5545d5ed3b84ecd4f72438d36Timo Sirainen view->log_file_seq,
1225a5a7ce39f1d5545d5ed3b84ecd4f72438d36Timo Sirainen view->log_file_offset,
1225a5a7ce39f1d5545d5ed3b84ecd4f72438d36Timo Sirainen view->log_file_seq,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->log_file_offset,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen MAIL_TRANSACTION_TYPE_MASK);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (ctx->expunges != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buffer_free(ctx->expunges);
1225a5a7ce39f1d5545d5ed3b84ecd4f72438d36Timo Sirainen
1225a5a7ce39f1d5545d5ed3b84ecd4f72438d36Timo Sirainen view->syncing = FALSE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen i_free(ctx);
1225a5a7ce39f1d5545d5ed3b84ecd4f72438d36Timo Sirainen}
1225a5a7ce39f1d5545d5ed3b84ecd4f72438d36Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_view_add_synced_transaction(struct mail_index_view *view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t log_file_seq,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uoff_t log_file_offset)
6eb30032b4a50c383dea4c9c74342d906de6ad36Timo Sirainen{
6eb30032b4a50c383dea4c9c74342d906de6ad36Timo Sirainen if (view->log_syncs == NULL) {
1225a5a7ce39f1d5545d5ed3b84ecd4f72438d36Timo Sirainen view->log_syncs = buffer_create_dynamic(default_pool,
1225a5a7ce39f1d5545d5ed3b84ecd4f72438d36Timo Sirainen 128, (size_t)-1);
6eb30032b4a50c383dea4c9c74342d906de6ad36Timo Sirainen }
6eb30032b4a50c383dea4c9c74342d906de6ad36Timo Sirainen buffer_append(view->log_syncs, &log_file_offset,
6eb30032b4a50c383dea4c9c74342d906de6ad36Timo Sirainen sizeof(log_file_offset));
6eb30032b4a50c383dea4c9c74342d906de6ad36Timo Sirainen buffer_append(view->log_syncs, &log_file_seq, sizeof(log_file_seq));
6eb30032b4a50c383dea4c9c74342d906de6ad36Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen