Mercurial > dovecot > core-2.2
view src/lib-storage/index/index-sync-pvt.c @ 15714:90710c6c3beb
Updated copyright notices to include year 2013.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 02 Feb 2013 17:01:07 +0200 |
parents | 69371578720f |
children | 36ef72481934 |
line wrap: on
line source
* Copyright (c) 2013 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "mailbox-list-private.h" #include "index-sync-private.h" static int sync_pvt_expunges(struct mailbox *box, struct mail_index_view *view_pvt, struct mail_index_transaction *trans_pvt, struct mail_index_view *view_shared) { uint32_t seq_shared, seq_pvt, count_shared, count_pvt; uint32_t uid_shared, uid_pvt; count_shared = mail_index_view_get_messages_count(view_shared); count_pvt = mail_index_view_get_messages_count(view_pvt); seq_shared = seq_pvt = 1; while (seq_pvt <= count_pvt && seq_shared <= count_shared) { mail_index_lookup_uid(view_pvt, seq_pvt, &uid_pvt); mail_index_lookup_uid(view_shared, seq_shared, &uid_shared); if (uid_pvt == uid_shared) { seq_pvt++; seq_shared++; } else if (uid_pvt < uid_shared) { /* message expunged */ mail_index_expunge(trans_pvt, seq_pvt); seq_pvt++; } else { mail_storage_set_critical(box->storage, "%s: Message UID=%u unexpectedly inserted to mailbox", box->index_pvt->filepath, uid_shared); return -1; } } return 0; } static void sync_pvt_copy_self_flags(struct mailbox *box, struct mail_index_view *view, struct mail_index_transaction *trans, ARRAY_TYPE(keyword_indexes) *keywords, uint32_t seq_old, uint32_t seq_new) { const struct mail_index_record *old_rec; old_rec = mail_index_lookup(view, seq_old); mail_index_lookup_keywords(view, seq_old, keywords); if (old_rec->flags != 0) { mail_index_update_flags(trans, seq_new, MODIFY_ADD, old_rec->flags); } if (array_count(keywords) > 0) { struct mail_keywords *kw; kw = mail_index_keywords_create_from_indexes(box->index_pvt, keywords); mail_index_update_keywords(trans, seq_new, MODIFY_ADD, kw); mail_index_keywords_unref(&kw); } } static int index_storage_mailbox_sync_pvt_index(struct mailbox *box) { struct mail_index_sync_ctx *sync_ctx; struct mail_index_view *view_pvt; struct mail_index_transaction *trans_pvt; const struct mail_index_header *hdr_shared, *hdr_pvt; struct mail_index_view *view_shared; ARRAY_TYPE(keyword_indexes) keywords; uint32_t seq_shared, seq_pvt, seq_old_pvt, seq2, count_shared, uid; bool reset = FALSE, preserve_old_flags = FALSE; int ret; /* open a view for the latest version of the index */ if (mail_index_refresh(box->index) < 0 || mail_index_refresh(box->index_pvt) < 0) { mailbox_set_index_error(box); return -1; } view_shared = mail_index_view_open(box->index); hdr_shared = mail_index_get_header(view_shared); if (hdr_shared->uid_validity == 0) { /* the mailbox hasn't been fully created yet, no need for a private index yet */ mail_index_view_close(&view_shared); return 0; } hdr_pvt = mail_index_get_header(box->view_pvt); if (hdr_pvt->next_uid == hdr_shared->next_uid && hdr_pvt->messages_count == hdr_shared->messages_count) { /* no new or expunged mails, don't bother syncing */ mail_index_view_close(&view_shared); return 0; } if (mail_index_sync_begin(box->index_pvt, &sync_ctx, &view_pvt, &trans_pvt, 0) < 0) { mailbox_set_index_error(box); mail_index_view_close(&view_shared); return -1; } /* get an updated private header */ hdr_pvt = mail_index_get_header(view_pvt); if (hdr_shared->uid_validity == hdr_pvt->uid_validity) { /* same mailbox. expunge messages from private index that no longer exist. */ if (sync_pvt_expunges(box, view_pvt, trans_pvt, view_shared) < 0) { reset = TRUE; preserve_old_flags = TRUE; t_array_init(&keywords, 32); } } else if (hdr_pvt->uid_validity == 0 || hdr_pvt->uid_validity != 0) { /* mailbox created/recreated */ reset = TRUE; } count_shared = mail_index_view_get_messages_count(view_shared); if (!reset) { if (!mail_index_lookup_seq_range(view_shared, hdr_pvt->next_uid, hdr_shared->next_uid, &seq_shared, &seq2)) { /* no new messages */ seq_shared = count_shared+1; } } else { mail_index_reset(trans_pvt); mail_index_update_header(trans_pvt, offsetof(struct mail_index_header, uid_validity), &hdr_shared->uid_validity, sizeof(hdr_shared->uid_validity), TRUE); seq_shared = 1; } uid = 0; for (; seq_shared <= count_shared; seq_shared++) { mail_index_lookup_uid(view_shared, seq_shared, &uid); mail_index_append(trans_pvt, uid, &seq_pvt); if (preserve_old_flags && mail_index_lookup_seq(view_pvt, uid, &seq_old_pvt)) { /* copy flags from the original index */ sync_pvt_copy_self_flags(box, view_pvt, trans_pvt, &keywords, seq_old_pvt, seq_pvt); } } if (uid < hdr_shared->next_uid) { mail_index_update_header(trans_pvt, offsetof(struct mail_index_header, next_uid), &hdr_shared->next_uid, sizeof(hdr_shared->next_uid), FALSE); } if ((ret = mail_index_sync_commit(&sync_ctx)) < 0) mailbox_set_index_error(box); mail_index_view_close(&view_shared); return ret; } int index_storage_mailbox_sync_pvt(struct mailbox *box, ARRAY_TYPE(seq_range) *flag_updates, ARRAY_TYPE(seq_range) *hidden_updates) { struct mail_index_view_sync_ctx *view_sync_ctx; struct mail_index_view_sync_rec sync_rec; uint32_t seq1, seq2; bool delayed_expunges; int ret; if ((ret = mailbox_open_index_pvt(box)) <= 0) return ret; /* sync private index against shared index by adding/removing mails */ if (index_storage_mailbox_sync_pvt_index(box) < 0) return -1; /* sync the private view */ view_sync_ctx = mail_index_view_sync_begin(box->view_pvt, 0); while (mail_index_view_sync_next(view_sync_ctx, &sync_rec)) { if (sync_rec.type != MAIL_INDEX_VIEW_SYNC_TYPE_FLAGS) continue; /* *_updates contains box->view sequences (not view_pvt sequences) */ if (mail_index_lookup_seq_range(box->view, sync_rec.uid1, sync_rec.uid2, &seq1, &seq2)) { if (!sync_rec.hidden) { seq_range_array_add_range(flag_updates, seq1, seq2); } else { seq_range_array_add_range(hidden_updates, seq1, seq2); } } } if (mail_index_view_sync_commit(&view_sync_ctx, &delayed_expunges) < 0) return -1; return 0; }