mail-index-transaction-finish.c revision 4860b8746b3b7846a9fe65b8c2907ba8aebd422f
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2003-2013 Dovecot authors, see the included COPYING file */
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
80c1d98d3638b71e57a39cafa88b9122bf8169c6Timo Sirainen#include "array.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-private.h"
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen#include "mail-index-modseq.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-transaction-private.h"
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenint mail_transaction_expunge_guid_cmp(const struct mail_transaction_expunge_guid *e1,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_transaction_expunge_guid *e2)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (e1->uid < e2->uid)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else if (e1->uid > e2->uid)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen return 0;
8887bf3757d51d73887dd20b1db3334d867d3817Timo Sirainen}
8887bf3757d51d73887dd20b1db3334d867d3817Timo Sirainen
369a1084c500a9df7448ffa9409ce32e42060bc2Timo Sirainenvoid mail_index_transaction_sort_expunges(struct mail_index_transaction *t)
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen{
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen if (!t->expunges_nonsorted)
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen return;
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen array_sort(&t->expunges, mail_transaction_expunge_guid_cmp);
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen t->expunges_nonsorted = FALSE;
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenext_reset_update_atomic(struct mail_index_transaction *t,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t ext_id, uint32_t expected_reset_id)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen const struct mail_index_ext *map_ext;
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen struct mail_transaction_ext_reset *reset;
6ec7cf71ccd0eed1f9cc1b0bda8960796b04160bTimo Sirainen uint32_t idx, reset_id;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!mail_index_map_get_ext_idx(t->view->index->map, ext_id, &idx)) {
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen /* new extension */
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen reset_id = 1;
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen } else {
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen map_ext = array_idx(&t->view->index->map->extensions, idx);
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen reset_id = map_ext->reset_id + 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (reset_id != expected_reset_id) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* ignore this extension update */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_ext_set_reset_id(t, ext_id, 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (reset_id == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen reset_id++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen array_idx_set(&t->ext_reset_ids, ext_id, &reset_id);
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen /* reseting existing data is optional */
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen if (array_is_created(&t->ext_resets)) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen reset = array_idx_modifiable(&t->ext_resets, ext_id);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (reset->new_reset_id == (uint32_t)-1)
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen reset->new_reset_id = reset_id;
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainentransaction_update_atomic_reset_ids(struct mail_index_transaction *t)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const uint32_t *expected_reset_ids;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int ext_id, count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen if (!array_is_created(&t->ext_reset_atomic))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen expected_reset_ids = array_get(&t->ext_reset_atomic, &count);
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen for (ext_id = 0; ext_id < count; ext_id++) {
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen if (expected_reset_ids[ext_id] != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ext_reset_update_atomic(t, ext_id,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen expected_reset_ids[ext_id]);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen}
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainenstatic unsigned int
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainenmail_transaction_drop_range(struct mail_index_transaction *t,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_flag_update update,
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen unsigned int update_idx,
2a734f36105e33ab452d057df6bc7a2b7d9f96f0Timo Sirainen ARRAY_TYPE(seq_range) *keeps)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen const struct seq_range *keep_range;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen unsigned int i, keep_count;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen keep_range = array_get(keeps, &keep_count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (keep_count == 1 &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen update.uid1 == keep_range[0].seq1 &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen update.uid2 == keep_range[0].seq2) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen /* evereything is kept */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return update_idx + 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_delete(&t->updates, update_idx, 1);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* add back all the updates we want to keep */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen for (i = 0; i < keep_count; i++, update_idx++) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen update.uid1 = keep_range[i].seq1;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen update.uid2 = keep_range[i].seq2;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_insert(&t->updates, update_idx, &update, 1);
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen }
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen return update_idx;
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen}
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainenstatic void
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainenmail_index_transaction_finish_flag_updates(struct mail_index_transaction *t)
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen{
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen const struct mail_index_flag_update *updates, *u;
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen const struct mail_index_record *rec;
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen unsigned int i, count;
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen ARRAY_TYPE(seq_range) keeps;
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen uint32_t seq;
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!t->drop_unnecessary_flag_updates || !array_is_created(&t->updates))
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen return;
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen t_array_init(&keeps, 64);
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen updates = array_get(&t->updates, &count);
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen for (i = 0; i < count; ) {
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen /* first get the list of changes to drop */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen u = &updates[i];
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen array_clear(&keeps);
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen for (seq = u->uid1; seq <= u->uid2; seq++) {
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen rec = mail_index_lookup(t->view, seq);
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen if ((rec->flags & u->add_flags) != u->add_flags ||
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen (rec->flags & u->remove_flags) != 0) {
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen /* keep this change */
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen seq_range_array_add(&keeps, seq);
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen }
d6a1fa1d65c6d1996937802c2482c0f14dd821a7Timo Sirainen }
d6a1fa1d65c6d1996937802c2482c0f14dd821a7Timo Sirainen i = mail_transaction_drop_range(t, updates[i], i, &keeps);
d6a1fa1d65c6d1996937802c2482c0f14dd821a7Timo Sirainen updates = array_get(&t->updates, &count);
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen }
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen
7761758f43d6150be4b07f4c54457ce662f78c4cTimo Sirainen if (array_count(&t->updates) == 0)
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen array_free(&t->updates);
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen}
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainenstatic void
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainenmail_index_transaction_check_conflicts(struct mail_index_transaction *t)
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen{
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen uint32_t seq;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen bool ret1, ret2;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainen i_assert(t->max_modseq != 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(t->conflict_seqs != NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (t->max_modseq == mail_index_modseq_get_highest(t->view)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* no conflicts possible */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (t->min_flagupdate_seq == 0) {
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen /* no flag updates */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen for (seq = t->min_flagupdate_seq; seq <= t->max_flagupdate_seq; seq++) {
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen if (mail_index_modseq_lookup(t->view, seq) > t->max_modseq) {
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen ret1 = mail_index_cancel_flag_updates(t, seq);
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen ret2 = mail_index_cancel_keyword_updates(t, seq);
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen if (ret1 || ret2) {
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen seq_range_array_add_with_init(t->conflict_seqs,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen 16, seq);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_transaction_set_log_updates(t);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic uint32_t
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenmail_index_transaction_get_uid(struct mail_index_transaction *t, uint32_t seq)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
80fc743146da5130de34174cdaad2576f103723fTimo Sirainen const struct mail_index_record *rec;
80fc743146da5130de34174cdaad2576f103723fTimo Sirainen
80fc743146da5130de34174cdaad2576f103723fTimo Sirainen i_assert(seq > 0);
80fc743146da5130de34174cdaad2576f103723fTimo Sirainen
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen if (seq >= t->first_new_seq)
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen rec = mail_index_transaction_lookup(t, seq);
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen else {
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen i_assert(seq <= t->view->map->hdr.messages_count);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen rec = MAIL_INDEX_MAP_IDX(t->view->map, seq - 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(rec->uid != 0);
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen return rec->uid;
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen}
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_index_convert_to_uids(struct mail_index_transaction *t,
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen ARRAY_TYPE(seq_array) *array)
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen{
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen uint32_t *seq;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen unsigned int i, count;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!array_is_created(array))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen count = array_count(array);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen for (i = 0; i < count; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen seq = array_idx_modifiable(array, i);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *seq = mail_index_transaction_get_uid(t, *seq);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic uint32_t
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenget_nonexpunged_uid2(struct mail_index_transaction *t,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t uid1, uint32_t seq1)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen seq1++;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen while (mail_index_transaction_get_uid(t, seq1) == uid1 + 1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen seq1++;
7c95b03620a03a43dd72d39608cea5fc77393ad6Timo Sirainen uid1++;
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return uid1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenstatic void
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainenmail_index_convert_to_uid_ranges(struct mail_index_transaction *t,
2674b4f0cf8f3c203d8e56b29735f5e267038dafTimo Sirainen ARRAY_TYPE(seq_range) *array)
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen{
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainen struct seq_range *range, *new_range;
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainen unsigned int i, count;
2674b4f0cf8f3c203d8e56b29735f5e267038dafTimo Sirainen uint32_t uid1, uid2, prev_uid = 0;
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen if (!array_is_created(array))
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen count = array_count(array);
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen for (i = 0; i < count; i++) {
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen range = array_idx_modifiable(array, i);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen uid1 = mail_index_transaction_get_uid(t, range->seq1);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen uid2 = mail_index_transaction_get_uid(t, range->seq2);
d6a1fa1d65c6d1996937802c2482c0f14dd821a7Timo Sirainen i_assert(uid1 > prev_uid);
d6a1fa1d65c6d1996937802c2482c0f14dd821a7Timo Sirainen if (uid2 - uid1 == range->seq2 - range->seq1) {
d6a1fa1d65c6d1996937802c2482c0f14dd821a7Timo Sirainen /* simple conversion */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen range->seq1 = uid1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen range->seq2 = uid2;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen prev_uid = uid2;
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen } else {
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen /* remove expunged UIDs */
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen new_range = array_insert_space(array, i);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen range = array_idx_modifiable(array, i + 1);
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen count++;
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memcpy(new_range, range, array->arr.element_size);
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen new_range->seq1 = uid1;
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen new_range->seq2 = get_nonexpunged_uid2(t, uid1,
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen range->seq1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(new_range->seq2 < uid2);
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen /* continue the range without the inserted seqs */
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen range->seq1 += new_range->seq2 - new_range->seq1 + 1;
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen prev_uid = new_range->seq2;
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen }
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen }
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void keyword_updates_convert_to_uids(struct mail_index_transaction *t)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
aa0647f2debf0d48d504a321186f66c85596aaf4Timo Sirainen struct mail_index_transaction_keyword_update *update;
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen if (!array_is_created(&t->keyword_updates))
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen return;
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen array_foreach_modifiable(&t->keyword_updates, update) {
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen mail_index_convert_to_uid_ranges(t, &update->add_seq);
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen mail_index_convert_to_uid_ranges(t, &update->remove_seq);
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen }
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen}
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainenstatic void expunges_convert_to_uids(struct mail_index_transaction *t)
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen{
768b7f5783c8de119d7386321e5d0c72d5c2d9f6Timo Sirainen struct mail_transaction_expunge_guid *expunges;
768b7f5783c8de119d7386321e5d0c72d5c2d9f6Timo Sirainen unsigned int src, dest, count;
768b7f5783c8de119d7386321e5d0c72d5c2d9f6Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!array_is_created(&t->expunges))
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen return;
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen mail_index_transaction_sort_expunges(t);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
89caf81340a4da959ef18c5f9b9c99824a53066bTimo Sirainen expunges = array_get_modifiable(&t->expunges, &count);
89caf81340a4da959ef18c5f9b9c99824a53066bTimo Sirainen if (count == 0)
89caf81340a4da959ef18c5f9b9c99824a53066bTimo Sirainen return;
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* convert uids and drop duplicates */
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen expunges[0].uid = mail_index_transaction_get_uid(t, expunges[0].uid);
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen for (src = dest = 1; src < count; src++) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen expunges[dest].uid =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_transaction_get_uid(t, expunges[src].uid);
685393de106e55b61f754d420e378d05bd462ebbTimo Sirainen if (expunges[dest-1].uid != expunges[dest].uid) {
87712707722ef7d73acb065546e61afa4455cd9eTimo Sirainen if (dest != src) {
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen memcpy(expunges[dest].guid_128, expunges[src].guid_128,
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen sizeof(expunges[dest].guid_128));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen dest++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen array_delete(&t->expunges, dest, count-dest);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
7761758f43d6150be4b07f4c54457ce662f78c4cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainenmail_index_transaction_convert_to_uids(struct mail_index_transaction *t)
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen{
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen ARRAY_TYPE(seq_array) *update;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen if (array_is_created(&t->ext_rec_updates)) {
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen array_foreach_modifiable(&t->ext_rec_updates, update)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_convert_to_uids(t, update);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainen if (array_is_created(&t->ext_rec_atomics)) {
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainen array_foreach_modifiable(&t->ext_rec_atomics, update)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen mail_index_convert_to_uids(t, update);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen }
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen keyword_updates_convert_to_uids(t);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen expunges_convert_to_uids(t);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen mail_index_convert_to_uids(t, (void *)&t->modseq_updates);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen mail_index_convert_to_uid_ranges(t, (void *)&t->updates);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen}
bb26f09873c18f342cd1ab2d0ee0b9018e6546d9Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenvoid mail_index_transaction_finish(struct mail_index_transaction *t)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (array_is_created(&t->appends)) {
b5ea11802f2bafbec06282a7b3b6704dc5fae584Timo Sirainen mail_index_update_day_headers(t);
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen mail_index_transaction_sort_appends(t);
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen }
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen mail_index_transaction_finish_flag_updates(t);
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen if (array_is_created(&t->ext_reset_atomic))
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen transaction_update_atomic_reset_ids(t);
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen if (t->max_modseq != 0)
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen mail_index_transaction_check_conflicts(t);
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen /* finally convert all sequences to UIDs before we write them,
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen but after we've checked and removed conflicts */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_transaction_convert_to_uids(t);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen /* and kind of ugly way to update highest modseq */
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen if (t->min_highest_modseq != 0)
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen mail_index_update_modseq(t, 0, t->min_highest_modseq);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen