mail-index-sync.c revision e86d0d34fe365da4c7ca4312d575bfcbf3a01c0e
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn/* Copyright (C) 2003-2004 Timo Sirainen */
acbb59f50d5196facde837ea377f70e98ce1e6f8Serge Hallyn const struct mail_transaction_flag_update *src,
acbb59f50d5196facde837ea377f70e98ce1e6f8Serge Hallyn const struct mail_transaction_flag_update *src_end;
acbb59f50d5196facde837ea377f70e98ce1e6f8Serge Hallyn struct mail_transaction_flag_update new_update, tmp_update;
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser dest = buffer_get_modifyable_data(dest_buf, &dest_count);
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn /* insert it into buffer, split and merge it with existing
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn updates if needed. */
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn for (; i < dest_count; i++) {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn /* at least partially overlapping */
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn /* { 5..6 } + { 1..5 } -> { 1..4 } + { 5..6 } */
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn buffer_insert(dest_buf, i * sizeof(tmp_update),
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn /* { 5..7 } + { 6..6 } ->
daaf41b36790bdaae855048e56ed090b17a77c97Stéphane Graber split old to { 5..5 } + { 6..7 } */
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn buffer_insert(dest_buf, i * sizeof(tmp_update),
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn /* { 5..7 } + { 5..6 } -> { 5..6 } + { 7..7 } */
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser /* full match, or continues. */
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn /* dest[i] now contains the overlapping area.
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn merge them - new_update overrides old changes. */
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn dest[i].remove_flags |= new_update.remove_flags;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn for (j = 0; j < INDEX_KEYWORDS_BYTE_COUNT; j++) {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn buffer_insert(dest_buf, i * sizeof(new_update),
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn dest = buffer_get_modifyable_data(dest_buf, NULL);
57d116ab501594c2e50ab45f1cf2fae48c5eab09Serge Hallynstatic void mail_index_sync_sort_transaction(struct mail_index_sync_ctx *ctx)
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn switch (ctx->hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
80a881b232b8955b85b360d4def99e6e680ff61bSerge Hallyn mail_transaction_log_sort_expunges(ctx->expunges_buf,
4d7bcfb638c5c4907e8539aa09d41bb1de08a097Serge Hallyn mail_index_sync_sort_flags(ctx->updates_buf, ctx->data,
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn const struct mail_index_record *rec = ctx->data;
42ff5f0f8767114d060f5031055038a1a1c3759aSerge Hallynstatic int mail_index_sync_add_dirty_updates(struct mail_index_sync_ctx *ctx)
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn messages_count = mail_index_view_get_message_count(ctx->view);
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn if (mail_index_lookup(ctx->view, seq, &rec) < 0)
840295ff4cf11da0938a19f99fef8a1525de8106Stéphane Graber if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) == 0)
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn for (i = 0; i < INDEX_KEYWORDS_BYTE_COUNT; i++)
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn update.remove_keywords[i] = ~update.add_keywords[i];
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallynstatic int mail_index_sync_add_recent_updates(struct mail_index_sync_ctx *ctx)
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser messages_count = mail_index_view_get_message_count(ctx->view);
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser if (mail_index_lookup(ctx->view, seq, &rec) < 0)
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn /* group updates together as much as possible */
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber mail_index_sync_sort_flags(ctx->updates_buf,
4759162d078d86628956cae4846c6efccf548e67Serge Hallynmail_index_sync_read_and_sort(struct mail_index_sync_ctx *ctx, int sync_recent,
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn if ((ctx->view->map->hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) &&
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn /* show dirty flags as flag updates */
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn if (mail_index_sync_add_dirty_updates(ctx) < 0)
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser if (mail_index_sync_add_recent_updates(ctx) < 0)
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser while ((ret = mail_transaction_log_view_next(ctx->view->log_view,
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn if ((ctx->hdr->type & MAIL_TRANSACTION_EXTERNAL) != 0)
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser ctx->expunges = buffer_get_data(ctx->expunges_buf, &size);
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser ctx->expunges_count = size / sizeof(*ctx->expunges);
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn ctx->updates = buffer_get_data(ctx->updates_buf, &size);
52c8f624b5f9ef665f33a7aa80e0aa18b91daa4aSerge Hallyn ctx->updates_count = size / sizeof(*ctx->updates);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallynstatic int mail_index_need_lock(struct mail_index *index, int sync_recent,
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber if (sync_recent && index->hdr->recent_messages_count > 0)
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber (index->hdr->log_file_seq == log_file_seq &&
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber index->hdr->log_file_int_offset >= log_file_offset &&
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber index->hdr->log_file_ext_offset >= log_file_offset)) {
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber /* already synced */
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber return mail_cache_need_compress(index->cache);
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graberstatic int mail_index_sync_commit_external(struct mail_index_sync_ctx *ctx,
8a63c0a9d9089e6365e5a696455476febed39d6aStéphane Graber while ((ret = mail_transaction_log_view_next(ctx->view->log_view,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if ((ctx->hdr->type & MAIL_TRANSACTION_EXTERNAL) != 0)
427bffc7a10c9015dc78ef52543f7b8cb9414359Serge Hallyn if (mail_transaction_log_view_set(ctx->view->log_view,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (mail_index_sync_update_index(ctx, TRUE) < 0)
1881820ae4ff9004beef1bf7f04553580840441dSerge Hallynint mail_index_sync_begin(struct mail_index *index,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn unsigned int lock_id;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (mail_transaction_log_sync_lock(index->log, &seq, &offset) < 0)
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Moser if (mail_index_lock_shared(index, TRUE, &lock_id) < 0) {
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn /* we may have synced our internal view more than what
b942e67226af9e690bd63ac440b99aedb6becbb3Scott Moser is synced in index. re-read the whole index if our
b942e67226af9e690bd63ac440b99aedb6becbb3Scott Moser sync seq/offset doesn't match what is in index's
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn /* the whole log file is synced already. */
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn i_assert(index->map->hdr.log_file_ext_offset == offset);
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn if (mail_transaction_log_view_set(ctx->view->log_view,
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn /* See if there are some external transactions which were
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn written to transaction log, but weren't yet committed to
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn index. commit them first to avoid conflicts with another
3eecde703e9ac3af788ac17357f378d6b6d7c658Serge Hallyn external sync.
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn This is mostly needed to make sure there won't be multiple
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn appends with same UIDs, because those would cause
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn transaction log to be marked corrupted.
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn Note that any internal transactions must not be committed
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn yet. They need to be synced with the real mailbox first. */
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn if (mail_index_sync_commit_external(ctx, seq, offset) < 0) {
f1ccde27c038e7fb7e538913505248b36ddd9e65Serge Hallyn if (mail_transaction_log_view_set(ctx->view->log_view,
57d116ab501594c2e50ab45f1cf2fae48c5eab09Serge Hallyn /* we need to have all the transactions sorted to optimize
57d116ab501594c2e50ab45f1cf2fae48c5eab09Serge Hallyn caller's mailbox access patterns */
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn ctx->expunges_buf = buffer_create_dynamic(default_pool, 1024);
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn ctx->updates_buf = buffer_create_dynamic(default_pool, 1024);
1aad9e44d65e7c20dabc4c99f57bcf532db66c68Serge Hallyn if (mail_index_sync_read_and_sort(ctx, sync_recent,
65d8ae9c4a66f5ca85289c02dc06d63261c84619Scott Mosermail_index_sync_get_expunge(struct mail_index_sync_rec *rec,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallynmail_index_sync_get_update(struct mail_index_sync_rec *rec,
b942e67226af9e690bd63ac440b99aedb6becbb3Scott Moser const struct mail_transaction_flag_update *update)
return FALSE;
return TRUE;
int ret = 0;
return ret;
for (i = 0; i < INDEX_KEYWORDS_BYTE_COUNT; i++) {