mail-index-view-sync.c revision 26a8b7deb3a5b6f26f9c4d71538e1248f680e4be
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "array.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;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen enum mail_transaction_type visible_sync_mask;
56561d472db25ebda35ae6afdc7f7deb75c323fcTimo Sirainen struct mail_index_sync_map_ctx sync_map_ctx;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ARRAY_TYPE(uid_range) expunges;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_transaction_header *hdr;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const void *data;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen size_t data_offset;
bcf5af3335a814e4923ba1bf2e0d80eb6dabfb22Timo Sirainen unsigned int skipped_some:1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int last_read:1;
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen unsigned int sync_map_update:1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen};
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainenstatic void
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainenmail_transaction_log_sort_expunges(ARRAY_TYPE(uid_range) *expunges,
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen const struct uid_range *src, size_t src_size)
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen{
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen const struct uid_range *src_end;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen struct uid_range *dest, new_exp;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen unsigned int first, i, dest_count;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen i_assert(src_size % sizeof(*src) == 0);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* @UNSAFE */
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen dest = array_get_modifiable(expunges, &dest_count);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (dest_count == 0) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen array_append(expunges, src, src_size / sizeof(*src));
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen return;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen }
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen src_end = CONST_PTR_OFFSET(src, src_size);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen for (i = 0; src != src_end; src++) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* src[] must be sorted. */
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen i_assert(src+1 == src_end || src->uid2 < src[1].uid1);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen i_assert(src->uid1 <= src->uid2);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen for (; i < dest_count; i++) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (src->uid1 < dest[i].uid1)
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen break;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen }
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen new_exp = *src;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen first = i;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen while (i < dest_count && src->uid2 >= dest[i].uid1-1) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* we can/must merge with next record */
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (new_exp.uid2 < dest[i].uid2)
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen new_exp.uid2 = dest[i].uid2;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen i++;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen }
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (first > 0 && new_exp.uid1 <= dest[first-1].uid2+1) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* continue previous record */
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (dest[first-1].uid2 < new_exp.uid2)
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen dest[first-1].uid2 = new_exp.uid2;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen } else if (i == first) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen array_insert(expunges, i, &new_exp, 1);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen i++; first++;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen dest = array_get_modifiable(expunges, &dest_count);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen } else {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen /* use next record */
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen dest[first] = new_exp;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen first++;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen }
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (i > first) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen array_delete(expunges, first, i - first);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen dest = array_get_modifiable(expunges, &dest_count);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen i = first;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen }
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen }
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen}
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainenstatic int view_sync_set_log_view_range(struct mail_index_view *view,
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen enum mail_transaction_type type_mask)
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen{
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen const struct mail_index_header *hdr = view->index->hdr;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen int ret;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen ret = mail_transaction_log_view_set(view->log_view,
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen view->log_file_seq,
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen view->log_file_offset,
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen hdr->log_file_seq,
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen hdr->log_file_int_offset,
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen type_mask);
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen if (ret <= 0) {
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen if (ret == 0) {
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen /* FIXME: use the new index to get needed changes */
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen mail_index_set_error(view->index,
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen "Transaction log got desynced for index %s",
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen view->index->filepath);
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen mail_index_set_inconsistent(view->index);
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen }
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen return -1;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen }
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen return 0;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen}
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainenview_sync_get_expunges(struct mail_index_view *view,
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ARRAY_TYPE(uid_range) *expunges_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
659fe5d24825b160cae512538088020d97a60239Timo Sirainen const struct mail_transaction_header *hdr;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen struct uid_range *src, *src_end, *dest;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen const void *data;
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen unsigned int count;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen int ret;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen if (view_sync_set_log_view_range(view, MAIL_TRANSACTION_EXPUNGE) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen
26a8b7deb3a5b6f26f9c4d71538e1248f680e4beTimo Sirainen ARRAY_CREATE(expunges_r, default_pool, 64);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
659fe5d24825b160cae512538088020d97a60239Timo Sirainen &hdr, &data, NULL)) > 0) {
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen i_assert((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen mail_transaction_log_sort_expunges(expunges_r, data, hdr->size);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen if (ret < 0) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen array_free(expunges_r);
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen /* convert to sequences */
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen src = dest = array_get_modifiable(expunges_r, &count);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen src_end = src + count;
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen for (; src != src_end; src++) {
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen ret = mail_index_lookup_uid_range(view, src->uid1,
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen src->uid2,
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen &dest->uid1,
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen &dest->uid2);
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen i_assert(ret == 0);
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen if (dest->uid1 == 0)
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen count--;
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen else
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen dest++;
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen }
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen array_delete(expunges_r, count, array_count(expunges_r) - count);
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainenstatic void mail_index_view_hdr_update(struct mail_index_view *view,
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen struct mail_index_map *map)
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen{
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen /* Keep message count the same. */
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen map->hdr.next_uid = view->hdr.next_uid;
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen map->hdr.messages_count = view->hdr.messages_count;
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen /* Keep the old message flag counts also, although they may be
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen somewhat stale already. We just don't want them to be more than
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen our old messages_count. */
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen map->hdr.recent_messages_count = view->hdr.recent_messages_count;
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen map->hdr.seen_messages_count = view->hdr.seen_messages_count;
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen map->hdr.deleted_messages_count = view->hdr.deleted_messages_count;
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen /* Keep log position so we know where to continue syncing */
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen map->hdr.log_file_seq = view->hdr.log_file_seq;
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen map->hdr.log_file_int_offset = view->hdr.log_file_int_offset;
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen map->hdr.log_file_ext_offset = view->hdr.log_file_ext_offset;
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen view->hdr = map->hdr;
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen buffer_write(map->hdr_copy_buf, 0, &map->hdr, sizeof(map->hdr));
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen}
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen#define MAIL_INDEX_VIEW_VISIBLE_FLAGS_MASK \
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen (MAIL_INDEX_SYNC_TYPE_FLAGS | \
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET | \
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD | MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE)
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen#define MAIL_TRANSACTION_VISIBLE_SYNC_MASK \
d6f50f100ce17fa4b3a89e9567a5ff993b38b872Timo Sirainen (MAIL_TRANSACTION_EXPUNGE | MAIL_TRANSACTION_APPEND | \
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen MAIL_TRANSACTION_FLAG_UPDATE | MAIL_TRANSACTION_KEYWORD_UPDATE | \
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen MAIL_TRANSACTION_KEYWORD_RESET)
d6f50f100ce17fa4b3a89e9567a5ff993b38b872Timo 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;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct mail_index_map *map;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen enum mail_transaction_type log_get_mask, visible_mask;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ARRAY_TYPE(uid_range) expunges = ARRAY_INIT;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* We must sync flags as long as view is mmap()ed, as the flags may
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen have already changed under us. */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen i_assert((sync_mask & MAIL_INDEX_VIEW_VISIBLE_FLAGS_MASK) ==
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen MAIL_INDEX_VIEW_VISIBLE_FLAGS_MASK);
18634dae6e304bac982bb1e0ff1b6b88fc448dbcTimo Sirainen /* Currently we're not handling correctly expunges + no-appends case */
18634dae6e304bac982bb1e0ff1b6b88fc448dbcTimo Sirainen i_assert((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) == 0 ||
18634dae6e304bac982bb1e0ff1b6b88fc448dbcTimo Sirainen (sync_mask & MAIL_INDEX_SYNC_TYPE_APPEND) != 0);
18634dae6e304bac982bb1e0ff1b6b88fc448dbcTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(!view->syncing);
d39c0e195c67be5f2b0a15f25a8d6039bef02711Timo Sirainen i_assert(view->transactions == 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen if (mail_index_view_lock_head(view, TRUE) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen hdr = view->index->hdr;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* get list of all expunges first */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (view_sync_get_expunges(view, &expunges) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
bcf5af3335a814e4923ba1bf2e0d80eb6dabfb22Timo Sirainen /* only flags, appends and expunges can be left to be synced later */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen visible_mask = mail_transaction_type_mask_get(sync_mask);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen i_assert((visible_mask & ~MAIL_TRANSACTION_VISIBLE_SYNC_MASK) == 0);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* we want to also get non-visible changes. especially because we use
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen the returned skipped-flag in mail_transaction_log_view_next() to
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen tell us if any visible changes were skipped. */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen log_get_mask = visible_mask | (MAIL_TRANSACTION_TYPE_MASK ^
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen MAIL_TRANSACTION_VISIBLE_SYNC_MASK);
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen if (view_sync_set_log_view_range(view, log_get_mask) < 0) {
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (array_is_created(&expunges))
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen array_free(&expunges);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx = i_new(struct mail_index_view_sync_ctx, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->view = view;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen ctx->visible_sync_mask = visible_mask;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->expunges = expunges;
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen mail_index_sync_map_init(&ctx->sync_map_ctx, view,
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen MAIL_INDEX_SYNC_HANDLER_VIEW);
56561d472db25ebda35ae6afdc7f7deb75c323fcTimo Sirainen
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0 &&
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen (sync_mask & MAIL_INDEX_SYNC_TYPE_APPEND) != 0) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen view->sync_new_map = view->index->map;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen view->sync_new_map->refcount++;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen /* since we're syncing everything, the counters get fixed */
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen view->broken_counters = FALSE;
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen /* keep the old mapping without expunges until we're
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen fully synced */
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen } else {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* We need a private copy of the map if we don't want to
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen sync expunges.
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen If view's map is the head map, it means that it contains
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen already all the latest changes and there's no need for us
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen to apply any changes to it. This can only happen if there
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen hadn't been any expunges. */
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen uint32_t old_records_count = view->map->records_count;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (view->map != view->index->map) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* Using non-head mapping. We have to apply
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen transactions to it to get latest changes into it. */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen ctx->sync_map_update = TRUE;
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen /* Unless map was synced at the exact same position as
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen view, the message flags can't be reliably used to
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen update flag counters. */
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen ctx->sync_map_ctx.unreliable_flags =
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen !(view->map->hdr.log_file_seq ==
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen view->log_file_seq &&
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen view->map->hdr.log_file_int_offset ==
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen view->log_file_offset);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* Copy only the mails that we see currently, since
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen we're going to append the new ones when we see
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen their transactions. */
d7095f3a4466fbb78b2d5eb3d322bc15a5b0ab1fTimo Sirainen i_assert(view->map->records_count >=
d7095f3a4466fbb78b2d5eb3d322bc15a5b0ab1fTimo Sirainen view->hdr.messages_count);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen view->map->records_count = view->hdr.messages_count;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
d7095f3a4466fbb78b2d5eb3d322bc15a5b0ab1fTimo Sirainen map = mail_index_map_clone(view->map,
d7095f3a4466fbb78b2d5eb3d322bc15a5b0ab1fTimo Sirainen view->map->hdr.record_size);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen view->map->records_count = old_records_count;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mail_index_unmap(view->index, &view->map);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen view->map = map;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (ctx->sync_map_update) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* Start the sync using our old view's header.
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen The old view->hdr may differ from map->hdr if
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen another view sharing the map with us had synced
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen itself. */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen i_assert(map->hdr_base == map->hdr_copy_buf->data);
c75721032dbe34369b94ad02444c89111d6686d4Timo Sirainen mail_index_view_hdr_update(view, map);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen }
20c26f4fcf9ef87434761829cc209c2f84ff5716Timo Sirainen
20c26f4fcf9ef87434761829cc209c2f84ff5716Timo Sirainen i_assert(map->records_count == map->hdr.messages_count);
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen }
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* Syncing the view invalidates all previous looked up records.
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen Unreference the mappings this view keeps because of them. */
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen mail_index_view_unref_maps(view);
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen view->syncing = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *ctx_r = ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainenstatic bool view_sync_pos_find(ARRAY_TYPE(view_log_sync_pos) *sync_arr,
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen uint32_t seq, uoff_t offset)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen const struct mail_index_view_log_sync_pos *syncs;
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen unsigned int i, count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen if (!array_is_created(sync_arr))
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen syncs = array_get(sync_arr, &count);
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen for (i = 0; i < count; i++) {
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen if (syncs[i].log_file_offset == offset &&
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen syncs[i].log_file_seq == seq)
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainenstatic int
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainenmail_index_view_sync_get_next_transaction(struct mail_index_view_sync_ctx *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_transaction_log_view *log_view = ctx->view->log_view;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_view *view = ctx->view;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen uint32_t seq;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen uoff_t offset;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen int ret;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen bool skipped;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen for (;;) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* Get the next transaction from log. */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen ret = mail_transaction_log_view_next(log_view, &ctx->hdr,
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen &ctx->data, &skipped);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if (ret <= 0) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if (ret < 0)
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen return -1;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen ctx->hdr = NULL;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen ctx->last_read = TRUE;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen return 0;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen mail_transaction_log_view_get_prev_pos(log_view, &seq, &offset);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if (skipped) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* We skipped some (visible) transactions that were
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen outside our sync mask. */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen ctx->skipped_some = TRUE;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen } else if (!ctx->skipped_some) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* We haven't skipped anything while syncing this view.
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen Update this view's synced log offset. */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen view->log_file_seq = seq;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen view->log_file_offset = offset + sizeof(*ctx->hdr) +
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen ctx->hdr->size;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen /* skip everything we've already synced */
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen if (view_sync_pos_find(&view->syncs_done, seq, offset))
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen continue;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* Apply transaction to view's mapping if needed (meaning we
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen didn't just re-map the view to head mapping). */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if (ctx->sync_map_update) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen i_assert((ctx->hdr->type &
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen MAIL_TRANSACTION_EXPUNGE) == 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if (mail_index_sync_record(&ctx->sync_map_ctx,
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen ctx->hdr, ctx->data) < 0)
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen return -1;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if ((ctx->hdr->type & ctx->visible_sync_mask) == 0) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* non-visible change that we just wanted to update
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen to map. */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen continue;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen }
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen /* skip changes committed by hidden transactions (eg. in IMAP
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen store +flags.silent command) */
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen if (view_sync_pos_find(&view->syncs_hidden, seq, offset))
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen continue;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if (ctx->skipped_some) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* We've been skipping some transactions, which means we'll
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen go through these same transaction again later. Since we're
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen syncing this one, we don't want to do it again. */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen mail_index_view_add_synced_transaction(view, seq, offset);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen#define FLAG_UPDATE_IS_INTERNAL(u) \
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen ((((u)->add_flags | (u)->remove_flags) & \
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen ~(MAIL_INDEX_MAIL_FLAG_DIRTY | MAIL_RECENT)) == 0)
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainenstatic int
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainenmail_index_view_sync_get_rec(struct mail_index_view_sync_ctx *ctx,
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen struct mail_index_view_sync_rec *rec)
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen{
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen const struct mail_transaction_header *hdr = ctx->hdr;
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen const void *data = ctx->data;
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen case MAIL_TRANSACTION_APPEND: {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* data contains the appended records, but we don't care */
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_APPEND;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen rec->uid1 = rec->uid2 = 0;
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen ctx->data_offset += hdr->size;
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen break;
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen }
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen case MAIL_TRANSACTION_EXPUNGE: {
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen const struct mail_transaction_expunge *exp =
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen CONST_PTR_OFFSET(data, ctx->data_offset);
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* data contains mail_transaction_expunge[] */
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_EXPUNGE;
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen rec->uid1 = exp->uid1;
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen rec->uid2 = exp->uid2;
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen ctx->data_offset += sizeof(*exp);
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen break;
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen }
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen case MAIL_TRANSACTION_FLAG_UPDATE: {
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen const struct mail_transaction_flag_update *update =
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen CONST_PTR_OFFSET(data, ctx->data_offset);
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* data contains mail_transaction_flag_update[] */
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen for (;;) {
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen ctx->data_offset += sizeof(*update);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (!FLAG_UPDATE_IS_INTERNAL(update))
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen break;
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* skip internal flag changes */
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen if (ctx->data_offset == ctx->hdr->size)
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen return 0;
d0143523a87b41eae0b118ff03aad539903b3555Timo Sirainen
d0143523a87b41eae0b118ff03aad539903b3555Timo Sirainen update = CONST_PTR_OFFSET(data, ctx->data_offset);
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen }
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_FLAGS;
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen rec->uid1 = update->uid1;
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen rec->uid2 = update->uid2;
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen break;
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen case MAIL_TRANSACTION_KEYWORD_UPDATE: {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen const struct mail_transaction_keyword_update *update = data;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen const uint32_t *uids;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* data contains mail_transaction_keyword_update header,
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen the keyword name and an array of { uint32_t uid1, uid2; } */
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (ctx->data_offset == 0) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* skip over the header and name */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen ctx->data_offset = sizeof(*update) + update->name_size;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if ((ctx->data_offset % 4) != 0)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen ctx->data_offset += 4 - (ctx->data_offset % 4);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen uids = CONST_PTR_OFFSET(data, ctx->data_offset);
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen rec->uid1 = uids[0];
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen rec->uid2 = uids[1];
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen ctx->data_offset += sizeof(uint32_t) * 2;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen break;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen }
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen case MAIL_TRANSACTION_KEYWORD_RESET: {
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen const struct mail_transaction_keyword_reset *reset =
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen CONST_PTR_OFFSET(data, ctx->data_offset);
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* data contains mail_transaction_keyword_reset[] */
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET;
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen rec->uid1 = reset->uid1;
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen rec->uid2 = reset->uid2;
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen ctx->data_offset += sizeof(*reset);
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen break;
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen }
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen default:
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen i_unreached();
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen }
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen return 1;
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen}
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_index_view_sync_next(struct mail_index_view_sync_ctx *ctx,
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen struct mail_index_view_sync_rec *sync_rec)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen do {
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen if (ctx->hdr == NULL || ctx->data_offset == ctx->hdr->size) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen ret = mail_index_view_sync_get_next_transaction(ctx);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if (ret <= 0)
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen return ret;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen ctx->data_offset = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen } while (!mail_index_view_sync_get_rec(ctx, sync_rec));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenconst uint32_t *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_index_view_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen unsigned int *count_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen const struct uid_range *data;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen data = array_get(&ctx->expunges, count_r);
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen return (const uint32_t *)data;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainenstatic void
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainenmail_index_view_sync_clean_log_syncs(struct mail_index_view_sync_ctx *ctx,
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ARRAY_TYPE(view_log_sync_pos) *sync_arr)
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen{
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen struct mail_index_view *view = ctx->view;
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen const struct mail_index_view_log_sync_pos *syncs;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen unsigned int i, count;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen if (!array_is_created(sync_arr))
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen return;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if (!ctx->skipped_some) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* Nothing skipped. Clean it up the quick way. */
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen array_clear(sync_arr);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen return;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen }
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* Clean up until view's current syncing position */
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen syncs = array_get(sync_arr, &count);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen for (i = 0; i < count; i++) {
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen if ((syncs[i].log_file_offset >= view->log_file_offset &&
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen syncs[i].log_file_seq == view->log_file_seq) ||
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen syncs[i].log_file_seq > view->log_file_seq)
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen break;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen }
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if (i > 0)
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen array_delete(sync_arr, 0, i);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen}
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid mail_index_view_sync_end(struct mail_index_view_sync_ctx **_ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct mail_index_view_sync_ctx *ctx = *_ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_view *view = ctx->view;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(view->syncing);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen *_ctx = NULL;
9873ccef8e39b55637d80fd1a27619ea2c91cfd5Timo Sirainen mail_index_sync_map_deinit(&ctx->sync_map_ctx);
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen mail_index_view_sync_clean_log_syncs(ctx, &view->syncs_done);
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen mail_index_view_sync_clean_log_syncs(ctx, &view->syncs_hidden);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!ctx->last_read && ctx->hdr != NULL &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->data_offset != ctx->hdr->size) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we didn't sync everything */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->inconsistent = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen if (view->sync_new_map != NULL) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mail_index_unmap(view->index, &view->map);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen view->map = view->sync_new_map;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen view->sync_new_map = NULL;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen view->hdr = view->map->hdr;
5a58037ad75b88356d82240fab2bc604de03107eTimo Sirainen
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen /* set log view to empty range so unneeded memory gets freed */
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen (void)mail_transaction_log_view_set(view->log_view,
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen view->log_file_seq,
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen view->log_file_offset,
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen view->log_file_seq,
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen view->log_file_offset,
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen MAIL_TRANSACTION_TYPE_MASK);
7888a9d2008eab9985096c46e1da9ee985c22a2aTimo Sirainen
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen if (array_is_created(&ctx->expunges))
b032dc80e358f09893f09999f172ff12f5dbbb8eTimo Sirainen array_free(&ctx->expunges);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->syncing = FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(ctx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainenstatic void log_sync_pos_add(ARRAY_TYPE(view_log_sync_pos) *sync_arr,
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen uint32_t log_file_seq, uoff_t log_file_offset)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen struct mail_index_view_log_sync_pos *pos;
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen
26a8b7deb3a5b6f26f9c4d71538e1248f680e4beTimo Sirainen if (!array_is_created(sync_arr))
26a8b7deb3a5b6f26f9c4d71538e1248f680e4beTimo Sirainen ARRAY_CREATE(sync_arr, default_pool, 32);
7b3bf1de3fa7eee2185d1e404812b50c295e2b93Timo Sirainen
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen pos = array_append_space(sync_arr);
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen pos->log_file_seq = log_file_seq;
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen pos->log_file_offset = log_file_offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainenvoid mail_index_view_add_synced_transaction(struct mail_index_view *view,
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen uint32_t log_file_seq,
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen uoff_t log_file_offset)
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen{
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen log_sync_pos_add(&view->syncs_done, log_file_seq, log_file_offset);
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen}
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainenvoid mail_index_view_add_hidden_transaction(struct mail_index_view *view,
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen uint32_t log_file_seq,
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen uoff_t log_file_offset)
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen{
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen log_sync_pos_add(&view->syncs_hidden, log_file_seq, log_file_offset);
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen}