mail-index-view-sync.c revision 0c909e3461607eadcd66f4eac69b7f34e37fccf1
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2003-2009 Dovecot authors, see the included COPYING file */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* After syncing view, map is replaced with sync_new_map. */
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainen /* temporary variables while handling lost transaction logs: */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen ARRAY_TYPE(keyword_indexes) lost_old_kw, lost_new_kw;
5733207dc3ec10e6e5a6e0a8b30fbd1b061062b9Timo Sirainen /* result of lost transaction logs: */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenview_sync_set_log_view_range(struct mail_index_view *view, bool sync_expunges,
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainen const struct mail_index_header *hdr = &view->index->map->hdr;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* the view begins from the first non-synced transaction */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen ret = mail_transaction_log_view_set(view->log_view,
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen /* log was reset, but we don't want to sync expunges.
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen we can't do this, so sync only up to the reset. */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen mail_transaction_log_view_get_prev_pos(view->log_view,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* we have only this reset log */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen mail_transaction_log_view_clear(view->log_view,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic unsigned int
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainenview_sync_expunges2seqs(struct mail_index_view_sync_ctx *ctx)
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainen /* convert UIDs to sequences */
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainen src = dest = array_get_modifiable(&ctx->expunges, &count);
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainen if (!mail_index_lookup_seq_range(view, src->seq1, src->seq2,
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainenview_sync_add_expunge_range(ARRAY_TYPE(seq_range) *dest,
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainen unsigned int i, src_count;
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainen for (i = 0; i < src_count; i++)
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainen seq_range_array_add_range(dest, src[i].seq1, src[i].seq2);
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainenview_sync_add_expunge_guids(ARRAY_TYPE(seq_range) *dest,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const struct mail_transaction_expunge_guid *src,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen unsigned int i, src_count;
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainen for (i = 0; i < src_count; i++)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenview_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainen /* get a list of expunge transactions. there may be some that we have
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainen already synced, but it doesn't matter because they'll get dropped
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainen out when converting to sequences. the uid ranges' validity has
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainen already been verified, so we can use them directly. */
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainen mail_transaction_log_view_mark(view->log_view);
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainen /* skip expunge requests */
447bf65ddb82ec279e7386828748ef47e199a6afTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE_GUID) != 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen } else if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen mail_transaction_log_view_rewind(view->log_view);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen *expunge_count_r = view_sync_expunges2seqs(ctx);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic bool have_existing_expunges(struct mail_index_view *view,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (mail_index_lookup_seq_range(view, range->seq1, range->seq2,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenhave_existing_guid_expunge(struct mail_index_view *view,
5733207dc3ec10e6e5a6e0a8b30fbd1b061062b9Timo Sirainen const struct mail_transaction_expunge_guid *expunges,
5733207dc3ec10e6e5a6e0a8b30fbd1b061062b9Timo Sirainen const struct mail_transaction_expunge_guid *expunges_end;
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen expunges_end = CONST_PTR_OFFSET(expunges, size);
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen for (; expunges != expunges_end; expunges++) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (mail_index_lookup_seq(view, expunges->uid, &seq))
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainenstatic bool view_sync_have_expunges(struct mail_index_view *view)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen mail_transaction_log_view_mark(view->log_view);
5733207dc3ec10e6e5a6e0a8b30fbd1b061062b9Timo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* skip expunge requests */
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE_GUID) != 0) {
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen /* we have an expunge. see if it still exists. */
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen if (have_existing_expunges(view, data, hdr->size)) {
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen } else if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
5733207dc3ec10e6e5a6e0a8b30fbd1b061062b9Timo Sirainen /* we have an expunge. see if it still exists. */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (have_existing_guid_expunge(view, data, hdr->size)) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen mail_transaction_log_view_rewind(view->log_view);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* handle failures as having expunges (which is safer).
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen we'll probably fail later. */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic int uint_cmp(const void *p1, const void *p2)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic bool view_sync_lost_keywords_equal(struct mail_index_view_sync_ctx *ctx)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen old_idx = array_get_modifiable(&ctx->lost_old_kw, &old_count);
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen new_idx = array_get_modifiable(&ctx->lost_new_kw, &new_count);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen qsort(old_idx, old_count, sizeof(*old_idx), uint_cmp);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen qsort(new_idx, new_count, sizeof(*new_idx), uint_cmp);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return memcmp(old_idx, new_idx, old_count * sizeof(old_idx)) == 0;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic int view_sync_update_keywords(struct mail_index_view_sync_ctx *ctx,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const unsigned int *kw_idx;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const char *const *kw_names;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen unsigned int i, count;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen kw_idx = array_get(&ctx->lost_new_kw, &count);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen kw_names = array_idx(&ctx->view->index->keywords, 0);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen thdr.type = MAIL_TRANSACTION_KEYWORD_UPDATE | MAIL_TRANSACTION_EXTERNAL;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* add new flags one by one */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen for (i = 0; i < count; i++) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen kw_up.name_size = strlen(kw_names[kw_idx[i]]);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen buffer_append(ctx->lost_kw_buf, &kw_up, sizeof(kw_up));
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen buffer_append(ctx->lost_kw_buf, kw_names[kw_idx[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;
MAIL_TRANSACTION_EXPUNGE_GUID)) != 0 &&
return FALSE;
return FALSE;
return FALSE;
return TRUE;
int ret;
bool synced_to_map;
if (ret <= 0) {
if (ret < 0)
MAIL_TRANSACTION_EXPUNGE_GUID)) == 0) {
T_BEGIN {
} 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)