mail-index-view-sync.c revision d2b0d5daa7350cd0d67f011e8b390a256f5f4218
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen#include "lib.h"
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen#include "array.h"
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen#include "buffer.h"
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen#include "mail-index-view-private.h"
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen#include "mail-index-sync-private.h"
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen#include "mail-transaction-log.h"
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen#include "mail-transaction-util.h"
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainenstruct mail_index_view_sync_ctx {
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen struct mail_index_view *view;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen enum mail_transaction_type visible_sync_mask;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen struct mail_index_sync_map_ctx sync_map_ctx;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen ARRAY_TYPE(seq_range) expunges;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen const struct mail_transaction_header *hdr;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen const void *data;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen size_t data_offset;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen unsigned int skipped_some:1;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen unsigned int last_read:1;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen unsigned int sync_map_update:1;
39e6fcc3e8b1ccb13087c232cb6bdea04d1a20a4Timo Sirainen};
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainenstatic void
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainenmail_transaction_log_sort_expunges(ARRAY_TYPE(seq_range) *expunges,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen const struct seq_range *src, size_t src_size)
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen{
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen /* Note that all the sequences are actually still UIDs at this point */
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen const struct seq_range *src_end;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen struct seq_range *dest, new_exp;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen unsigned int first, i, dest_count;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen i_assert(src_size % sizeof(*src) == 0);
150e64c376365becf1ec5c9d45912ecb840eea96Timo Sirainen
150e64c376365becf1ec5c9d45912ecb840eea96Timo Sirainen /* @UNSAFE */
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen dest = array_get_modifiable(expunges, &dest_count);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (dest_count == 0) {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen array_append(expunges, src, src_size / sizeof(*src));
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen return;
39e6fcc3e8b1ccb13087c232cb6bdea04d1a20a4Timo Sirainen }
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen src_end = CONST_PTR_OFFSET(src, src_size);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen for (i = 0; src != src_end; src++) {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen /* src[] must be sorted. */
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen i_assert(src+1 == src_end || src->seq2 < src[1].seq1);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen i_assert(src->seq1 <= src->seq2);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen for (; i < dest_count; i++) {
39e6fcc3e8b1ccb13087c232cb6bdea04d1a20a4Timo Sirainen if (src->seq1 < dest[i].seq1)
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen break;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen new_exp = *src;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen first = i;
bc3698b8892df8003b410daea6f5bbcd20433808Timo Sirainen while (i < dest_count && src->seq2 >= dest[i].seq1-1) {
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen /* we can/must merge with next record */
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (new_exp.seq2 < dest[i].seq2)
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen new_exp.seq2 = dest[i].seq2;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen i++;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen }
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen if (first > 0 && new_exp.seq1 <= dest[first-1].seq2+1) {
ccb77e2f63626ec46e5745ef4f38baa8e8e504fcTimo Sirainen /* continue previous record */
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (dest[first-1].seq2 < new_exp.seq2)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen dest[first-1].seq2 = new_exp.seq2;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen } else if (i == first) {
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen array_insert(expunges, i, &new_exp, 1);
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen i++; first++;
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen dest = array_get_modifiable(expunges, &dest_count);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen } else {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen /* use next record */
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen dest[first] = new_exp;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen first++;
63f36c2b47217fc2dc4ed49cfc1907311d5ed366Timo Sirainen }
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen if (i > first) {
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen array_delete(expunges, first, i - first);
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen dest = array_get_modifiable(expunges, &dest_count);
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen i = first;
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen }
c6ae908f6a2313573625d782bdd4e0ff3882c44aTimo Sirainen }
c6ae908f6a2313573625d782bdd4e0ff3882c44aTimo Sirainen}
150e64c376365becf1ec5c9d45912ecb840eea96Timo Sirainen
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainenstatic int view_sync_set_log_view_range(struct mail_index_view *view,
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen enum mail_transaction_type type_mask)
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen{
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen const struct mail_index_header *hdr = view->index->hdr;
17b03c9db961e1c004284907d969eb11b08a795eTimo Sirainen int ret;
17b03c9db961e1c004284907d969eb11b08a795eTimo Sirainen
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen ret = mail_transaction_log_view_set(view->log_view,
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen view->log_file_seq,
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen view->log_file_offset,
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen hdr->log_file_seq,
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen hdr->log_file_int_offset,
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen type_mask);
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen if (ret <= 0) {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (ret == 0) {
ccb77e2f63626ec46e5745ef4f38baa8e8e504fcTimo Sirainen /* FIXME: use the new index to get needed changes */
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen mail_index_set_error(view->index,
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen "Transaction log got desynced for index %s",
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen view->index->filepath);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen mail_index_set_inconsistent(view->index);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen }
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen return -1;
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen }
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen return 0;
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen}
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainenstatic int
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainenview_sync_get_expunges(struct mail_index_view *view,
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen ARRAY_TYPE(seq_range) *expunges_r)
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen{
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen const struct mail_transaction_header *hdr;
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen struct seq_range *src, *src_end, *dest;
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen const void *data;
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen unsigned int count;
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen int ret;
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen if (view_sync_set_log_view_range(view, MAIL_TRANSACTION_EXPUNGE) < 0)
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen return -1;
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen i_array_init(expunges_r, 64);
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen &hdr, &data, NULL)) > 0) {
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen i_assert((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0);
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen mail_transaction_log_sort_expunges(expunges_r, data, hdr->size);
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen }
68efcccb384f2d6871164b072457e87473502c51Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen if (ret < 0) {
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen array_free(expunges_r);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen return -1;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen }
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen /* convert UIDs to sequences */
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen src = dest = array_get_modifiable(expunges_r, &count);
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen src_end = src + count;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen for (; src != src_end; src++) {
68efcccb384f2d6871164b072457e87473502c51Timo Sirainen ret = mail_index_lookup_uid_range(view, src->seq1,
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen src->seq2,
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen &dest->seq1,
a54be2bd26d6f0860d194d3aeedfa6b7fc14d24cTimo Sirainen &dest->seq2);
a54be2bd26d6f0860d194d3aeedfa6b7fc14d24cTimo Sirainen i_assert(ret == 0);
a54be2bd26d6f0860d194d3aeedfa6b7fc14d24cTimo Sirainen
10cfe8a2bdc5ccfc05380689c71c27209327538fTimo Sirainen if (dest->seq1 == 0)
10cfe8a2bdc5ccfc05380689c71c27209327538fTimo Sirainen count--;
a54be2bd26d6f0860d194d3aeedfa6b7fc14d24cTimo Sirainen else
10cfe8a2bdc5ccfc05380689c71c27209327538fTimo Sirainen dest++;
a54be2bd26d6f0860d194d3aeedfa6b7fc14d24cTimo Sirainen }
a54be2bd26d6f0860d194d3aeedfa6b7fc14d24cTimo Sirainen array_delete(expunges_r, count, array_count(expunges_r) - count);
a54be2bd26d6f0860d194d3aeedfa6b7fc14d24cTimo Sirainen return 0;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen}
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainenstatic void mail_index_view_hdr_update(struct mail_index_view *view,
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen struct mail_index_map *map)
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen{
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen /* Keep message count the same. */
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen map->hdr.next_uid = view->hdr.next_uid;
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen map->hdr.messages_count = view->hdr.messages_count;
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen /* Keep the old message flag counts also, although they may be
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen somewhat stale already. We just don't want them to be more than
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen our old messages_count. */
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen map->hdr.recent_messages_count = view->hdr.recent_messages_count;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen map->hdr.seen_messages_count = view->hdr.seen_messages_count;
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen map->hdr.deleted_messages_count = view->hdr.deleted_messages_count;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen /* Keep log position so we know where to continue syncing */
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen map->hdr.log_file_seq = view->hdr.log_file_seq;
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen map->hdr.log_file_int_offset = view->hdr.log_file_int_offset;
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen map->hdr.log_file_ext_offset = view->hdr.log_file_ext_offset;
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen view->hdr = map->hdr;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen buffer_write(map->hdr_copy_buf, 0, &map->hdr, sizeof(map->hdr));
68efcccb384f2d6871164b072457e87473502c51Timo Sirainen}
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen#define MAIL_INDEX_VIEW_VISIBLE_FLAGS_MASK \
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen (MAIL_INDEX_SYNC_TYPE_FLAGS | \
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET | \
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD | MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE)
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen#define MAIL_TRANSACTION_VISIBLE_SYNC_MASK \
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen (MAIL_TRANSACTION_EXPUNGE | MAIL_TRANSACTION_APPEND | \
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen MAIL_TRANSACTION_FLAG_UPDATE | MAIL_TRANSACTION_KEYWORD_UPDATE | \
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen MAIL_TRANSACTION_KEYWORD_RESET)
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainenint mail_index_view_sync_begin(struct mail_index_view *view,
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen enum mail_index_sync_type sync_mask,
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen struct mail_index_view_sync_ctx **ctx_r)
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen{
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen const struct mail_index_header *hdr;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen struct mail_index_view_sync_ctx *ctx;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen struct mail_index_map *map;
68efcccb384f2d6871164b072457e87473502c51Timo Sirainen enum mail_transaction_type log_get_mask, visible_mask;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen ARRAY_TYPE(seq_range) expunges = ARRAY_INIT;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen /* We must sync flags as long as view is mmap()ed, as the flags may
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen have already changed under us. */
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen i_assert((sync_mask & MAIL_INDEX_VIEW_VISIBLE_FLAGS_MASK) ==
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen MAIL_INDEX_VIEW_VISIBLE_FLAGS_MASK);
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen /* Currently we're not handling correctly expunges + no-appends case */
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen i_assert((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) == 0 ||
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen (sync_mask & MAIL_INDEX_SYNC_TYPE_APPEND) != 0);
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen i_assert(!view->syncing);
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen i_assert(view->transactions == 0);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (mail_index_view_lock_head(view, TRUE) < 0)
3419b088ffe531799bdb47b3ff3fce85c8b7569aTimo Sirainen return -1;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen hdr = view->index->hdr;
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0) {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen /* get list of all expunges first */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (view_sync_get_expunges(view, &expunges) < 0)
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen return -1;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen /* only flags, appends and expunges can be left to be synced later */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen visible_mask = mail_transaction_type_mask_get(sync_mask);
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen i_assert((visible_mask & ~MAIL_TRANSACTION_VISIBLE_SYNC_MASK) == 0);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* we want to also get non-visible changes. especially because we use
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen the returned skipped-flag in mail_transaction_log_view_next() to
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen tell us if any visible changes were skipped. */
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen log_get_mask = visible_mask | (MAIL_TRANSACTION_TYPE_MASK ^
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen MAIL_TRANSACTION_VISIBLE_SYNC_MASK);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (view_sync_set_log_view_range(view, log_get_mask) < 0) {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (array_is_created(&expunges))
3419b088ffe531799bdb47b3ff3fce85c8b7569aTimo Sirainen array_free(&expunges);
3419b088ffe531799bdb47b3ff3fce85c8b7569aTimo Sirainen return -1;
3419b088ffe531799bdb47b3ff3fce85c8b7569aTimo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen ctx = i_new(struct mail_index_view_sync_ctx, 1);
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen ctx->view = view;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen ctx->visible_sync_mask = visible_mask;
2d340205d897e23fbecb40c8e63a4ca49bd6739bTimo Sirainen ctx->expunges = expunges;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen mail_index_sync_map_init(&ctx->sync_map_ctx, view,
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen MAIL_INDEX_SYNC_HANDLER_VIEW);
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0 &&
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen (sync_mask & MAIL_INDEX_SYNC_TYPE_APPEND) != 0) {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen view->sync_new_map = view->index->map;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen view->sync_new_map->refcount++;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* since we're syncing everything, the counters get fixed */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen view->broken_counters = FALSE;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* keep the old mapping without expunges until we're
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen fully synced */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen } else {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* We need a private copy of the map if we don't want to
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen sync expunges.
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen If view's map is the head map, it means that it contains
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen already all the latest changes and there's no need for us
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen to apply any changes to it. This can only happen if there
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen hadn't been any expunges. */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen uint32_t old_records_count = view->map->records_count;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen if (view->map != view->index->map) {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* Using non-head mapping. We have to apply
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen transactions to it to get latest changes into it. */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen ctx->sync_map_update = TRUE;
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen /* Unless map was synced at the exact same position as
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen view, the message flags can't be reliably used to
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen update flag counters. */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen ctx->sync_map_ctx.unreliable_flags =
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen !(view->map->hdr.log_file_seq ==
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen view->log_file_seq &&
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen view->map->hdr.log_file_int_offset ==
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen view->log_file_offset);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* Copy only the mails that we see currently, since
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen we're going to append the new ones when we see
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen their transactions. */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen i_assert(view->map->records_count >=
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen view->hdr.messages_count);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen view->map->records_count = view->hdr.messages_count;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen map = mail_index_map_clone(view->map,
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen view->map->hdr.record_size);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen view->map->records_count = old_records_count;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen mail_index_unmap(view->index, &view->map);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen view->map = map;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (ctx->sync_map_update) {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* Start the sync using our old view's header.
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen The old view->hdr may differ from map->hdr if
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen another view sharing the map with us had synced
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen itself. */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen i_assert(map->hdr_base == map->hdr_copy_buf->data);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen mail_index_view_hdr_update(view, map);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen i_assert(map->records_count == map->hdr.messages_count);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* Syncing the view invalidates all previous looked up records.
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen Unreference the mappings this view keeps because of them. */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen mail_index_view_unref_maps(view);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen view->syncing = TRUE;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen *ctx_r = ctx;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen return 0;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen}
2d340205d897e23fbecb40c8e63a4ca49bd6739bTimo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainenstatic bool view_sync_pos_find(ARRAY_TYPE(view_log_sync_pos) *sync_arr,
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen uint32_t seq, uoff_t offset)
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen{
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen const struct mail_index_view_log_sync_pos *syncs;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen unsigned int i, count;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen if (!array_is_created(sync_arr))
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen return FALSE;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen syncs = array_get(sync_arr, &count);
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen for (i = 0; i < count; i++) {
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen if (syncs[i].log_file_offset == offset &&
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen syncs[i].log_file_seq == seq)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen return TRUE;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen return FALSE;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen}
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
e60a349c641bb2f4723e4a395a25f55531682d2bTimo Sirainenstatic int
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainenmail_index_view_sync_get_next_transaction(struct mail_index_view_sync_ctx *ctx)
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen{
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen struct mail_transaction_log_view *log_view = ctx->view->log_view;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen struct mail_index_view *view = ctx->view;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen uint32_t seq;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen uoff_t offset;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen int ret;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen bool skipped;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen for (;;) {
294f1a51763015cda0e2d874c5027d6fe7a2cd54Timo Sirainen /* Get the next transaction from log. */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen ret = mail_transaction_log_view_next(log_view, &ctx->hdr,
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen &ctx->data, &skipped);
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (skipped) {
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen /* We skipped some (visible) transactions that were
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen outside our sync mask. Note that we may get here
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen even when ret=0. */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen ctx->skipped_some = TRUE;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen if (ret <= 0) {
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen if (ret < 0)
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen return -1;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen ctx->hdr = NULL;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen ctx->last_read = TRUE;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen return 0;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen }
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen mail_transaction_log_view_get_prev_pos(log_view, &seq, &offset);
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen if (!ctx->skipped_some) {
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen /* We haven't skipped anything while syncing this view.
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen Update this view's synced log offset. */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen view->log_file_seq = seq;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen view->log_file_offset = offset + sizeof(*ctx->hdr) +
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen ctx->hdr->size;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* skip everything we've already synced */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (view_sync_pos_find(&view->syncs_done, seq, offset))
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen continue;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen if (ctx->skipped_some) {
2d340205d897e23fbecb40c8e63a4ca49bd6739bTimo Sirainen /* We've been skipping some transactions, which means
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen we'll go through these same transactions again
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen later. Since we're syncing this one, we don't want
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen to do it again. */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen mail_index_view_add_synced_transaction(view, seq,
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen offset);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* Apply transaction to view's mapping if needed (meaning we
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen didn't just re-map the view to head mapping). */
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen if (ctx->sync_map_update) {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen i_assert((ctx->hdr->type &
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen MAIL_TRANSACTION_EXPUNGE) == 0);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (mail_index_sync_record(&ctx->sync_map_ctx,
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen ctx->hdr, ctx->data) < 0)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen return -1;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if ((ctx->hdr->type & ctx->visible_sync_mask) == 0) {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* non-visible change that we just wanted to update
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen to map. */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen continue;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen /* skip changes committed by hidden transactions (eg. in IMAP
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen store +flags.silent command) */
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen if (view_sync_pos_find(&view->syncs_hidden, seq, offset))
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen continue;
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen break;
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen }
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen return 1;
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen}
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen#define FLAG_UPDATE_IS_INTERNAL(u) \
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen ((((u)->add_flags | (u)->remove_flags) & \
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen ~(MAIL_INDEX_MAIL_FLAG_DIRTY | MAIL_RECENT)) == 0)
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainenstatic int
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainenmail_index_view_sync_get_rec(struct mail_index_view_sync_ctx *ctx,
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen struct mail_index_view_sync_rec *rec)
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen{
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen const struct mail_transaction_header *hdr = ctx->hdr;
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen const void *data = ctx->data;
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen case MAIL_TRANSACTION_APPEND: {
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen /* data contains the appended records, but we don't care */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_APPEND;
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen rec->uid1 = rec->uid2 = 0;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen ctx->data_offset += hdr->size;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen break;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen case MAIL_TRANSACTION_EXPUNGE: {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen const struct mail_transaction_expunge *exp =
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen CONST_PTR_OFFSET(data, ctx->data_offset);
/* data contains mail_transaction_expunge[] */
rec->type = MAIL_INDEX_SYNC_TYPE_EXPUNGE;
rec->uid1 = exp->uid1;
rec->uid2 = exp->uid2;
ctx->data_offset += sizeof(*exp);
break;
}
case MAIL_TRANSACTION_FLAG_UPDATE: {
const struct mail_transaction_flag_update *update =
CONST_PTR_OFFSET(data, ctx->data_offset);
/* data contains mail_transaction_flag_update[] */
for (;;) {
ctx->data_offset += sizeof(*update);
if (!FLAG_UPDATE_IS_INTERNAL(update))
break;
/* skip internal flag changes */
if (ctx->data_offset == ctx->hdr->size)
return 0;
update = CONST_PTR_OFFSET(data, ctx->data_offset);
}
rec->type = MAIL_INDEX_SYNC_TYPE_FLAGS;
rec->uid1 = update->uid1;
rec->uid2 = update->uid2;
break;
}
case MAIL_TRANSACTION_KEYWORD_UPDATE: {
const struct mail_transaction_keyword_update *update = data;
const uint32_t *uids;
/* data contains mail_transaction_keyword_update header,
the keyword name and an array of { uint32_t uid1, uid2; } */
if (ctx->data_offset == 0) {
/* skip over the header and name */
ctx->data_offset = sizeof(*update) + update->name_size;
if ((ctx->data_offset % 4) != 0)
ctx->data_offset += 4 - (ctx->data_offset % 4);
}
uids = CONST_PTR_OFFSET(data, ctx->data_offset);
rec->type = MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD;
rec->uid1 = uids[0];
rec->uid2 = uids[1];
ctx->data_offset += sizeof(uint32_t) * 2;
break;
}
case MAIL_TRANSACTION_KEYWORD_RESET: {
const struct mail_transaction_keyword_reset *reset =
CONST_PTR_OFFSET(data, ctx->data_offset);
/* data contains mail_transaction_keyword_reset[] */
rec->type = MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET;
rec->uid1 = reset->uid1;
rec->uid2 = reset->uid2;
ctx->data_offset += sizeof(*reset);
break;
}
default:
i_unreached();
}
return 1;
}
int mail_index_view_sync_next(struct mail_index_view_sync_ctx *ctx,
struct mail_index_view_sync_rec *sync_rec)
{
int ret;
do {
if (ctx->hdr == NULL || ctx->data_offset == ctx->hdr->size) {
ret = mail_index_view_sync_get_next_transaction(ctx);
if (ret <= 0)
return ret;
ctx->data_offset = 0;
}
} while (!mail_index_view_sync_get_rec(ctx, sync_rec));
return 1;
}
void mail_index_view_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
const ARRAY_TYPE(seq_range) **expunges_r)
{
*expunges_r = &ctx->expunges;
}
static void
mail_index_view_sync_clean_log_syncs(struct mail_index_view_sync_ctx *ctx,
ARRAY_TYPE(view_log_sync_pos) *sync_arr)
{
struct mail_index_view *view = ctx->view;
const struct mail_index_view_log_sync_pos *syncs;
unsigned int i, count;
if (!array_is_created(sync_arr))
return;
if (!ctx->skipped_some) {
/* Nothing skipped. Clean it up the quick way. */
array_clear(sync_arr);
return;
}
/* Clean up until view's current syncing position */
syncs = array_get(sync_arr, &count);
for (i = 0; i < count; i++) {
if ((syncs[i].log_file_offset >= view->log_file_offset &&
syncs[i].log_file_seq == view->log_file_seq) ||
syncs[i].log_file_seq > view->log_file_seq)
break;
}
if (i > 0)
array_delete(sync_arr, 0, i);
}
void mail_index_view_sync_end(struct mail_index_view_sync_ctx **_ctx)
{
struct mail_index_view_sync_ctx *ctx = *_ctx;
struct mail_index_view *view = ctx->view;
i_assert(view->syncing);
*_ctx = NULL;
mail_index_sync_map_deinit(&ctx->sync_map_ctx);
mail_index_view_sync_clean_log_syncs(ctx, &view->syncs_done);
mail_index_view_sync_clean_log_syncs(ctx, &view->syncs_hidden);
if (!ctx->last_read && ctx->hdr != NULL &&
ctx->data_offset != ctx->hdr->size) {
/* we didn't sync everything */
view->inconsistent = TRUE;
}
if (view->sync_new_map != NULL) {
mail_index_unmap(view->index, &view->map);
view->map = view->sync_new_map;
view->sync_new_map = NULL;
}
view->hdr = view->map->hdr;
/* set log view to empty range so unneeded memory gets freed */
(void)mail_transaction_log_view_set(view->log_view,
view->log_file_seq,
view->log_file_offset,
view->log_file_seq,
view->log_file_offset,
MAIL_TRANSACTION_TYPE_MASK);
if (array_is_created(&ctx->expunges))
array_free(&ctx->expunges);
view->syncing = FALSE;
i_free(ctx);
}
static void log_sync_pos_add(ARRAY_TYPE(view_log_sync_pos) *sync_arr,
uint32_t log_file_seq, uoff_t log_file_offset)
{
struct mail_index_view_log_sync_pos *pos;
if (!array_is_created(sync_arr))
i_array_init(sync_arr, 32);
pos = array_append_space(sync_arr);
pos->log_file_seq = log_file_seq;
pos->log_file_offset = log_file_offset;
}
void mail_index_view_add_synced_transaction(struct mail_index_view *view,
uint32_t log_file_seq,
uoff_t log_file_offset)
{
log_sync_pos_add(&view->syncs_done, log_file_seq, log_file_offset);
}
void mail_index_view_add_hidden_transaction(struct mail_index_view *view,
uint32_t log_file_seq,
uoff_t log_file_offset)
{
log_sync_pos_add(&view->syncs_hidden, log_file_seq, log_file_offset);
}