mail-index-view-sync.c revision d39c0e195c67be5f2b0a15f25a8d6039bef02711
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher/* Copyright (C) 2003-2004 Timo Sirainen */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagher#include "lib.h"
33396dc46ea52c18f47db1b5d590880806521005Sumit Bose#include "buffer.h"
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagher#include "mail-index-view-private.h"
33396dc46ea52c18f47db1b5d590880806521005Sumit Bose#include "mail-index-sync-private.h"
703dc1eb5b050b24235a6640f271d34ea008cf98Jan Engelhardt#include "mail-transaction-log.h"
703dc1eb5b050b24235a6640f271d34ea008cf98Jan Engelhardt#include "mail-transaction-util.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bosestruct mail_index_view_sync_ctx {
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bose struct mail_index_view *view;
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bose enum mail_transaction_type trans_sync_mask;
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bose struct mail_index_sync_map_ctx sync_map_ctx;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_t *expunges;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher const struct mail_transaction_header *hdr;
e65df5b966b27e13283c65f59f99ac44781e0333Simo Sorce const void *data;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
002f84aea86371aa079b867c0ec39396b97109d3Lukas Slebodnik size_t data_offset;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int skipped_some:1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int last_read:1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int sync_map_update:1;
87d3b47abba6a40fcf809c85a2b138bc1013d9c5Jakub Hrozek};
87d3b47abba6a40fcf809c85a2b138bc1013d9c5Jakub Hrozek
deeadf40db3a1eec64cf030e54afc4cb8612a8d5Lukas Slebodnikstruct mail_index_view_log_sync_pos {
ccf340e56364851f2e5b75e52d3d63701b662954Lukas Slebodnik uint32_t log_file_seq;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uoff_t log_file_offset;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher};
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagherstatic int
cc98edd9479d4622634a1275c98058916c14059aStephen Gallagherview_sync_get_expunges(struct mail_index_view *view, buffer_t **expunges_r)
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagher{
cc98edd9479d4622634a1275c98058916c14059aStephen Gallagher const struct mail_transaction_header *hdr;
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březina struct mail_transaction_expunge *src, *src_end, *dest;
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březina const void *data;
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březina size_t size;
c481179da5d5b53ce16d8784c0bd2857ffc2f061Lukas Slebodnik int ret;
1183d29d87c5c7439cf2364b7d7324d4a13b6e35Stephen Gallagher
002f84aea86371aa079b867c0ec39396b97109d3Lukas Slebodnik if (mail_transaction_log_view_set(view->log_view,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher view->log_file_seq,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher view->log_file_offset,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher view->index->hdr->log_file_seq,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher view->index->hdr->log_file_int_offset,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MAIL_TRANSACTION_EXPUNGE) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *expunges_r = buffer_create_dynamic(default_pool, 512);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher while ((ret = mail_transaction_log_view_next(view->log_view,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher &hdr, &data, NULL)) > 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0);
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce mail_transaction_log_sort_expunges(*expunges_r,
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce data, hdr->size);
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce }
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek if (ret < 0) {
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek buffer_free(*expunges_r);
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce *expunges_r = NULL;
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce return -1;
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek }
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek /* convert to sequences */
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek src = dest = buffer_get_modifyable_data(*expunges_r, &size);
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek src_end = PTR_OFFSET(src, size);
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek for (; src != src_end; src++) {
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek ret = mail_index_lookup_uid_range(view, src->uid1,
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek src->uid2,
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek &dest->uid1,
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek &dest->uid2);
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek i_assert(ret == 0);
48130eef6c5c64a07094b9e8582ba358b2048f24Jakub Hrozek
48130eef6c5c64a07094b9e8582ba358b2048f24Jakub Hrozek if (dest->uid1 == 0)
48130eef6c5c64a07094b9e8582ba358b2048f24Jakub Hrozek size -= sizeof(*dest);
48130eef6c5c64a07094b9e8582ba358b2048f24Jakub Hrozek else
1658c567191c35beaddffafdb079abe33248037bLukas Slebodnik dest++;
1658c567191c35beaddffafdb079abe33248037bLukas Slebodnik }
1658c567191c35beaddffafdb079abe33248037bLukas Slebodnik buffer_set_used_size(*expunges_r, size);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#define MAIL_INDEX_VIEW_VISIBLE_SYNC_MASK \
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (MAIL_TRANSACTION_EXPUNGE | MAIL_TRANSACTION_APPEND | \
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MAIL_TRANSACTION_FLAG_UPDATE | MAIL_TRANSACTION_KEYWORD_UPDATE | \
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MAIL_TRANSACTION_KEYWORD_RESET)
d921c1eba437662437847279f251a0a5d8f70127Maxim
d921c1eba437662437847279f251a0a5d8f70127Maximint mail_index_view_sync_begin(struct mail_index_view *view,
d921c1eba437662437847279f251a0a5d8f70127Maxim enum mail_index_sync_type sync_mask,
d921c1eba437662437847279f251a0a5d8f70127Maxim struct mail_index_view_sync_ctx **ctx_r)
d921c1eba437662437847279f251a0a5d8f70127Maxim{
d921c1eba437662437847279f251a0a5d8f70127Maxim const struct mail_index_header *hdr;
d921c1eba437662437847279f251a0a5d8f70127Maxim struct mail_index_view_sync_ctx *ctx;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer struct mail_index_map *map;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer enum mail_transaction_type mask, want_mask;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer buffer_t *expunges = NULL;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer /* We must sync flags as long as view is mmap()ed, as the flags may
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer have already changed under us. */
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer i_assert((sync_mask & MAIL_INDEX_SYNC_TYPE_FLAGS) != 0);
327127bb7fcc07f882209f029e14026de1b23c94Maxim i_assert(!view->syncing);
327127bb7fcc07f882209f029e14026de1b23c94Maxim i_assert(view->transactions == 0);
327127bb7fcc07f882209f029e14026de1b23c94Maxim
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail_index_view_lock_head(view, TRUE) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher hdr = view->index->hdr;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* get list of all expunges first */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (view_sync_get_expunges(view, &expunges) < 0)
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce return -1;
bc9235cfb80bd64a3bfa959e8d26d5ad1be0bdf4Jakub Hrozek }
bc9235cfb80bd64a3bfa959e8d26d5ad1be0bdf4Jakub Hrozek
07d82f79d2970a08628ebf71343441ec55faa6faPavel Březina /* only flags, appends and expunges can be left to be synced later */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher want_mask = mail_transaction_type_mask_get(sync_mask);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert((want_mask & ~MAIL_INDEX_VIEW_VISIBLE_SYNC_MASK) == 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mask = want_mask |
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (MAIL_TRANSACTION_TYPE_MASK ^
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MAIL_INDEX_VIEW_VISIBLE_SYNC_MASK);
4b6a0d0b3d42e5fdb457f47d9adfa5e66b160256Stephen Gallagher
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose if (mail_transaction_log_view_set(view->log_view,
03713859dffacc7142393e53c73d8d4cf7dee8d5Pavel Březina view->log_file_seq,
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik view->log_file_offset,
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik hdr->log_file_seq,
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke hdr->log_file_int_offset, mask) < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (expunges != NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_free(expunges);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
772464c842968d6e544118ae1aa7c49a7cda2ad6Stephen Gallagher
32381402a4a9afc003782c9e2301fc59c9bda2a9Yassir Elley ctx = i_new(struct mail_index_view_sync_ctx, 1);
068dbee9ca7bf5b37330eff91c94ae10f288d09fJakub Hrozek ctx->view = view;
98ce3c3e85a4bb2e1822bf8ab2a1c2ab9e3dd61dJakub Hrozek ctx->trans_sync_mask = want_mask;
be65f065fef1d387281096ef095a2acef39ecc12Jakub Hrozek ctx->expunges = expunges;
e124844907ed6973915e4d56f5442ecd07535a12Jakub Hrozek mail_index_sync_map_init(&ctx->sync_map_ctx, view,
f36078af138f052cd9a30360867b0ebd0805af5eJakub Hrozek MAIL_INDEX_SYNC_HANDLER_VIEW);
34c78b745eb349eef2b0f13ef2b722632aebe619Jan Cholasta
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0 &&
e07a94a66985b674c5df11ca466792902164c4e2George McCollister (sync_mask & MAIL_INDEX_SYNC_TYPE_APPEND) != 0) {
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek view->new_map = view->index->map;
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik view->new_map->refcount++;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer /* keep the old mapping without expunges until we're
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose fully synced */
bc13c352ba9c2877f1e9bc62e55ad60fc000a55dJakub Hrozek } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* we need a private copy of the map if we don't want to
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher sync expunges. we need to sync mapping only if we're not
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher using the latest one. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uint32_t old_records_count = view->map->records_count;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (view->map != view->index->map) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(view->map->records_count >=
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher view->hdr.messages_count);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher view->map->records_count = view->hdr.messages_count;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->sync_map_update = TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher map = mail_index_map_clone(view->map,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher view->map->hdr.record_size);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher view->map->records_count = old_records_count;
a5077712fc8c24e8cad08207b7b5a6603bde6a7cJakub Hrozek mail_index_unmap(view->index, view->map);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher view->map = map;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ctx->sync_map_update) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (map->hdr_base != map->hdr_copy_buf->data) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_reset(map->hdr_copy_buf);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_append(map->hdr_copy_buf, map->hdr_base,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher map->hdr.header_size);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher map->hdr_base = map->hdr_copy_buf->data;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose /* start from our old view's header. */
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke buffer_write(map->hdr_copy_buf, 0,
6b0a7c72bb841d6885a620c68bd51d55109b66c7Jakub Hrozek &view->hdr, sizeof(view->hdr));
9917c138d9a270deb5820915384fbde751190c2aLukas Slebodnik map->hdr = view->hdr;
0e1dcef53d9d8465ce97d31ad11be4445a6e7eb8Lukas Slebodnik }
c3889e5a101a075defe533d81f5296d5e680f639Lukas Slebodnik
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina i_assert(map->records_count == map->hdr.messages_count);
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer }
40b2be4f4312470044cdef460b02b66003f5c85fJakub Hrozek
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek mail_index_view_unref_maps(view);
9d453f1e8b28983b363b44c49b7cd701a994fd97Nikolai Kondrashov view->syncing = TRUE;
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina *ctx_r = ctx;
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina return 0;
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina}
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagherstatic int view_is_transaction_synced(struct mail_index_view *view,
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher uint32_t seq, uoff_t offset)
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik{
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik const struct mail_index_view_log_sync_pos *pos, *end;
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik size_t size;
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik if (view->log_syncs == NULL)
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik return 0;
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher pos = buffer_get_data(view->log_syncs, &size);
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik end = CONST_PTR_OFFSET(pos, size);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
539b1be3507abdf8ac235b06eeed5011b0b5cde2Ondrej Kos for (; pos != end; pos++) {
539b1be3507abdf8ac235b06eeed5011b0b5cde2Ondrej Kos if (pos->log_file_offset == offset && pos->log_file_seq == seq)
574a1c20f114851071ae74112b34488c3d1aeeb3Ondrej Kos return 1;
574a1c20f114851071ae74112b34488c3d1aeeb3Ondrej Kos }
574a1c20f114851071ae74112b34488c3d1aeeb3Ondrej Kos
574a1c20f114851071ae74112b34488c3d1aeeb3Ondrej Kos return 0;
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek}
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozek
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozekstatic int mail_index_view_sync_next_trans(struct mail_index_view_sync_ctx *ctx,
9542512d7be40f2000298c86d3d2b728f4f0f65aStephen Gallagher uint32_t *seq_r, uoff_t *offset_r)
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozek{
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek struct mail_transaction_log_view *log_view = ctx->view->log_view;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail_index_view *view = ctx->view;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int ret, skipped;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = mail_transaction_log_view_next(log_view, &ctx->hdr, &ctx->data,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher &skipped);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret <= 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->hdr = NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->last_read = TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (skipped)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->skipped_some = TRUE;
b50dffea929ee5cd0c59ba3c4822337cc162ff92Kamil Dudka
b50dffea929ee5cd0c59ba3c4822337cc162ff92Kamil Dudka mail_transaction_log_view_get_prev_pos(log_view, seq_r, offset_r);
b50dffea929ee5cd0c59ba3c4822337cc162ff92Kamil Dudka
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* skip flag changes that we committed ourself or have already synced */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (view_is_transaction_synced(view, *seq_r, *offset_r))
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek return 0;
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* expunges have to be synced afterwards so that caller can still get
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek information of the messages. otherwise caller most likely wants to
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek see only updated information. */
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek if (ctx->sync_map_update &&
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek (ctx->hdr->type & MAIL_TRANSACTION_EXPUNGE) == 0) {
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek if (mail_index_sync_record(&ctx->sync_map_ctx, ctx->hdr,
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek ctx->data) < 0)
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek return -1;
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek }
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek if ((ctx->hdr->type & ctx->trans_sync_mask) == 0)
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek return 0;
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek return 1;
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek}
6f51c802311fd81a409a26763ed45b28a3234d0dJakub Hrozek
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek#define FLAG_UPDATE_IS_INTERNAL(u) \
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ((((u)->add_flags | (u)->remove_flags) & \
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek ~(MAIL_INDEX_MAIL_FLAG_DIRTY | MAIL_RECENT)) == 0)
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher
f5b6f977d4144c28e9c66f3f1c9d634d595d1117Marko Myllynenstatic int
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghermail_index_view_sync_get_rec(struct mail_index_view_sync_ctx *ctx,
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik struct mail_index_sync_rec *rec)
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik{
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik const struct mail_transaction_header *hdr = ctx->hdr;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik const void *data = ctx->data;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik case MAIL_TRANSACTION_APPEND: {
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik rec->type = MAIL_INDEX_SYNC_TYPE_APPEND;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik rec->uid1 = rec->uid2 = 0;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik ctx->data_offset += hdr->size;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik break;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik }
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik case MAIL_TRANSACTION_EXPUNGE: {
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik const struct mail_transaction_expunge *exp =
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik CONST_PTR_OFFSET(data, ctx->data_offset);
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik ctx->data_offset += sizeof(*exp);
dc4c30bae512c0b45ff925d9e998337f8fe97e94Lukas Slebodnik mail_index_sync_get_expunge(rec, exp);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik break;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik case MAIL_TRANSACTION_FLAG_UPDATE: {
72e60fd4eabcfbcdbfe01e8c38b94052bc6c2067Jakub Hrozek const struct mail_transaction_flag_update *update =
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik CONST_PTR_OFFSET(data, ctx->data_offset);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik for (;;) {
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik ctx->data_offset += sizeof(*update);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik if (!FLAG_UPDATE_IS_INTERNAL(update))
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik break;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik if (ctx->data_offset == ctx->hdr->size)
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik return 0;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik update = CONST_PTR_OFFSET(data, ctx->data_offset);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_index_sync_get_update(rec, update);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik break;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik }
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik case MAIL_TRANSACTION_KEYWORD_UPDATE: {
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik const struct mail_transaction_keyword_update *update = data;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik const uint32_t *uids;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik if (ctx->data_offset == 0) {
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik ctx->data_offset = sizeof(*update) + update->name_size;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik if ((ctx->data_offset % 4) != 0)
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik ctx->data_offset += 4 - (ctx->data_offset % 4);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik }
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik uids = CONST_PTR_OFFSET(data, ctx->data_offset);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik /* FIXME: this isn't exactly correct.. but no-one cares? */
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik rec->type = MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik rec->uid1 = uids[0];
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik rec->uid2 = uids[1];
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik ctx->data_offset += sizeof(uint32_t) * 2;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik break;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik }
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik case MAIL_TRANSACTION_KEYWORD_RESET: {
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik const struct mail_transaction_keyword_reset *reset =
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik CONST_PTR_OFFSET(data, ctx->data_offset);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik rec->type = MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik rec->uid1 = reset->uid1;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik rec->uid2 = reset->uid2;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik ctx->data_offset += sizeof(*reset);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik break;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik }
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik default:
9d453f1e8b28983b363b44c49b7cd701a994fd97Nikolai Kondrashov i_unreached();
9d453f1e8b28983b363b44c49b7cd701a994fd97Nikolai Kondrashov }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
3d038d2e0dc7af04ec2f7c85ae325accb39f6237Jakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherint mail_index_view_sync_next(struct mail_index_view_sync_ctx *ctx,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail_index_sync_rec *sync_rec)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail_index_view *view = ctx->view;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uint32_t seq;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uoff_t offset;
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek int ret;
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek do {
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek if (ctx->hdr == NULL || ctx->data_offset == ctx->hdr->size) {
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek ctx->data_offset = 0;
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek do {
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek ret = mail_index_view_sync_next_trans(ctx, &seq,
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek &offset);
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek if (ret < 0)
e07a94a66985b674c5df11ca466792902164c4e2George McCollister return -1;
e07a94a66985b674c5df11ca466792902164c4e2George McCollister
e07a94a66985b674c5df11ca466792902164c4e2George McCollister if (ctx->last_read)
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose return 0;
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose if (!ctx->skipped_some) {
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose view->log_file_seq = seq;
172c07013d1ea99447a780fd36f49d5c3a76981bJakub Hrozek view->log_file_offset = offset +
9917c138d9a270deb5820915384fbde751190c2aLukas Slebodnik sizeof(*ctx->hdr) +
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->hdr->size;
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce }
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce } while (ret == 0);
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce if (ctx->skipped_some) {
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce mail_index_view_add_synced_transaction(view,
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce seq,
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce offset);
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce }
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce }
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce } while (!mail_index_view_sync_get_rec(ctx, sync_rec));
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce
336879aabae137f9a81304f147fb0d43001654b0Simo Sorce return 1;
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik}
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnikconst uint32_t *
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnikmail_index_view_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik size_t *count_r)
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik{
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik const uint32_t *data;
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik size_t size;
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik data = buffer_get_data(ctx->expunges, &size);
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik *count_r = size / (sizeof(uint32_t)*2);
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik return data;
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik}
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnikvoid mail_index_view_sync_end(struct mail_index_view_sync_ctx *ctx)
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik{
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik struct mail_index_view *view = ctx->view;
aac071824f6c98003f30d49ab440c15b4b53692cLukas Slebodnik
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(view->syncing);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ctx->sync_map_update)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_index_sync_map_deinit(&ctx->sync_map_ctx);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (view->log_syncs != NULL && !ctx->skipped_some)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_set_used_size(view->log_syncs, 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!ctx->last_read && ctx->hdr != NULL &&
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->data_offset != ctx->hdr->size) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* we didn't sync everything */
1c7f25390572025baa6783ede14523e22fc73043Lukas Slebodnik view->inconsistent = TRUE;
40b2be4f4312470044cdef460b02b66003f5c85fJakub Hrozek }
40b2be4f4312470044cdef460b02b66003f5c85fJakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (view->new_map != NULL) {
9d453f1e8b28983b363b44c49b7cd701a994fd97Nikolai Kondrashov mail_index_unmap(view->index, view->map);
9d453f1e8b28983b363b44c49b7cd701a994fd97Nikolai Kondrashov view->map = view->new_map;
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher view->new_map = NULL;
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher view->hdr = view->map->hdr;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (void)mail_transaction_log_view_set(view->log_view,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher view->log_file_seq,
96c73559adfbdac96720008fc022cb1d540b53c3Jakub Hrozek view->log_file_offset,
9542512d7be40f2000298c86d3d2b728f4f0f65aStephen Gallagher view->log_file_seq,
428db8a58c0c149d5efccc6d788f70916c1d34d7Jakub Hrozek view->log_file_offset,
9d453f1e8b28983b363b44c49b7cd701a994fd97Nikolai Kondrashov MAIL_TRANSACTION_TYPE_MASK);
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose if (ctx->expunges != NULL)
f1ce53a3b5656361557f80f61dfd42a371230c65Stephen Gallagher buffer_free(ctx->expunges);
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose view->syncing = FALSE;
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose i_free(ctx);
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina}
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina
f1ce53a3b5656361557f80f61dfd42a371230c65Stephen Gallaghervoid mail_index_view_add_synced_transaction(struct mail_index_view *view,
1a59af8245f183f22d87d067a90197d8e2ea958dJakub Hrozek uint32_t log_file_seq,
f1ce53a3b5656361557f80f61dfd42a371230c65Stephen Gallagher uoff_t log_file_offset)
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher{
struct mail_index_view_log_sync_pos pos;
memset(&pos, 0, sizeof(pos));
pos.log_file_seq = log_file_seq;
pos.log_file_offset = log_file_offset;
if (view->log_syncs == NULL)
view->log_syncs = buffer_create_dynamic(default_pool, 128);
buffer_append(view->log_syncs, &pos, sizeof(pos));
}