mail-index-view-sync.c revision a050ca9def13949dbaa67bd6574a41c4f397ae26
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen#include "lib.h"
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen#include "array.h"
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen#include "buffer.h"
dd3ccdbb29dad006f7781ea138a5ba39727963c4Timo Sirainen#include "mail-index-view-private.h"
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen#include "mail-index-sync-private.h"
419be6cd72f6e11705576bbba683b29c32eaa762Timo Sirainen#include "mail-transaction-log.h"
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen#include "mail-transaction-util.h"
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen
dd3ccdbb29dad006f7781ea138a5ba39727963c4Timo Sirainenstruct mail_index_view_sync_ctx {
c4390dad33b03dd51ba2a475f550347c86ebdb9aTimo Sirainen struct mail_index_view *view;
dd3ccdbb29dad006f7781ea138a5ba39727963c4Timo Sirainen enum mail_transaction_type visible_sync_mask;
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen struct mail_index_sync_map_ctx sync_map_ctx;
6b6011c2242e470b41316f92512b282b5e306dacTimo Sirainen array_t ARRAY_DEFINE(expunges, struct mail_transaction_expunge);
18458233e89c8467e30d8b93b1823128f26bc174Timo Sirainen
ffaa309c211897ab875bbe0b093bc7e709bb1e5dTimo Sirainen const struct mail_transaction_header *hdr;
a566d9f8797dd66b4d5432a20ab2b9f7c8f76102Timo Sirainen const void *data;
42abccd9b2a5a4190bd3c14ec2dcc10d51c0f491Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen size_t data_offset;
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen unsigned int skipped_some:1;
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen unsigned int last_read:1;
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen unsigned int sync_map_update:1;
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen};
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainenstruct mail_index_view_log_sync_pos {
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen uint32_t log_file_seq;
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen uoff_t log_file_offset;
458acd7b39c84bae0d18c36ff9ddff9a49b4ae4aTimo Sirainen};
78a5b3e697af5db96fe0dffed600b0d6370bb8e5Timo Sirainen
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainenstatic void
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainenmail_transaction_log_sort_expunges(array_t *expunges,
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen const struct mail_transaction_expunge *src,
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen size_t src_size)
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen{
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen ARRAY_SET_TYPE(expunges, struct mail_transaction_expunge);
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen const struct mail_transaction_expunge *src_end;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen struct mail_transaction_expunge *dest;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen struct mail_transaction_expunge new_exp;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen unsigned int first, i, dest_count;
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen
a50f8b9c6196b0f0bb0a7aac3ae9c12b1c42b93bTimo Sirainen i_assert(src_size % sizeof(*src) == 0);
eed0a07ecb946ec9d021f5b413fb33eb36e135fdTimo Sirainen
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen /* @UNSAFE */
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen dest = array_get_modifyable(expunges, &dest_count);
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen if (dest_count == 0) {
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen array_append(expunges, src, src_size / sizeof(*src));
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen return;
89502bb187e8285b2a155559894ca80374ac3ae7Timo Sirainen }
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen src_end = CONST_PTR_OFFSET(src, src_size);
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen for (i = 0; src != src_end; src++) {
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen /* src[] must be sorted. */
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen i_assert(src+1 == src_end || src->uid2 < src[1].uid1);
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen i_assert(src->uid1 <= src->uid2);
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen for (; i < dest_count; i++) {
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen if (src->uid1 < dest[i].uid1)
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen break;
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen }
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen new_exp = *src;
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen first = i;
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen while (i < dest_count && src->uid2 >= dest[i].uid1-1) {
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen /* we can/must merge with next record */
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen if (new_exp.uid2 < dest[i].uid2)
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen new_exp.uid2 = dest[i].uid2;
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen i++;
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen }
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen if (first > 0 && new_exp.uid1 <= dest[first-1].uid2+1) {
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen /* continue previous record */
d65cc3312d3126d34b51ae8eccd6b48215d50029Timo Sirainen if (dest[first-1].uid2 < new_exp.uid2)
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen dest[first-1].uid2 = new_exp.uid2;
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen } else if (i == first) {
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen array_insert(expunges, i, &new_exp, 1);
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen i++; first++;
b015d3d3af5b1c0fd526f31d78229bf9f633db56Timo Sirainen
a566d9f8797dd66b4d5432a20ab2b9f7c8f76102Timo Sirainen dest = array_get_modifyable(expunges, &dest_count);
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen } else {
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen /* use next record */
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen dest[first] = new_exp;
eed03830015b7138b9d4522e72bef650aa24b45fTimo Sirainen first++;
fcd443a32b01c4da131f36649d5a5fa5f8452dcfTimo Sirainen }
fcd443a32b01c4da131f36649d5a5fa5f8452dcfTimo Sirainen
d65cc3312d3126d34b51ae8eccd6b48215d50029Timo Sirainen if (i > first) {
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen array_delete(expunges, first, i - first);
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen dest = array_get_modifyable(expunges, &dest_count);
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen i = first;
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen }
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen }
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen}
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainenstatic int view_sync_set_log_view_range(struct mail_index_view *view,
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen enum mail_transaction_type type_mask)
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen{
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen const struct mail_index_header *hdr = view->index->hdr;
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen int ret;
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen ret = mail_transaction_log_view_set(view->log_view,
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen view->log_file_seq,
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen view->log_file_offset,
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen hdr->log_file_seq,
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen hdr->log_file_int_offset,
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen type_mask);
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen if (ret <= 0) {
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen if (ret == 0) {
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen /* FIXME: use the new index to get needed changes */
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen mail_index_set_error(view->index,
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen "Transaction log got desynced for index %s",
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen view->index->filepath);
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen mail_index_set_inconsistent(view->index);
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen }
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen return -1;
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen }
4fbf59562594dbbbe037f8d4c480dbf88f3fc708Timo Sirainen return 0;
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen}
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainenstatic int
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainenview_sync_get_expunges(struct mail_index_view *view, array_t *expunges_r)
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen{
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen ARRAY_SET_TYPE(expunges_r, struct mail_transaction_expunge);
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen const struct mail_transaction_header *hdr;
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen struct mail_transaction_expunge *src, *src_end, *dest;
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen const void *data;
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen unsigned int count;
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen int ret;
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen if (view_sync_set_log_view_range(view, MAIL_TRANSACTION_EXPUNGE) < 0)
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen return -1;
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen ARRAY_CREATE(expunges_r, default_pool,
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen struct mail_transaction_expunge, 64);
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen &hdr, &data, NULL)) > 0) {
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen i_assert((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0);
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen mail_transaction_log_sort_expunges(expunges_r, data, hdr->size);
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen }
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen if (ret < 0) {
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen array_free(expunges_r);
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen return -1;
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen }
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen /* convert to sequences */
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen src = dest = array_get_modifyable(expunges_r, &count);
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen src_end = src + count;
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen for (; src != src_end; src++) {
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen ret = mail_index_lookup_uid_range(view, src->uid1,
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen src->uid2,
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen &dest->uid1,
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen &dest->uid2);
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen i_assert(ret == 0);
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen if (dest->uid1 == 0)
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen count--;
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen else
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen dest++;
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen }
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen array_delete(expunges_r, count, array_count(expunges_r) - count);
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen return 0;
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen}
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen#define MAIL_INDEX_VIEW_VISIBLE_FLAGS_MASK \
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen (MAIL_INDEX_SYNC_TYPE_FLAGS | \
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET | \
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD | MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE)
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen#define MAIL_TRANSACTION_VISIBLE_SYNC_MASK \
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen (MAIL_TRANSACTION_EXPUNGE | MAIL_TRANSACTION_APPEND | \
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen MAIL_TRANSACTION_FLAG_UPDATE | MAIL_TRANSACTION_KEYWORD_UPDATE | \
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen MAIL_TRANSACTION_KEYWORD_RESET)
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainenint mail_index_view_sync_begin(struct mail_index_view *view,
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen enum mail_index_sync_type sync_mask,
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen struct mail_index_view_sync_ctx **ctx_r)
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen{
6de95f63d4590814354fa5e35e92946c58d4562eTimo Sirainen const struct mail_index_header *hdr;
6de95f63d4590814354fa5e35e92946c58d4562eTimo Sirainen struct mail_index_view_sync_ctx *ctx;
6de95f63d4590814354fa5e35e92946c58d4562eTimo Sirainen struct mail_index_map *map;
6de95f63d4590814354fa5e35e92946c58d4562eTimo Sirainen enum mail_transaction_type log_get_mask, visible_mask;
6de95f63d4590814354fa5e35e92946c58d4562eTimo Sirainen array_t expunges = { 0, 0 };
6de95f63d4590814354fa5e35e92946c58d4562eTimo Sirainen
6de95f63d4590814354fa5e35e92946c58d4562eTimo Sirainen /* We must sync flags as long as view is mmap()ed, as the flags may
6de95f63d4590814354fa5e35e92946c58d4562eTimo Sirainen have already changed under us. */
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen i_assert((sync_mask & MAIL_INDEX_VIEW_VISIBLE_FLAGS_MASK) ==
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen MAIL_INDEX_VIEW_VISIBLE_FLAGS_MASK);
65514ab6ccc1889e1667211fddb0cca4b51017dfTimo Sirainen /* Currently we're not handling correctly expunges + no-appends case */
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen i_assert((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) == 0 ||
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen (sync_mask & MAIL_INDEX_SYNC_TYPE_APPEND) != 0);
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen i_assert(!view->syncing);
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen i_assert(view->transactions == 0);
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen if (mail_index_view_lock_head(view, TRUE) < 0)
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen return -1;
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen hdr = view->index->hdr;
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0) {
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen /* get list of all expunges first */
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen if (view_sync_get_expunges(view, &expunges) < 0)
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen return -1;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen }
e93ab1b206e3792a8dabc460ad2ee60aaf6830b1Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen /* only flags, appends and expunges can be left to be synced later */
e93ab1b206e3792a8dabc460ad2ee60aaf6830b1Timo Sirainen visible_mask = mail_transaction_type_mask_get(sync_mask);
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen i_assert((visible_mask & ~MAIL_TRANSACTION_VISIBLE_SYNC_MASK) == 0);
65514ab6ccc1889e1667211fddb0cca4b51017dfTimo Sirainen
65514ab6ccc1889e1667211fddb0cca4b51017dfTimo Sirainen /* we want to also get non-visible changes. especially because we use
65514ab6ccc1889e1667211fddb0cca4b51017dfTimo Sirainen the returned skipped-flag in mail_transaction_log_view_next() to
65514ab6ccc1889e1667211fddb0cca4b51017dfTimo Sirainen tell us if any visible changes were skipped. */
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen log_get_mask = visible_mask | (MAIL_TRANSACTION_TYPE_MASK ^
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen MAIL_TRANSACTION_VISIBLE_SYNC_MASK);
e5b06a21b5f857d7037fd6ff41ba3bd449d1232aTimo Sirainen if (view_sync_set_log_view_range(view, log_get_mask) < 0) {
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen if (array_is_created(&expunges))
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen array_free(&expunges);
d65cc3312d3126d34b51ae8eccd6b48215d50029Timo Sirainen return -1;
6b6011c2242e470b41316f92512b282b5e306dacTimo Sirainen }
6de95f63d4590814354fa5e35e92946c58d4562eTimo Sirainen
6de95f63d4590814354fa5e35e92946c58d4562eTimo Sirainen ctx = i_new(struct mail_index_view_sync_ctx, 1);
6de95f63d4590814354fa5e35e92946c58d4562eTimo Sirainen ctx->view = view;
6de95f63d4590814354fa5e35e92946c58d4562eTimo Sirainen ctx->visible_sync_mask = visible_mask;
6de95f63d4590814354fa5e35e92946c58d4562eTimo Sirainen ctx->expunges = expunges;
6b6011c2242e470b41316f92512b282b5e306dacTimo Sirainen mail_index_sync_map_init(&ctx->sync_map_ctx, view,
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen MAIL_INDEX_SYNC_HANDLER_VIEW);
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen
315ce5be539bfe8bc7777ab0654499c49583cea2Timo Sirainen if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0 &&
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen (sync_mask & MAIL_INDEX_SYNC_TYPE_APPEND) != 0) {
3322dfd56c9cae5015a33bab4c80124c08c3d9caTimo Sirainen view->sync_new_map = view->index->map;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen view->sync_new_map->refcount++;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen /* keep the old mapping without expunges until we're
eed0a07ecb946ec9d021f5b413fb33eb36e135fdTimo Sirainen fully synced */
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen } else {
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen /* We need a private copy of the map if we don't want to
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen sync expunges.
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen If view's map is the head map, it means that it contains
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen already all the latest changes and there's no need for us
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen to apply any changes to it. This can only happen if there
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen hadn't been any expunges. */
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen uint32_t old_records_count = view->map->records_count;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen if (view->map != view->index->map) {
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen /* Using non-head mapping. We have to apply
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen transactions to it to get latest changes into it. */
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen ctx->sync_map_update = TRUE;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen
eed0a07ecb946ec9d021f5b413fb33eb36e135fdTimo Sirainen /* Copy only the mails that we see currently, since
009217abb57a24a4076092e8e4e165545747839eStephan Bosch we're going to append the new ones when we see
009217abb57a24a4076092e8e4e165545747839eStephan Bosch their transactions. */
009217abb57a24a4076092e8e4e165545747839eStephan Bosch i_assert(view->map->records_count >=
009217abb57a24a4076092e8e4e165545747839eStephan Bosch view->hdr.messages_count);
eed0a07ecb946ec9d021f5b413fb33eb36e135fdTimo Sirainen view->map->records_count = view->hdr.messages_count;
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch }
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch map = mail_index_map_clone(view->map,
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch view->map->hdr.record_size);
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch view->map->records_count = old_records_count;
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch mail_index_unmap(view->index, view->map);
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch view->map = map;
eed0a07ecb946ec9d021f5b413fb33eb36e135fdTimo Sirainen
eed0a07ecb946ec9d021f5b413fb33eb36e135fdTimo Sirainen if (ctx->sync_map_update) {
eed0a07ecb946ec9d021f5b413fb33eb36e135fdTimo Sirainen /* Start the sync using our old view's header.
eed0a07ecb946ec9d021f5b413fb33eb36e135fdTimo Sirainen The old view->hdr may differ from map->hdr if
eed0a07ecb946ec9d021f5b413fb33eb36e135fdTimo Sirainen another view sharing the map with us had synced
eed0a07ecb946ec9d021f5b413fb33eb36e135fdTimo Sirainen itself. */
eed0a07ecb946ec9d021f5b413fb33eb36e135fdTimo Sirainen i_assert(map->hdr_base == map->hdr_copy_buf->data);
eed0a07ecb946ec9d021f5b413fb33eb36e135fdTimo Sirainen buffer_write(map->hdr_copy_buf, 0,
eed0a07ecb946ec9d021f5b413fb33eb36e135fdTimo Sirainen &view->hdr, sizeof(view->hdr));
eed0a07ecb946ec9d021f5b413fb33eb36e135fdTimo Sirainen map->hdr = view->hdr;
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen }
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen i_assert(map->records_count == map->hdr.messages_count);
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen }
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen /* Syncing the view invalidates all previous looked up records.
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen Unreference the mappings this view keeps because of them. */
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen mail_index_view_unref_maps(view);
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen view->syncing = TRUE;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen *ctx_r = ctx;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen return 0;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen}
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainenstatic int view_is_transaction_synced(struct mail_index_view *view,
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen uint32_t seq, uoff_t offset)
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen{
3322dfd56c9cae5015a33bab4c80124c08c3d9caTimo Sirainen const struct mail_index_view_log_sync_pos *pos;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen unsigned int i, count;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen if (!array_is_created(&view->log_syncs))
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen return FALSE;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen pos = array_get(&view->log_syncs, &count);
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen for (i = 0; i < count; i++) {
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen if (pos[i].log_file_offset == offset &&
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen pos[i].log_file_seq == seq)
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen return TRUE;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen }
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen return FALSE;
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen}
972c9172e9e6a0fc6053efb3d2ee9d354b67727fLennart Weller
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainenstatic int
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainenmail_index_view_sync_get_next_transaction(struct mail_index_view_sync_ctx *ctx)
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen{
972c9172e9e6a0fc6053efb3d2ee9d354b67727fLennart Weller struct mail_transaction_log_view *log_view = ctx->view->log_view;
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen struct mail_index_view *view = ctx->view;
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen uint32_t seq;
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen uoff_t offset;
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen int ret, skipped;
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen for (;;) {
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen /* Get the next transaction from log. */
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen ret = mail_transaction_log_view_next(log_view, &ctx->hdr,
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen &ctx->data, &skipped);
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen if (ret <= 0) {
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen if (ret < 0)
972c9172e9e6a0fc6053efb3d2ee9d354b67727fLennart Weller return -1;
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen ctx->hdr = NULL;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen ctx->last_read = TRUE;
3322dfd56c9cae5015a33bab4c80124c08c3d9caTimo Sirainen return 0;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen }
86fafb22c02f4b85a9d59f2b60059a48286286fbTimo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen mail_transaction_log_view_get_prev_pos(log_view, &seq, &offset);
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen if (skipped) {
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen /* We skipped some (visible) transactions that were
86fafb22c02f4b85a9d59f2b60059a48286286fbTimo Sirainen outside our sync mask. */
86fafb22c02f4b85a9d59f2b60059a48286286fbTimo Sirainen ctx->skipped_some = TRUE;
86fafb22c02f4b85a9d59f2b60059a48286286fbTimo Sirainen } else if (!ctx->skipped_some) {
86fafb22c02f4b85a9d59f2b60059a48286286fbTimo Sirainen /* We haven't skipped anything while syncing this view.
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen Update this view's synced log offset. */
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen view->log_file_seq = seq;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen view->log_file_offset = offset + sizeof(*ctx->hdr) +
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen ctx->hdr->size;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen }
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen /* skip flag changes that we committed ourself or have
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen already synced */
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (view_is_transaction_synced(view, seq, offset))
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen continue;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen /* Apply transaction to view's mapping if needed (meaning we
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen didn't just re-map the view to head mapping). */
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen if (ctx->sync_map_update) {
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen i_assert((ctx->hdr->type &
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen MAIL_TRANSACTION_EXPUNGE) == 0);
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen if (mail_index_sync_record(&ctx->sync_map_ctx,
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen ctx->hdr, ctx->data) < 0)
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen return -1;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen }
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen if ((ctx->hdr->type & ctx->visible_sync_mask) == 0) {
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen /* non-visible change that we just wanted to update
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen to map. */
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen continue;
eed0a07ecb946ec9d021f5b413fb33eb36e135fdTimo Sirainen }
eed0a07ecb946ec9d021f5b413fb33eb36e135fdTimo Sirainen break;
38f624b427aa8b6fad3765e6efd97c85a7f97a09Timo Sirainen }
eed0a07ecb946ec9d021f5b413fb33eb36e135fdTimo Sirainen
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen if (ctx->skipped_some) {
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen /* We've been skipping some transactions, which means we'll
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen go through these same transaction again later. Since we're
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen syncing this one, we don't want to do it again. */
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen mail_index_view_add_synced_transaction(view, seq, offset);
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen }
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen return 1;
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen}
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen#define FLAG_UPDATE_IS_INTERNAL(u) \
972c9172e9e6a0fc6053efb3d2ee9d354b67727fLennart Weller ((((u)->add_flags | (u)->remove_flags) & \
d2a2e0b6d302c17c33638a6fd48bd665a1c81e46Timo Sirainen ~(MAIL_INDEX_MAIL_FLAG_DIRTY | MAIL_RECENT)) == 0)
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainenstatic int
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainenmail_index_view_sync_get_rec(struct mail_index_view_sync_ctx *ctx,
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen struct mail_index_view_sync_rec *rec)
7aa2dd189748ed57c2fb8d8d9b7cb3c4ac2f7ea5Timo Sirainen{
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen const struct mail_transaction_header *hdr = ctx->hdr;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen const void *data = ctx->data;
9508ac436fff0e1dcea975855c139cd251deb703Timo Sirainen
ddbdc644a15f56f4b43596f1b8c0fc196c101445Timo Sirainen switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
ddbdc644a15f56f4b43596f1b8c0fc196c101445Timo Sirainen case MAIL_TRANSACTION_APPEND: {
ddbdc644a15f56f4b43596f1b8c0fc196c101445Timo Sirainen /* data contains the appended records, but we don't care */
ddbdc644a15f56f4b43596f1b8c0fc196c101445Timo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_APPEND;
ddbdc644a15f56f4b43596f1b8c0fc196c101445Timo Sirainen rec->uid1 = rec->uid2 = 0;
ddbdc644a15f56f4b43596f1b8c0fc196c101445Timo Sirainen ctx->data_offset += hdr->size;
ddbdc644a15f56f4b43596f1b8c0fc196c101445Timo Sirainen break;
ddbdc644a15f56f4b43596f1b8c0fc196c101445Timo Sirainen }
7aa2dd189748ed57c2fb8d8d9b7cb3c4ac2f7ea5Timo Sirainen case MAIL_TRANSACTION_EXPUNGE: {
7aa2dd189748ed57c2fb8d8d9b7cb3c4ac2f7ea5Timo Sirainen const struct mail_transaction_expunge *exp =
7aa2dd189748ed57c2fb8d8d9b7cb3c4ac2f7ea5Timo Sirainen CONST_PTR_OFFSET(data, ctx->data_offset);
7aa2dd189748ed57c2fb8d8d9b7cb3c4ac2f7ea5Timo Sirainen
7aa2dd189748ed57c2fb8d8d9b7cb3c4ac2f7ea5Timo Sirainen /* data contains mail_transaction_expunge[] */
7aa2dd189748ed57c2fb8d8d9b7cb3c4ac2f7ea5Timo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_EXPUNGE;
7aa2dd189748ed57c2fb8d8d9b7cb3c4ac2f7ea5Timo Sirainen rec->uid1 = exp->uid1;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen rec->uid2 = exp->uid2;
3322dfd56c9cae5015a33bab4c80124c08c3d9caTimo Sirainen
3322dfd56c9cae5015a33bab4c80124c08c3d9caTimo Sirainen ctx->data_offset += sizeof(*exp);
3322dfd56c9cae5015a33bab4c80124c08c3d9caTimo Sirainen break;
32efae185f1f86167b3f00ea84f8502940c6c677Timo Sirainen }
3322dfd56c9cae5015a33bab4c80124c08c3d9caTimo Sirainen case MAIL_TRANSACTION_FLAG_UPDATE: {
d163fac99c7ca5b2ce2edfa83a1b2922cf66aeacTimo Sirainen const struct mail_transaction_flag_update *update =
3322dfd56c9cae5015a33bab4c80124c08c3d9caTimo Sirainen CONST_PTR_OFFSET(data, ctx->data_offset);
3322dfd56c9cae5015a33bab4c80124c08c3d9caTimo Sirainen
ddbdc644a15f56f4b43596f1b8c0fc196c101445Timo Sirainen /* data contains mail_transaction_flag_update[] */
3322dfd56c9cae5015a33bab4c80124c08c3d9caTimo Sirainen for (;;) {
3322dfd56c9cae5015a33bab4c80124c08c3d9caTimo Sirainen ctx->data_offset += sizeof(*update);
e93ab1b206e3792a8dabc460ad2ee60aaf6830b1Timo Sirainen if (!FLAG_UPDATE_IS_INTERNAL(update))
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen break;
e93ab1b206e3792a8dabc460ad2ee60aaf6830b1Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen /* skip internal flag changes */
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen if (ctx->data_offset == ctx->hdr->size)
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen return 0;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen update = CONST_PTR_OFFSET(data, ctx->data_offset);
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen }
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_FLAGS;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen rec->uid1 = update->uid1;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen rec->uid2 = update->uid2;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen break;
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen }
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen case MAIL_TRANSACTION_KEYWORD_UPDATE: {
c2ebc8f28b5504f280cd5d4adfe57ed70f9a7d83Timo Sirainen const struct mail_transaction_keyword_update *update = data;
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen const uint32_t *uids;
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen /* data contains mail_transaction_keyword_update header,
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen the keyword name and an array of { uint32_t uid1, uid2; } */
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen if (ctx->data_offset == 0) {
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen /* skip over the header and name */
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen ctx->data_offset = sizeof(*update) + update->name_size;
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen if ((ctx->data_offset % 4) != 0)
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen ctx->data_offset += 4 - (ctx->data_offset % 4);
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen }
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen uids = CONST_PTR_OFFSET(data, ctx->data_offset);
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD;
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen rec->uid1 = uids[0];
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen rec->uid2 = uids[1];
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen ctx->data_offset += sizeof(uint32_t) * 2;
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen break;
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen }
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen case MAIL_TRANSACTION_KEYWORD_RESET: {
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen const struct mail_transaction_keyword_reset *reset =
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen CONST_PTR_OFFSET(data, ctx->data_offset);
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen /* data contains mail_transaction_keyword_reset[] */
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET;
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen rec->uid1 = reset->uid1;
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen rec->uid2 = reset->uid2;
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen ctx->data_offset += sizeof(*reset);
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen break;
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen }
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen default:
a338794c56fc9674121e262fcb67c3dc1da31436Timo Sirainen i_unreached();
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen }
972c9172e9e6a0fc6053efb3d2ee9d354b67727fLennart Weller return 1;
972c9172e9e6a0fc6053efb3d2ee9d354b67727fLennart Weller}
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen
7b22071c71a99bcb71ee9fcfbb83ed5bf5e08a2dTimo Sirainenint mail_index_view_sync_next(struct mail_index_view_sync_ctx *ctx,
972c9172e9e6a0fc6053efb3d2ee9d354b67727fLennart Weller struct mail_index_view_sync_rec *sync_rec)
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen{
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen int ret;
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen do {
32efae185f1f86167b3f00ea84f8502940c6c677Timo Sirainen if (ctx->hdr == NULL || ctx->data_offset == ctx->hdr->size) {
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen ret = mail_index_view_sync_get_next_transaction(ctx);
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen if (ret <= 0)
7b22071c71a99bcb71ee9fcfbb83ed5bf5e08a2dTimo Sirainen return ret;
972c9172e9e6a0fc6053efb3d2ee9d354b67727fLennart Weller
972c9172e9e6a0fc6053efb3d2ee9d354b67727fLennart Weller ctx->data_offset = 0;
972c9172e9e6a0fc6053efb3d2ee9d354b67727fLennart Weller }
972c9172e9e6a0fc6053efb3d2ee9d354b67727fLennart Weller } while (!mail_index_view_sync_get_rec(ctx, sync_rec));
7b22071c71a99bcb71ee9fcfbb83ed5bf5e08a2dTimo Sirainen
972c9172e9e6a0fc6053efb3d2ee9d354b67727fLennart Weller return 1;
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen}
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen
7b22071c71a99bcb71ee9fcfbb83ed5bf5e08a2dTimo Sirainenconst uint32_t *
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainenmail_index_view_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen unsigned int *count_r)
7b22071c71a99bcb71ee9fcfbb83ed5bf5e08a2dTimo Sirainen{
7b22071c71a99bcb71ee9fcfbb83ed5bf5e08a2dTimo Sirainen const struct mail_transaction_expunge *data;
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen data = array_get(&ctx->expunges, count_r);
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen return (const uint32_t *)data;
9a935c34e98ba7a9cc90784ceb63b2fbdab4105fTimo Sirainen}
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainenstatic void
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainenmail_index_view_sync_clean_log_syncs(struct mail_index_view_sync_ctx *ctx)
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen{
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen struct mail_index_view *view = ctx->view;
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen const struct mail_index_view_log_sync_pos *pos;
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen unsigned int i, count;
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen if (!array_is_created(&view->log_syncs))
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen return;
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen if (!ctx->skipped_some) {
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen /* Nothing skipped. Clean it up the quick way. */
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen array_clear(&view->log_syncs);
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen return;
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen }
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen /* Clean up until view's current syncing position */
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen pos = array_get(&view->log_syncs, &count);
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen for (i = 0; i < count; i++) {
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen if ((pos[i].log_file_offset >= view->log_file_offset &&
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen pos[i].log_file_seq == view->log_file_seq) ||
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen pos[i].log_file_seq > view->log_file_seq)
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen break;
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen }
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen if (i > 0)
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen array_delete(&view->log_syncs, 0, i);
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen}
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainenvoid mail_index_view_sync_end(struct mail_index_view_sync_ctx *ctx)
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen{
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen struct mail_index_view *view = ctx->view;
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen i_assert(view->syncing);
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen if (ctx->sync_map_update)
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen mail_index_sync_map_deinit(&ctx->sync_map_ctx);
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen mail_index_view_sync_clean_log_syncs(ctx);
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen if (!ctx->last_read && ctx->hdr != NULL &&
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen ctx->data_offset != ctx->hdr->size) {
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen /* we didn't sync everything */
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen view->inconsistent = TRUE;
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen }
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen if (view->sync_new_map != NULL) {
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen mail_index_unmap(view->index, view->map);
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen view->map = view->sync_new_map;
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen view->sync_new_map = NULL;
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen }
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen view->hdr = view->map->hdr;
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen /* set log view to empty range so unneeded memory gets freed */
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen (void)mail_transaction_log_view_set(view->log_view,
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen view->log_file_seq,
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen view->log_file_offset,
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen view->log_file_seq,
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen view->log_file_offset,
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen MAIL_TRANSACTION_TYPE_MASK);
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen if (array_is_created(&ctx->expunges))
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen array_free(&ctx->expunges);
e7b1f9db0128384b152b58ea65303d66484c9d7bTimo Sirainen
170834eda87ac8e6b8b6577738ef373fc68f117dTimo Sirainen view->syncing = FALSE;
170834eda87ac8e6b8b6577738ef373fc68f117dTimo Sirainen i_free(ctx);
170834eda87ac8e6b8b6577738ef373fc68f117dTimo Sirainen}
170834eda87ac8e6b8b6577738ef373fc68f117dTimo Sirainen
170834eda87ac8e6b8b6577738ef373fc68f117dTimo Sirainenvoid mail_index_view_add_synced_transaction(struct mail_index_view *view,
170834eda87ac8e6b8b6577738ef373fc68f117dTimo Sirainen uint32_t log_file_seq,
170834eda87ac8e6b8b6577738ef373fc68f117dTimo Sirainen uoff_t log_file_offset)
170834eda87ac8e6b8b6577738ef373fc68f117dTimo Sirainen{
170834eda87ac8e6b8b6577738ef373fc68f117dTimo Sirainen struct mail_index_view_log_sync_pos *pos;
170834eda87ac8e6b8b6577738ef373fc68f117dTimo Sirainen
170834eda87ac8e6b8b6577738ef373fc68f117dTimo Sirainen if (!array_is_created(&view->log_syncs)) {
02e8b5f55210f413853998a0ba5832eb3f9a6dc6Timo Sirainen ARRAY_CREATE(&view->log_syncs, default_pool,
02e8b5f55210f413853998a0ba5832eb3f9a6dc6Timo Sirainen struct mail_index_view_log_sync_pos, 32);
02e8b5f55210f413853998a0ba5832eb3f9a6dc6Timo Sirainen }
02e8b5f55210f413853998a0ba5832eb3f9a6dc6Timo Sirainen
02e8b5f55210f413853998a0ba5832eb3f9a6dc6Timo Sirainen pos = array_append_space(&view->log_syncs);
02e8b5f55210f413853998a0ba5832eb3f9a6dc6Timo Sirainen pos->log_file_seq = log_file_seq;
02e8b5f55210f413853998a0ba5832eb3f9a6dc6Timo Sirainen pos->log_file_offset = log_file_offset;
02e8b5f55210f413853998a0ba5832eb3f9a6dc6Timo Sirainen}
02e8b5f55210f413853998a0ba5832eb3f9a6dc6Timo Sirainen