mail-index-view-sync.c revision d6f50f100ce17fa4b3a89e9567a5ff993b38b872
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (C) 2003-2004 Timo Sirainen */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "lib.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "buffer.h"
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen#include "mail-index-view-private.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "mail-index-sync-private.h"
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen#include "mail-transaction-log.h"
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "mail-transaction-util.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenstruct mail_index_view_sync_ctx {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct mail_index_view *view;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen enum mail_transaction_type trans_sync_mask;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen buffer_t *expunges;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen const struct mail_transaction_header *hdr;
bd63b5b860658b01b1f46f26d406e1e4a9dc019aTimo Sirainen const void *data;
cd2cd224d3216a243d55c71c298a5b7684de0ac4Timo Sirainen
cd2cd224d3216a243d55c71c298a5b7684de0ac4Timo Sirainen size_t data_offset;
c1faff067b29fb48426cb84260adba563e93189aTimo Sirainen unsigned int skipped_some:1;
f6c1297c26b355c4aec2a08978f51ec3efecb351Timo Sirainen unsigned int last_read:1;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen unsigned int sync_map_update:1;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen};
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainenstatic int
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainenview_sync_get_expunges(struct mail_index_view *view, buffer_t **expunges_r)
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen{
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen const struct mail_transaction_header *hdr;
ef2b2ef2e6a6eb5e4667f2e63faae8a3b646e8baTimo Sirainen struct mail_transaction_expunge *src, *src_end, *dest;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen const void *data;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen size_t size;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen int ret;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen *expunges_r = buffer_create_dynamic(default_pool, 512, (size_t)-1);
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen /* with mask 0 we don't get anything, we'll just read the expunges
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen while seeking to end */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (mail_transaction_log_view_set(view->log_view,
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen view->log_file_seq,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen view->log_file_offset,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen view->index->hdr->log_file_seq,
f162f350e1eacce12288a565657e769d7976dd7fTimo Sirainen view->index->hdr->log_file_offset,
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainen MAIL_TRANSACTION_EXPUNGE) < 0)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return -1;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen &hdr, &data, NULL)) > 0) {
44f93baa7b8dca7d00bf187cd3db1c15eed384d2Timo Sirainen mail_transaction_log_sort_expunges(*expunges_r,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen data, hdr->size);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
f162f350e1eacce12288a565657e769d7976dd7fTimo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (ret == 0) {
4ea6c43a08b37f270bd54b5809142246fd118263Timo Sirainen /* convert to sequences */
bf9ea5404a0094a8fb8199b677d81f803512c44eTimo Sirainen src = dest = buffer_get_modifyable_data(*expunges_r, &size);
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainen src_end = src + size / sizeof(*src);
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen for (; src != src_end; src++) {
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainen ret = mail_index_lookup_uid_range(view, src->uid1,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen src->uid2,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen &dest->uid1,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen &dest->uid2);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen i_assert(ret == 0);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
4ea6c43a08b37f270bd54b5809142246fd118263Timo Sirainen if (dest->uid1 == 0)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen size -= sizeof(*dest);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen else
bffaca7da2825c2a77aa46022358e2f8400a0f94Timo Sirainen dest++;
f162f350e1eacce12288a565657e769d7976dd7fTimo Sirainen }
f162f350e1eacce12288a565657e769d7976dd7fTimo Sirainen buffer_set_used_size(*expunges_r, size);
bffaca7da2825c2a77aa46022358e2f8400a0f94Timo Sirainen } else {
bffaca7da2825c2a77aa46022358e2f8400a0f94Timo Sirainen buffer_set_used_size(*expunges_r, 0);
f162f350e1eacce12288a565657e769d7976dd7fTimo Sirainen }
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return ret;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#define MAIL_INDEX_VIEW_VISIBLE_SYNC_MASK \
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen (MAIL_TRANSACTION_EXPUNGE | MAIL_TRANSACTION_APPEND | \
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen MAIL_TRANSACTION_FLAG_UPDATE)
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenint mail_index_view_sync_begin(struct mail_index_view *view,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen enum mail_index_sync_type sync_mask,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct mail_index_view_sync_ctx **ctx_r)
7d87a87b360ecac47fe10e7ca5c7e1433dd63004Timo Sirainen{
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen const struct mail_index_header *hdr;
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen struct mail_index_view_sync_ctx *ctx;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct mail_index_map *map;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen enum mail_transaction_type mask, want_mask;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen buffer_t *expunges = NULL;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
7d87a87b360ecac47fe10e7ca5c7e1433dd63004Timo Sirainen /* We must sync flags as long as view is mmap()ed, as the flags may
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen have already changed under us. */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen i_assert((sync_mask & MAIL_INDEX_SYNC_TYPE_FLAGS) != 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_assert(!view->syncing);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (mail_index_view_lock_head(view, TRUE) < 0)
ef2b2ef2e6a6eb5e4667f2e63faae8a3b646e8baTimo Sirainen return -1;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen hdr = view->index->hdr;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0) {
10ccd0e45768923d69be459e87ef6cd2574cec60Timo Sirainen /* get list of all expunges first */
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen if (view_sync_get_expunges(view, &expunges) < 0)
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen return -1;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
4145cbac82bfc0c8bfeceeca0ef841700117930cTimo Sirainen /* only flags, appends and expunges can be left to be synced later */
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen want_mask = mail_transaction_type_mask_get(sync_mask);
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen i_assert((want_mask & ~MAIL_INDEX_VIEW_VISIBLE_SYNC_MASK) == 0);
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen mask = want_mask |
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen (MAIL_TRANSACTION_TYPE_MASK ^
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen MAIL_INDEX_VIEW_VISIBLE_SYNC_MASK);
44f93baa7b8dca7d00bf187cd3db1c15eed384d2Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (mail_transaction_log_view_set(view->log_view,
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen view->log_file_seq,
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen view->log_file_offset,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen hdr->log_file_seq,
3f7583189249a28892cd5bd69e15681c7a8a619bTimo Sirainen hdr->log_file_offset, mask) < 0) {
3f7583189249a28892cd5bd69e15681c7a8a619bTimo Sirainen if (expunges != NULL)
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen buffer_free(expunges);
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen return -1;
44f93baa7b8dca7d00bf187cd3db1c15eed384d2Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen ctx = i_new(struct mail_index_view_sync_ctx, 1);
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen ctx->view = view;
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen ctx->trans_sync_mask = want_mask;
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen ctx->expunges = expunges;
e10d8b1291090c26b9ef499637e6e632485ca5beTimo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0) {
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen view->new_map = view->index->map;
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen view->new_map->refcount++;
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen /* keep the old mapping without expunges until we're
d337f4291d9ea9cd1adee0f468bc0c3baeabb4feTimo Sirainen fully synced */
d337f4291d9ea9cd1adee0f468bc0c3baeabb4feTimo Sirainen } else {
d337f4291d9ea9cd1adee0f468bc0c3baeabb4feTimo Sirainen /* we need a private copy of the map if we don't want to
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen sync expunges */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (view->map != view->index->map)
d337f4291d9ea9cd1adee0f468bc0c3baeabb4feTimo Sirainen ctx->sync_map_update = TRUE;
d337f4291d9ea9cd1adee0f468bc0c3baeabb4feTimo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen map = mail_index_map_to_memory(view->map,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen view->map->hdr->record_size);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen mail_index_unmap(view->index, view->map);
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen view->map = map;
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen }
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen view->syncing = TRUE;
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen *ctx_r = ctx;
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen return 0;
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen}
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainenstatic int view_is_transaction_synced(struct mail_index_view *view,
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen uint32_t seq, uoff_t offset)
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen{
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen const unsigned char *data, *end;
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen size_t size;
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen if (view->log_syncs == NULL)
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen return 0;
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen data = buffer_get_data(view->log_syncs, &size);
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen end = data + size;
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen for (; data < end; ) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (*((const uoff_t *)data) == offset &&
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen *((const uint32_t *)(data + sizeof(uoff_t))) == seq)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return 1;
10ccd0e45768923d69be459e87ef6cd2574cec60Timo Sirainen data += sizeof(uoff_t) + sizeof(uint32_t);
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return 0;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenstatic int mail_index_view_sync_next_trans(struct mail_index_view_sync_ctx *ctx,
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen uint32_t *seq_r, uoff_t *offset_r)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct mail_transaction_log_view *log_view = ctx->view->log_view;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct mail_index_view *view = ctx->view;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen int ret, skipped;
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen ret = mail_transaction_log_view_next(log_view, &ctx->hdr, &ctx->data,
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen &skipped);
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen if (ret <= 0) {
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen if (ret < 0)
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen return -1;
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen ctx->hdr = NULL;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen ctx->last_read = TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return 1;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (skipped)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen ctx->skipped_some = TRUE;
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen
c2fbbf7515aa419dc8b2d62a3c2bb0471d51a391Timo Sirainen mail_transaction_log_view_get_prev_pos(log_view, seq_r, offset_r);
c2fbbf7515aa419dc8b2d62a3c2bb0471d51a391Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen /* skip flag changes that we committed ourself or have already synced */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (view_is_transaction_synced(view, *seq_r, *offset_r))
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return 0;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen /* expunges have to be synced afterwards so that caller can still get
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen information of the messages. otherwise caller most likely wants to
c2fbbf7515aa419dc8b2d62a3c2bb0471d51a391Timo Sirainen see only updated information. */
c2fbbf7515aa419dc8b2d62a3c2bb0471d51a391Timo Sirainen if (ctx->sync_map_update &&
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen (ctx->hdr->type & MAIL_TRANSACTION_EXPUNGE) == 0) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct mail_index_sync_map_ctx sync_map_ctx;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen memset(&sync_map_ctx, 0, sizeof(sync_map_ctx));
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen sync_map_ctx.view = view;
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (mail_transaction_map(view->index, ctx->hdr, ctx->data,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen &mail_index_map_sync_funcs,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen &sync_map_ctx) < 0)
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen return -1;
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen }
2521fd0986302cdabc8b0711eef63ac188f32cd6Timo Sirainen
2521fd0986302cdabc8b0711eef63ac188f32cd6Timo Sirainen if ((ctx->hdr->type & ctx->trans_sync_mask) == 0)
2521fd0986302cdabc8b0711eef63ac188f32cd6Timo Sirainen return 0;
c2fbbf7515aa419dc8b2d62a3c2bb0471d51a391Timo Sirainen
c2fbbf7515aa419dc8b2d62a3c2bb0471d51a391Timo Sirainen return 1;
c2fbbf7515aa419dc8b2d62a3c2bb0471d51a391Timo Sirainen}
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#define FLAG_UPDATE_IS_INTERNAL(u, empty) \
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen (((u)->add_flags | (u)->remove_flags) == MAIL_INDEX_MAIL_FLAG_DIRTY && \
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen memcmp((u)->add_keywords, empty, INDEX_KEYWORDS_BYTE_COUNT) == 0 && \
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen memcmp((u)->add_keywords, empty, INDEX_KEYWORDS_BYTE_COUNT) == 0)
bf9ea5404a0094a8fb8199b677d81f803512c44eTimo Sirainen
bf9ea5404a0094a8fb8199b677d81f803512c44eTimo Sirainenstatic int
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenmail_index_view_sync_get_rec(struct mail_index_view_sync_ctx *ctx,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct mail_index_sync_rec *rec)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen static keywords_mask_t empty_keywords = { 0, };
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen const struct mail_transaction_header *hdr = ctx->hdr;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen const void *data = ctx->data;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen case MAIL_TRANSACTION_APPEND: {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_APPEND;
cd2cd224d3216a243d55c71c298a5b7684de0ac4Timo Sirainen rec->uid1 = rec->uid2 = 0;
2c719bcb92302f45df4badb71d1d97f57235d0ccTimo Sirainen ctx->data_offset += hdr->size;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen break;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen case MAIL_TRANSACTION_EXPUNGE: {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const struct mail_transaction_expunge *exp =
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen CONST_PTR_OFFSET(data, ctx->data_offset);
cd2cd224d3216a243d55c71c298a5b7684de0ac4Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen ctx->data_offset += sizeof(*exp);
66a872b4569c048e804f0731680d89c6042d8890Timo Sirainen mail_index_sync_get_expunge(rec, exp);
66a872b4569c048e804f0731680d89c6042d8890Timo Sirainen break;
66a872b4569c048e804f0731680d89c6042d8890Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen case MAIL_TRANSACTION_FLAG_UPDATE: {
cd2cd224d3216a243d55c71c298a5b7684de0ac4Timo Sirainen const struct mail_transaction_flag_update *update =
ac0fed903142d28ae3a1d5d00d2097fdf161b138Timo Sirainen CONST_PTR_OFFSET(data, ctx->data_offset);
ac0fed903142d28ae3a1d5d00d2097fdf161b138Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen for (;;) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen ctx->data_offset += sizeof(*update);
f8da06de93e28b5d3e039a427cdde7e1e15daec8Timo Sirainen if (!FLAG_UPDATE_IS_INTERNAL(update, empty_keywords))
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen break;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (ctx->data_offset == ctx->hdr->size)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return 0;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen mail_index_sync_get_update(rec, update);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen break;
23fdad6c7e2581921f511e24cd9371c9eaebcef9Timo Sirainen }
23fdad6c7e2581921f511e24cd9371c9eaebcef9Timo Sirainen default:
8552b0cad8ffe9ccb8270577ba28b8010c89af11Timo Sirainen i_unreached();
}
return 1;
}
int mail_index_view_sync_next(struct mail_index_view_sync_ctx *ctx,
struct mail_index_sync_rec *sync_rec)
{
struct mail_index_view *view = ctx->view;
uint32_t seq;
uoff_t offset;
int ret;
do {
if (ctx->hdr == NULL || ctx->data_offset == ctx->hdr->size) {
ctx->data_offset = 0;
do {
ret = mail_index_view_sync_next_trans(ctx, &seq,
&offset);
if (ret < 0)
return -1;
if (ctx->last_read)
return 0;
if (!ctx->skipped_some) {
view->log_file_seq = seq;
view->log_file_offset = offset +
sizeof(*ctx->hdr) +
ctx->hdr->size;
}
} while (ret == 0);
if (ctx->skipped_some) {
mail_index_view_add_synced_transaction(view,
seq,
offset);
}
}
} while (!mail_index_view_sync_get_rec(ctx, sync_rec));
return 1;
}
const uint32_t *
mail_index_view_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
size_t *count_r)
{
const uint32_t *data;
size_t size;
data = buffer_get_data(ctx->expunges, &size);
*count_r = size / (sizeof(uint32_t)*2);
return data;
}
void mail_index_view_sync_end(struct mail_index_view_sync_ctx *ctx)
{
struct mail_index_view *view = ctx->view;
i_assert(view->syncing);
if (view->log_syncs != NULL && !ctx->skipped_some)
buffer_set_used_size(view->log_syncs, 0);
if (!ctx->last_read && ctx->hdr != NULL &&
ctx->data_offset != ctx->hdr->size) {
/* we didn't sync everything */
view->inconsistent = TRUE;
}
if (view->new_map != NULL) {
mail_index_unmap(view->index, view->map);
view->map = view->new_map;
view->new_map = NULL;
view->map_protected = FALSE;
}
if ((ctx->trans_sync_mask & MAIL_TRANSACTION_APPEND) != 0)
view->messages_count = view->map->records_count;
(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 (ctx->expunges != NULL)
buffer_free(ctx->expunges);
view->syncing = FALSE;
i_free(ctx);
}
void mail_index_view_add_synced_transaction(struct mail_index_view *view,
uint32_t log_file_seq,
uoff_t log_file_offset)
{
if (view->log_syncs == NULL) {
view->log_syncs = buffer_create_dynamic(default_pool,
128, (size_t)-1);
}
buffer_append(view->log_syncs, &log_file_offset,
sizeof(log_file_offset));
buffer_append(view->log_syncs, &log_file_seq, sizeof(log_file_seq));
}