mail-index-view-sync.c revision 4e1899e9bdafd0da1692240d21314d9c07d9946e
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2003-2009 Dovecot authors, see the included COPYING file */
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen /* After syncing view, map is replaced with sync_new_map. */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* temporary variables while handling lost transaction logs: */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ARRAY_TYPE(keyword_indexes) lost_old_kw, lost_new_kw;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* result of lost transaction logs: */
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainenmail_transaction_log_sort_expunges(ARRAY_TYPE(seq_range) *expunges,
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen /* Note that all the sequences are actually still UIDs at this point */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* @UNSAFE */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen dest = array_get_modifiable(expunges, &dest_count);
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen array_append(expunges, src, src_size / sizeof(*src));
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen /* src[] must be sorted. */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen (src+1 != src_end && src->seq2 >= src[1].seq1))
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen for (; i < dest_count; i++) {
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen while (i < dest_count && src->seq2 >= dest[i].seq1-1) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* we can/must merge with next record */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (first > 0 && new_exp.seq1 <= dest[first-1].seq2+1) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* continue previous record */
a30b52af112bc98b74b8624e9a5d20cb754b2ab7Timo Sirainen } else if (i == first) {
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen dest = array_get_modifiable(expunges, &dest_count);
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen /* use next record */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen dest = array_get_modifiable(expunges, &dest_count);
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainenview_sync_set_log_view_range(struct mail_index_view *view, bool sync_expunges,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen const struct mail_index_header *hdr = &view->index->map->hdr;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* the view begins from the first non-synced transaction */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ret = mail_transaction_log_view_set(view->log_view,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* log was reset, but we don't want to sync expunges.
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen we can't do this, so sync only up to the reset. */
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen mail_transaction_log_view_get_prev_pos(view->log_view,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* we have only this reset log */
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen mail_transaction_log_view_clear(view->log_view,
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainenstatic unsigned int
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenview_sync_expunges2seqs(struct mail_index_view_sync_ctx *ctx)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* convert UIDs to sequences */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen src = dest = array_get_modifiable(&ctx->expunges, &count);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (!mail_index_lookup_seq_range(view, src->seq1, src->seq2,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenview_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* get a list of expunge transactions. there may be some that we have
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen already synced, but it doesn't matter because they'll get dropped
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen out when converting to sequences */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen mail_transaction_log_view_mark(view->log_view);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) == 0)
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen /* this is simply a request for expunge */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (mail_transaction_log_sort_expunges(&ctx->expunges, data,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen mail_transaction_log_view_set_corrupted(view->log_view,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen "Corrupted expunge record");
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen mail_transaction_log_view_rewind(view->log_view);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen *expunge_count_r = view_sync_expunges2seqs(ctx);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic bool have_existing_expunges(struct mail_index_view *view,
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen if (mail_index_lookup_seq_range(view, range->seq1, range->seq2,
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainenstatic bool view_sync_have_expunges(struct mail_index_view *view)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen mail_transaction_log_view_mark(view->log_view);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) == 0)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* this is simply a request for expunge */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* we have an expunge. see if it still exists. */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (have_existing_expunges(view, data, hdr->size)) {
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainen mail_transaction_log_view_rewind(view->log_view);
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen /* handle failures as having expunges (which is safer).
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen we'll probably fail later. */
74674a53a72dab535c61f455b2246ef2797844eaTimo Sirainenstatic int uint_cmp(const void *p1, const void *p2)
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainenstatic bool view_sync_lost_keywords_equal(struct mail_index_view_sync_ctx *ctx)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen old_idx = array_get_modifiable(&ctx->lost_old_kw, &old_count);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen new_idx = array_get_modifiable(&ctx->lost_new_kw, &new_count);
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen qsort(old_idx, old_count, sizeof(*old_idx), uint_cmp);
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen qsort(new_idx, new_count, sizeof(*new_idx), uint_cmp);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return memcmp(old_idx, new_idx, old_count * sizeof(old_idx)) == 0;
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainenstatic int view_sync_update_keywords(struct mail_index_view_sync_ctx *ctx,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const unsigned int *kw_idx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *const *kw_names;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen unsigned int i, count;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen kw_idx = array_get(&ctx->lost_new_kw, &count);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen kw_names = array_idx(&ctx->view->index->keywords, 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen thdr.type = MAIL_TRANSACTION_KEYWORD_UPDATE | MAIL_TRANSACTION_EXTERNAL;
for (i = 0; i < count; i++) {
&flag_update) < 0)
&kw_reset) < 0)
if (changed) {
if (changed)
unsigned int *expunge_count_r)
for (; i < old_count; i++) {
for (; j < new_count; j++) {
bool reset;
struct mail_index_view_sync_ctx *
unsigned int expunge_count = 0;
int ret;
if (sync_expunges)
return ctx;
return ctx;
if (ret < 0) {
return ctx;
if (ret == 0) {
if (!sync_expunges)
if (ret < 0) {
return ctx;
} else if (sync_expunges) {
return ctx;
if (!have_expunges) {
if (sync_expunges) {
#ifdef DEBUG
return ctx;
unsigned int i, count;
return FALSE;
for (i = 0; i < count; i++) {
return TRUE;
return FALSE;
return FALSE;
return FALSE;
return FALSE;
return TRUE;
int ret;
bool synced_to_map;
if (ret <= 0) {
if (ret < 0)
} T_END;
if (ret < 0)
case MAIL_TRANSACTION_FLAG_UPDATE: {
case MAIL_TRANSACTION_KEYWORD_UPDATE: {
case MAIL_TRANSACTION_KEYWORD_RESET: {
return FALSE;
return TRUE;
unsigned int count;
return FALSE;
return TRUE;
int ret;
if (ret <= 0) {
if (ret < 0)
return FALSE;
return TRUE;
unsigned int i, count;
for (i = 0; i < count; i++) {
bool *delayed_expunges_r)
#ifdef DEBUG
return ret;
unsigned int length)